Pulumi’s Automation API enables you to provision your infrastructure programmatically using the Pulumi engine by exposing Pulumi programs and stacks as strongly-typed and composable building blocks.
In this guide, you will deploy an inline Pulumi program to create a static website using Automation API.
## Prerequisites
### Install Pulumi
{{<install-pulumi/>}}
Install the required language runtime, if you have not already.
You'll need a [Pulumi access token](/docs/pulumi-cloud/accounts#access-tokens) so that your programs can store the resulting state in the Pulumi Cloud. The easiest way to obtain a token is to run `pulumi login` from the command line.
First, define the Pulumi program you want to run as a function within your overall program. Note how it looks like a standard Pulumi program.
{{% choosable language "javascript,typescript" %}}
{{% notes type="info" %}}
This tutorial is based on the [`inlineProgram-ts` example](https://github.com/pulumi/automation-api-examples/tree/main/nodejs/inlineProgram-ts), which is a complete example of how to construct a simple Automation API program.
{{% /notes %}}
```typescript
const pulumiProgram = async () => {
// Create a bucket and expose a website index document.
const siteBucket = new s3.Bucket("s3-website-bucket", {
website: {
indexDocument: "index.html",
},
});
const indexContent = `<html><head>
<title>Hello S3</title><metacharset="UTF-8">
</head>
<body><p>Hello, world!</p><p>Made with ❤️ with <ahref="https://pulumi.com">Pulumi</a></p>
</body></html>
`
// Write our index.html into the site bucket.
let object = new s3.BucketObject("index", {
bucket: siteBucket,
content: indexContent,
contentType: "text/html; charset=utf-8",
key: "index.html"
});
// Create an S3 Bucket Policy to allow public read of all objects in bucket.
function publicReadPolicyForBucket(bucketName): PolicyDocument {
return {
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Principal: "*",
Action: [
"s3:GetObject"
],
Resource: [
`arn:aws:s3:::${bucketName}/*` // Policy refers to bucket name explicitly.
]
}]
};
}
// Set the access policy for the bucket so all objects are readable.
let bucketPolicy = new s3.BucketPolicy("bucketPolicy", {
bucket: siteBucket.bucket, // Refer to the bucket created earlier.
policy: siteBucket.bucket.apply(publicReadPolicyForBucket) // Use output property `siteBucket.bucket`.
});
return {
websiteUrl: siteBucket.websiteEndpoint,
};
};
```
{{% /choosable %}}
{{% choosable language python %}}
{{% notes type="info" %}}
This tutorial is based on the [`inline_program` example](https://github.com/pulumi/automation-api-examples/tree/main/python/inline_program), which is a complete example of how to construct a simple Automation API program.
{{% /notes %}}
```python
def pulumi_program():
# Create a bucket and expose a website index document.
This tutorial is based on the [`inline_program` example](https://github.com/pulumi/automation-api-examples/tree/main/go/inline_program), which is a complete example of how to construct a simple Automation API program.
{{% /notes %}}
```go
deployFunc := func(ctx *pulumi.Context) error {
// Similar go git_repo_program, our program defines a s3 website.
{{% choosable language "csharp,fsharp,visualbasic" %}}
{{% notes type="info" %}}
This tutorial is based on the [`InlineProgram` example](https://github.com/pulumi/automation-api-examples/tree/main/dotnet/InlineProgram), which is a complete example of how to construct a simple Automation API program.
{{% /notes %}}
```csharp
var program = PulumiFn.Create(() =>
{
// Create a bucket and expose a website index document.
var siteBucket = new Pulumi.Aws.S3.Bucket(
"s3-website-bucket",
new Pulumi.Aws.S3.BucketArgs
{
Website = new Pulumi.Aws.S3.Inputs.BucketWebsiteArgs
Statements = new List<Pulumi.Aws.Iam.Inputs.GetPolicyDocumentStatementArgs>
{
new Pulumi.Aws.Iam.Inputs.GetPolicyDocumentStatementArgs
{
Effect = "Allow",
Principals = new List<Pulumi.Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalArgs>
{
new Pulumi.Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalArgs
{
Identifiers = new List<string> { "*" },
Type = "AWS",
},
},
Actions = new List<string> { "s3:GetObject" },
Resources = new List<string> { $"{bucketArn}/*" },
},
},
}));
});
// Set the access policy for the bucket so all objects are readable.
new Pulumi.Aws.S3.BucketPolicy(
"bucket-policy",
new Pulumi.Aws.S3.BucketPolicyArgs
{
Bucket = siteBucket.BucketName,
Policy = bucketPolicyDocument.Apply(x => x.Json),
});
// Export the website url.
return new Dictionary<string,object?>
{
["website_url"] = siteBucket.WebsiteEndpoint,
};
});
```
{{% /choosable %}}
## Associate with a stack
As with executing Pulumi programs through the CLI, you need to associate your Pulumi program with a `Stack`. Automation API provides methods to create or select stacks.
Here's a convenient method to select an existing `Stack` or create one if none exists:
{{% choosable language "csharp,fsharp,visualbasic" %}}
```csharp
var projectName = "inline_s3_project";
var stackName = "dev";
var stackArgs = new InlineProgramArgs(projectName, stackName, program);
var stack = await LocalWorkspace.CreateOrSelectStackAsync(stackArgs);
```
{{% /choosable %}}
{{</chooser>}}
A `Stack` object operates within the context of a `Workspace`. A `Workspace` is the execution context containing a single Pulumi project, a program, and multiple stacks. Workspaces are used to manage the execution environment, providing various utilities such as plugin installation, environment configuration (`$PULUMI_HOME`), and creation, deletion, and listing of stacks. Because you are deploying AWS resources in this tutorial, you must install the AWS provider plugin within your `Workspace` so that your Pulumi program will have it available during execution.
The AWS plugin also needs configuration. You can provide that configuration just as you would with other Pulumi programs: either through [stack configuration](/docs/concepts/config/) or environment variables. In this tutorial, you'll use the `Stack` object to set the AWS region for the AWS provider plugin.
{{% choosable language "csharp,fsharp,visualbasic" %}}
```csharp
var result = await stack.UpAsync(new UpOptions { OnStandardOutput = Console.WriteLine });
```
{{% /choosable %}}
{{</chooser>}}
Notice how you can choose to have a callback function for standard output. In addition, the command returns a result of the update, which you can programmatically use to drive decisions within your program. For example, the result includes the stack outputs as well as a summary of the changes. This means you could choose to take different actions if there were no resources updated. Conversely, you could use the stack outputs to drive another Pulumi program within the same Automation program.
By now, you've hopefully gained a clearer understanding of how to utilize the Automation API. For additional ideas, see the [Automation API examples](https://github.com/pulumi/automation-api-examples).