Pulumi's Node.js SDK for infrastructure-as-code platform that allows you to create, deploy, and manage infrastructure using familiar programming languages and tools.
85
Pulumi's asset system enables packaging and deployment of files, directories, and remote content as part of your infrastructure resources, commonly used for Lambda functions, container images, and configuration files.
abstract class Asset {
readonly __pulumiAsset: boolean;
}
abstract class Archive {
readonly __pulumiArchive: boolean;
}
// File-based assets
class FileAsset extends Asset {
constructor(path: string);
readonly path: string;
}
class StringAsset extends Asset {
constructor(text: string);
readonly text: string;
}
class RemoteAsset extends Asset {
constructor(uri: string);
readonly uri: string;
}
// Archive types
class FileArchive extends Archive {
constructor(path: string);
readonly path: string;
}
class AssetArchive extends Archive {
constructor(assets: AssetMap);
readonly assets: AssetMap;
}
class RemoteArchive extends Archive {
constructor(uri: string);
readonly uri: string;
}
type AssetMap = {[name: string]: Asset | Archive};import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
// Single file asset
const configFile = new pulumi.asset.FileAsset("./config/app.json");
// Use in S3 bucket object
const configObject = new aws.s3.BucketObject("app-config", {
bucket: bucket.id,
key: "config/app.json",
source: configFile,
contentType: "application/json",
});
// String-based asset for generated content
const indexHtml = new pulumi.asset.StringAsset(`
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
</head>
<body>
<h1>Welcome to My App</h1>
<p>Environment: ${config.require("environment")}</p>
</body>
</html>
`);
const indexObject = new aws.s3.BucketObject("index", {
bucket: bucket.id,
key: "index.html",
source: indexHtml,
contentType: "text/html",
});import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
// Directory archive for Lambda function
const lambdaCode = new pulumi.asset.FileArchive("./lambda-function");
const lambdaFunction = new aws.lambda.Function("my-function", {
runtime: "nodejs18.x",
code: lambdaCode,
handler: "index.handler",
role: lambdaRole.arn,
});
// Selective file archive
const webAssets = new pulumi.asset.AssetArchive({
"index.html": new pulumi.asset.FileAsset("./web/index.html"),
"styles.css": new pulumi.asset.FileAsset("./web/styles.css"),
"app.js": new pulumi.asset.FileAsset("./web/app.js"),
"assets/": new pulumi.asset.FileArchive("./web/assets"),
});
const websiteZip = new aws.s3.BucketObject("website", {
bucket: bucket.id,
key: "website.zip",
source: webAssets,
});import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
// Remote file asset
const remoteScript = new pulumi.asset.RemoteAsset(
"https://raw.githubusercontent.com/myorg/scripts/main/setup.sh"
);
// Remote archive
const applicationCode = new pulumi.asset.RemoteArchive(
"https://github.com/myorg/myapp/archive/v1.2.3.tar.gz"
);
const lambdaFromRemote = new aws.lambda.Function("remote-function", {
runtime: "python3.9",
code: applicationCode,
handler: "main.handler",
role: lambdaRole.arn,
});import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as fs from "fs";
import * as path from "path";
// Generate configuration file dynamically
const config = new pulumi.Config();
const environment = config.require("environment");
const appConfig = {
environment: environment,
apiEndpoint: config.require("apiEndpoint"),
features: {
authentication: config.getBoolean("enableAuth") || false,
analytics: config.getBoolean("enableAnalytics") || false,
},
buildTimestamp: new Date().toISOString(),
};
const configAsset = new pulumi.asset.StringAsset(
JSON.stringify(appConfig, null, 2)
);
// Create archive with generated content
const deploymentPackage = new pulumi.asset.AssetArchive({
"config.json": configAsset,
"app/": new pulumi.asset.FileArchive("./src"),
"package.json": new pulumi.asset.FileAsset("./package.json"),
"yarn.lock": new pulumi.asset.FileAsset("./yarn.lock"),
});import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as docker from "@pulumi/docker";
// Build and push container image
const repository = new aws.ecr.Repository("app-repo");
const image = new docker.Image("app-image", {
build: {
context: "./app",
dockerfile: "./app/Dockerfile",
},
imageName: pulumi.interpolate`${repository.repositoryUrl}:latest`,
registry: {
server: repository.repositoryUrl,
username: "AWS",
password: pulumi.output(aws.ecr.getAuthorizationToken({
registryId: repository.registryId,
})).authorizationToken.apply(token =>
Buffer.from(token, "base64").toString().split(":")[1]
),
},
});
// Use in ECS task definition
const taskDefinition = new aws.ecs.TaskDefinition("app-task", {
family: "my-app",
containerDefinitions: pulumi.jsonStringify([{
name: "app",
image: image.imageName,
memory: 512,
essential: true,
portMappings: [{
containerPort: 8080,
hostPort: 8080,
}],
}]),
});import * as pulumi from "@pulumi/pulumi";
import * as fs from "fs";
import * as path from "path";
// Template processing function
function processTemplate(templatePath: string, variables: Record<string, any>): pulumi.asset.StringAsset {
let template = fs.readFileSync(templatePath, "utf8");
Object.entries(variables).forEach(([key, value]) => {
const placeholder = new RegExp(`{{\\s*${key}\\s*}}`, "g");
template = template.replace(placeholder, String(value));
});
return new pulumi.asset.StringAsset(template);
}
// Use template processing
const config = new pulumi.Config();
const nginxConfig = processTemplate("./templates/nginx.conf.template", {
serverName: config.require("serverName"),
upstreamHost: config.require("upstreamHost"),
upstreamPort: config.getNumber("upstreamPort") || 8080,
});
// Bundle multiple processed templates
const configBundle = new pulumi.asset.AssetArchive({
"nginx.conf": nginxConfig,
"mime.types": new pulumi.asset.FileAsset("./config/mime.types"),
"ssl/": new pulumi.asset.FileArchive("./ssl-certificates"),
});import * as pulumi from "@pulumi/pulumi";
const config = new pulumi.Config();
const environment = config.require("environment");
// Different assets based on environment
function getLambdaCode(): pulumi.asset.Archive {
if (environment === "development") {
// Use local development build
return new pulumi.asset.FileArchive("./dist/dev");
} else if (environment === "production") {
// Use optimized production build
return new pulumi.asset.FileArchive("./dist/prod");
} else {
// Use pre-built artifact from CI/CD
const artifactUrl = config.require("artifactUrl");
return new pulumi.asset.RemoteArchive(artifactUrl);
}
}
const lambdaFunction = new aws.lambda.Function("app-function", {
runtime: "nodejs18.x",
code: getLambdaCode(),
handler: "index.handler",
role: lambdaRole.arn,
environment: {
variables: {
NODE_ENV: environment,
},
},
});import * as pulumi from "@pulumi/pulumi";
import * as fs from "fs";
import * as path from "path";
// Utility function to validate assets exist
function validateAssetPath(assetPath: string): string {
const fullPath = path.resolve(assetPath);
if (!fs.existsSync(fullPath)) {
throw new Error(`Asset path does not exist: ${fullPath}`);
}
return assetPath;
}
// Helper for creating archives with validation
function createValidatedArchive(paths: Record<string, string>): pulumi.asset.AssetArchive {
const assets: Record<string, pulumi.asset.Asset | pulumi.asset.Archive> = {};
Object.entries(paths).forEach(([key, assetPath]) => {
validateAssetPath(assetPath);
const stats = fs.statSync(assetPath);
if (stats.isDirectory()) {
assets[key] = new pulumi.asset.FileArchive(assetPath);
} else {
assets[key] = new pulumi.asset.FileAsset(assetPath);
}
});
return new pulumi.asset.AssetArchive(assets);
}
// Usage with validation
const applicationBundle = createValidatedArchive({
"src/": "./src",
"package.json": "./package.json",
"config.json": "./config/production.json",
});FileArchive for packaging entire directories (Lambda functions, web assets)StringAsset for generated configuration files and templatesInstall with Tessl CLI
npx tessl i tessl/npm-pulumi--pulumidocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10