Skip to main content

Pulumi Ep 9: Pulumi Packages and the Registry

Rachmat Hidayat
Author
Rachmat Hidayat
Learn & sharing insights on TypeScript, Go, Kubernetes, DevOps, DevSecOps, SRE, Platform Engineering, AI/ML Engineering, and MLOps.
pulumi - This article is part of a series.
Part 9: This Article
If Pulumi could only communicate with AWS, it would be useless to the modern enterprise. The true power of IaC lies in its ability to orchestrate the entire software delivery lifecycle. Through the Pulumi Registry, you can install hundreds of official and community-built Providers to automate everything from DNS records to Kubernetes manifests.

1. The Pulumi Registry
#

The Pulumi Registry is the central repository for all Pulumi Providers. A Provider is simply a plugin that knows how to translate Pulumi’s internal JSON intent into the specific REST API calls required by a third-party service.

Because we are using TypeScript, Pulumi Providers are distributed as standard NPM packages.

To see what is available, search the Registry. You will find providers for:

  • Cloud Providers: AWS, Azure, Google Cloud, DigitalOcean.
  • Infrastructure Services: Cloudflare, Auth0, Datadog, PagerDuty.
  • Developer Tools: GitHub, GitLab, Docker, Kubernetes.

Installing a Provider
#

Let’s assume our team needs to provision an AWS EC2 instance, but we also need to create a GitHub repository for the application code.

First, we must install the GitHub Provider via NPM.

Run this in your terminal:

npm install @pulumi/github

That’s it. You do not need to edit a complex required_providers block like you do in Terraform. You just use standard package management.


2. Multi-Cloud Orchestration
#

Now that we have both @pulumi/aws and @pulumi/github installed, let’s write a multi-cloud orchestration script.

Open index.ts:

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as github from "@pulumi/github";

// 1. Create the AWS Infrastructure
const webServer = new aws.ec2.Instance("web-server", {
    ami: "ami-0fc5d935ebf8bc3bc",
    instanceType: "t3.micro",
});

// 2. Create the GitHub Repository
const appRepo = new github.Repository("app-source-code", {
    description: "The source code for the Web Server application",
    visibility: "private",
    hasIssues: true,
});

// 3. Orchestrate across clouds!
// We can pass the AWS Public IP as a GitHub Repository Secret!
const dbSecret = new github.ActionsSecret("api-url-secret", {
    repository: appRepo.name,
    secretName: "SERVER_PUBLIC_IP",
    
    // Passing cross-provider data!
    plaintextValue: webServer.publicIp, 
});

The Magic of Cross-Provider Dependencies
#

Look closely at Step 3. We are creating a GitHub Action Secret. The plaintextValue is set to webServer.publicIp.

The Pulumi Engine is incredibly smart. It builds a unified Dependency Graph across all providers.

  1. It knows it must create the AWS EC2 instance first to get the Public IP.
  2. It knows it must create the GitHub Repository first to get the Repository Name.
  3. It will execute both creations in parallel.
  4. Once both are complete, it will create the GitHub Secret.

You just orchestrated a complex multi-cloud deployment with zero race conditions.


3. Configuring Provider Credentials
#

How does Pulumi authenticate with GitHub? We never hardcoded a Personal Access Token (PAT).

Every Provider has a specific configuration block in the Pulumi.<stack>.yaml file. When Pulumi initializes the GitHub Provider, it looks for the github:token configuration variable.

You set this exactly like you set standard config, but you use the provider namespace:

# Set the GitHub token as an encrypted secret
pulumi config set github:token ghp_12345ABCDE --secret

If you look at your Pulumi.dev.yaml:

config:
  aws:region: us-east-1
  github:token:
    secure: v1:9876xyz:fedcba0987654321

Pulumi automatically decrypts the token at runtime and passes it to the GitHub Provider plugin.


4. Explicit Provider Instantiation
#

By default, when you import @pulumi/aws, Pulumi uses the “default” provider configuration (e.g., us-east-1 from your stack config).

But what if you need to deploy resources to us-east-1 AND eu-central-1 in the exact same TypeScript file? You must explicitly instantiate multiple Provider objects.

import * as aws from "@pulumi/aws";

// 1. Create an explicit Provider pointing to Europe
const euProvider = new aws.Provider("eu-provider", {
    region: "eu-central-1",
});

// 2. Create a resource using the default provider (us-east-1)
const usBucket = new aws.s3.Bucket("us-bucket");

// 3. Create a resource using the explicit EU provider
const euBucket = new aws.s3.Bucket("eu-bucket", {
    // Pass the explicit provider in the ResourceOptions!
}, { provider: euProvider }); 

This pattern is also essential if you need to assume different IAM Roles for different resources. You would create a new aws.Provider and pass the assumeRole arguments into it.


Troubleshooting & Common Errors
#

  1. error: Missing required configuration variable 'github:token'

    • Root Cause: You imported the GitHub SDK and instantiated a resource, but the Pulumi Engine cannot authenticate with the GitHub API because you forgot to set the configuration value.
    • Solution: Read the documentation for the specific Provider on the Pulumi Registry. It will always list the required configuration variables. Run pulumi config set <namespace>:<key> <value>.
  2. Module '"@pulumi/datadog"' has no exported member

    • Root Cause: A TypeScript error indicating your IDE doesn’t recognize the package.
    • Solution: Ensure you actually ran npm install @pulumi/datadog.

Conclusion & Next Steps
#

The Pulumi Registry transforms IaC from a simple cloud-provisioning tool into a universal Automation Engine. By integrating providers like GitHub, Kubernetes, and AWS, you can automate your entire organization’s lifecycle.

However, the @pulumi/aws package we have been using is technically a “Bridged” provider. It is actually built on top of the Terraform AWS Provider! This means it inherits some of Terraform’s quirks.

Recently, Pulumi released something revolutionary: a 100% native integration with the AWS Cloud Control API.

In Episode 10: Using Native Providers, we will explore @pulumi/aws-native, learn why it is significantly faster than the classic provider, and discuss when you should use it.

pulumi - This article is part of a series.
Part 9: This Article