Reference Google Cloud Resources Across Stacks
In this tutorial, you'll learn:
- How to create a stack output
- How to view the stack output
- How to reference the output from a different stack
Prerequisites:
- The Pulumi CLI
- A Pulumi Cloud account and access token
- A Google Cloud account
- The Google Cloud CLI
- Familiarity with one of Pulumi’s supported languages
Understanding stack outputs
Every Pulumi resource has outputs, which are properties of that resource whose values are generated during deployment. You can export these values as stack outputs, and they can be used for important values like resource IDs, computed IP addresses, and DNS names.
These outputs are shown during an update, can be easily retrieved with the Pulumi CLI, and are displayed in Pulumi Cloud. For the purposes of this tutorial, you will primarily be working from the CLI.
Create a new project
# Example using Python
$ mkdir pulumi-tutorial-gcp
$ cd pulumi-tutorial-gcp
$ pulumi new gcp-python
Then replace the default code with the following code snippet to scaffold your project with the required imports and overall program structure:
"use strict";
const pulumi = require("@pulumi/pulumi");
const gcp = require("@pulumi/gcp");
const bucket = new gcp.storage.Bucket("bucket", {
location: "US",
forceDestroy: true,
});
const role = new gcp.projects.IAMCustomRole("role", {
roleId: "bucketViewerRole",
title: "Bucket Viewer Role",
permissions: ["storage.objects.get", "storage.objects.list"],
stage: "GA",
});
const bucketViewerRoleAssignment = new gcp.storage.BucketIAMMember("bucketViewerRoleAssignment", {
bucket: bucket.name,
role: role.name,
member: "allAuthenticatedUsers",
});
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const bucket = new gcp.storage.Bucket("bucket", {
location: "US",
forceDestroy: true,
});
const role = new gcp.projects.IAMCustomRole("role", {
roleId: "bucketViewerRole",
title: "Bucket Viewer Role",
permissions: ["storage.objects.get", "storage.objects.list"],
stage: "GA",
});
const bucketViewerRoleAssignment = new gcp.storage.BucketIAMMember("bucketViewerRoleAssignment", {
bucket: bucket.name,
role: role.name,
member: "allAuthenticatedUsers",
});
import pulumi
from pulumi_gcp import storage, projects
role = projects.IAMCustomRole(
"bucketViewerRole",
role_id="bucketViewerRole",
title="Bucket Viewer Role",
permissions=[
"storage.objects.get",
"storage.objects.list"
],
stage="GA"
)
bucket = storage.Bucket(
"my-bucket",
location="US",
force_destroy=True
)
bucket_iam_member = storage.BucketIAMMember(
"bucketViewerRoleAssignment",
bucket=bucket.name,
role=role.name,
member="allAuthenticatedUsers"
)
package main
import (
"fmt"
"github.com/pulumi/pulumi-gcp/sdk/v8/go/gcp/projects"
"github.com/pulumi/pulumi-gcp/sdk/v8/go/gcp/storage"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
bucket, err := storage.NewBucket(ctx, "bucket", &storage.BucketArgs{
Location: pulumi.String("US"),
ForceDestroy: pulumi.Bool(true),
})
if err != nil {
return err
}
role, err := projects.NewIAMCustomRole(ctx, "role", &projects.IAMCustomRoleArgs{
RoleId: pulumi.String("bucketViewerRole"),
Title: pulumi.String("Bucket Viewer Role"),
Permissions: pulumi.StringArray{
pulumi.String("storage.objects.get"),
pulumi.String("storage.objects.list"),
},
Stage: pulumi.String("GA"),
})
if err != nil {
return err
}
_, err = storage.NewBucketIAMMember(ctx, "bucketViewerRoleAssignment", &storage.BucketIAMMemberArgs{
Bucket: bucket.Name,
Role: role.Name,
Member: pulumi.String("allAuthenticatedUsers"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var bucket = new Gcp.Storage.Bucket("bucket", new()
{
Location = "US",
ForceDestroy = true,
});
var role = new Gcp.Projects.IAMCustomRole("role", new()
{
RoleId = "bucketViewerRole",
Title = "Bucket Viewer Role",
Permissions = new[]
{
"storage.objects.get",
"storage.objects.list",
},
Stage = "GA",
});
var bucketViewerRoleAssignment = new Gcp.Storage.BucketIAMMember("bucketViewerRoleAssignment", new()
{
Bucket = bucket.Name,
Role = role.Name,
Member = "allAuthenticatedUsers",
});
});
name: gcp-storage-bucket-object-yaml
description: An example that deploys a storage bucket and uploads a file on Google Cloud.
runtime: yaml
resources:
role:
type: gcp:projects:IAMCustomRole
properties:
roleId: bucketViewerRole
title: Bucket Viewer Role
permissions:
- storage.objects.get
- storage.objects.list
stage: GA
bucket:
type: gcp:storage:Bucket
properties:
location: US
forceDestroy: true
bucketViewerRoleAssignment:
type: gcp:storage:BucketIAMMember
properties:
bucket: ${bucket.name}
role: ${role.name}
member: allAuthenticatedUsers
This baseline code defines the following on your behalf:
Export resource values
As mentioned in the Creating Resources on Google Cloud tutorial, every resource has various properties. For any resources that you define in your Pulumi projects, you can export the values of its properties from your program as outputs. You can view a list of available properties that can be exported by referring to the resource properties section of a particular resource’s API documentation (e.g. Bucket properties). The export
syntax is as follows:
exports.<output-name> = <output-value>;
export const <output-name> = <output-value>;
pulumi.export("<output-name>", <output-value>)
ctx.Export("<output-name>", <output-value>)
return await Pulumi.Deployment.RunAsync(() =>
{
return new Dictionary<string, object?>
{
["<output-name>"] = <output-value>
};
});
outputs:
<output-name>: ${<output-value>}
When defining these exports, you’ll need to provide two arguments:
Argument | Description |
---|---|
Output name | This is the name you will use as the identifier of your output value |
Output value | This is the actual value of your output |
To demonstrate how this works, let’s export the name of your IAM Role. By referring to the documentation, you can see that the name of the IAM Role can be referenced via its role ID
property, so update your code to reflect that as shown below:
"use strict";
const pulumi = require("@pulumi/pulumi");
const gcp = require("@pulumi/gcp");
const bucket = new gcp.storage.Bucket("bucket", {
location: "US",
forceDestroy: true,
});
const role = new gcp.projects.IAMCustomRole("role", {
roleId: "bucketViewerRole",
title: "Bucket Viewer Role",
permissions: ["storage.objects.get", "storage.objects.list"],
stage: "GA",
});
const bucketViewerRoleAssignment = new gcp.storage.BucketIAMMember("bucketViewerRoleAssignment", {
bucket: bucket.name,
role: role.name,
member: "allAuthenticatedUsers",
});
exports.roleName = role.roleId;
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const bucket = new gcp.storage.Bucket("bucket", {
location: "US",
forceDestroy: true,
});
const role = new gcp.projects.IAMCustomRole("role", {
roleId: "bucketViewerRole",
title: "Bucket Viewer Role",
permissions: ["storage.objects.get", "storage.objects.list"],
stage: "GA",
});
const bucketViewerRoleAssignment = new gcp.storage.BucketIAMMember("bucketViewerRoleAssignment", {
bucket: bucket.name,
role: role.name,
member: "allAuthenticatedUsers",
});
export const roleName1 = role.roleId;
import pulumi
from pulumi_gcp import storage, projects
role = projects.IAMCustomRole(
"bucketViewerRole",
role_id="bucketViewerRole",
title="Bucket Viewer Role",
permissions=[
"storage.objects.get",
"storage.objects.list"
],
stage="GA"
)
bucket = storage.Bucket(
"my-bucket",
location="US",
force_destroy=True
)
bucket_iam_member = storage.BucketIAMMember(
"bucketViewerRoleAssignment",
bucket=bucket.name,
role=role.name,
member="allAuthenticatedUsers"
)
pulumi.export("roleName", role.role_id)
package main
import (
"fmt"
"github.com/pulumi/pulumi-gcp/sdk/v8/go/gcp/projects"
"github.com/pulumi/pulumi-gcp/sdk/v8/go/gcp/storage"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
bucket, err := storage.NewBucket(ctx, "bucket", &storage.BucketArgs{
Location: pulumi.String("US"),
ForceDestroy: pulumi.Bool(true),
})
if err != nil {
return err
}
role, err := projects.NewIAMCustomRole(ctx, "role", &projects.IAMCustomRoleArgs{
RoleId: pulumi.String("bucketViewerRole"),
Title: pulumi.String("Bucket Viewer Role"),
Permissions: pulumi.StringArray{
pulumi.String("storage.objects.get"),
pulumi.String("storage.objects.list"),
},
Stage: pulumi.String("GA"),
})
if err != nil {
return err
}
_, err = storage.NewBucketIAMMember(ctx, "bucketViewerRoleAssignment", &storage.BucketIAMMemberArgs{
Bucket: bucket.Name,
Role: role.Name,
Member: pulumi.String("allAuthenticatedUsers"),
})
if err != nil {
return err
}
ctx.Export("roleName", role.RoleId)
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var bucket = new Gcp.Storage.Bucket("bucket", new()
{
Location = "US",
ForceDestroy = true,
});
var role = new Gcp.Projects.IAMCustomRole("role", new()
{
RoleId = "bucketViewerRole",
Title = "Bucket Viewer Role",
Permissions = new[]
{
"storage.objects.get",
"storage.objects.list",
},
Stage = "GA",
});
var bucketViewerRoleAssignment = new Gcp.Storage.BucketIAMMember("bucketViewerRoleAssignment", new()
{
Bucket = bucket.Name,
Role = role.Name,
Member = "allAuthenticatedUsers",
});
return new Dictionary<string, object?>
{
["roleName"] = role.RoleId,
};
});
name: gcp-storage-bucket-object-yaml
description: An example that deploys a storage bucket and uploads a file on Google Cloud.
runtime: yaml
resources:
role:
type: gcp:projects:IAMCustomRole
properties:
roleId: bucketViewerRole
title: Bucket Viewer Role
permissions:
- storage.objects.get
- storage.objects.list
stage: GA
bucket:
type: gcp:storage:Bucket
properties:
location: US
forceDestroy: true
bucketViewerRoleAssignment:
type: gcp:storage:BucketIAMMember
properties:
bucket: ${bucket.name}
role: ${role.name}
member: allAuthenticatedUsers
outputs:
roleName: ${role.name}
Deploy your resources
Now save your file and run the pulumi up
command to preview and deploy the resources you’ve just defined in your project.
$ pulumi up -y
Previewing update (stack-outputs)
Type Name Plan
+ pulumi:pulumi:Stack gcp-stack-outputs create
+ ├─ gcp:projects:IAMCustomRole bucketViewerRole create
+ └─ gcp:storage:Bucket my-bucket create
Outputs:
roleName: output<string>
Resources:
+ 3 to create
Updating (stack-outputs)
Type Name Status
+ pulumi:pulumi:Stack gcp-stack-outputs created (6s)
+ ├─ gcp:storage:Bucket my-bucket created (1s)
+ └─ gcp:projects:IAMCustomRole bucketViewerRole created (2s)
Outputs:
roleName: "bucketViewerRole"
Resources:
+ 3 created
Duration: 8s
You can see that the output you’ve created has been provided as a part of the update details. You will learn the different ways you can access this output in the next steps of the tutorial.
Access outputs via the CLI
Now that your resources are deployed, you can access its value either via the CLI or via your Pulumi program code. To access it via the CLI, you can use the pulumi stack output
command. Running this command by itself will list the names and values of all of the exports in your program:
$ pulumi stack output
Current stack outputs (1):
OUTPUT VALUE
roleName bucketViewerRole
If you want to retrieve a specific output value, you will need to provide the name of your desired output as shown below:
$ pulumi stack output roleName
bucketViewerRole
This can be especially useful if you have any workflow scripts that depend on the outputs of your program. For example, if you wanted to view the details of your IAM Role using the Google Cloud CLI, you can do so by running the gcloud iam roles describe
command and passing the output of roleName
to the command, making sure to replace the value of <YOUR_PROJECT_NAME>
with the name of your Google Cloud project:
$ gcloud iam roles describe --project=<YOUR_PROJECT_NAME> $(pulumi stack output roleName)
etag: BwYm3xAUufQ=
includedPermissions:
- storage.objects.get
- storage.objects.list
name: projects/pulumi-devrel/roles/bucketViewerRole
stage: GA
title: Bucket Viewer Role
You have seen how you can reference your output values from the CLI. Now let’s take a look at how you can do the same from within another Pulumi program stack.
Access outputs via stack reference
Stack references allow you to access the outputs of one stack from another stack. This enables developers to create resources even when there are inter-stack dependencies. For this section, you are going to create a new Pulumi program that will access stack output values from your existing program.
Reference resource group name
Start by making a new Pulumi project in a new directory. In this new program, you will need to add the code that will reference an output value from your first program. This can be done using Pulumi’s Stack Reference functionality. When defining a stack reference in code, you will need to pass in the fully qualified name of the stack as an argument. This name is comprised of the organization, project, and stack names in the format of <organization>/<project>/<stack>
For example, if the name of your organization is acmecorp
, the name of your first program is infra
, and the name of your stack is dev
, then your fully qualified name will be acmecorp/infra/dev
.
With that being said, a stack reference will look like the following in your code:
"use strict";
const pulumi = require("@pulumi/pulumi");
const stackRef = new pulumi.StackReference("acmecorp/infra/dev");
import * as pulumi from "@pulumi/pulumi";
const stackRef = new pulumi.StackReference("acmecorp/infra/dev");
import pulumi
stack_ref = pulumi.StackReference("acmecorp/infra/dev")
package main
import (
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
stackRef, err := pulumi.NewStackReference(ctx, "acmecorp/infra/dev", nil)
if err != nil {
return err
}
return nil
})
}
using Pulumi;
return await Pulumi.Deployment.RunAsync(() =>
{
var stackRef = new StackReference("acmecorp/infra/dev");
});
name: my-second-app-dev
runtime: yaml
description: A program to create a Stack Reference
resources:
stack-ref:
type: pulumi:pulumi:StackReference
properties:
name: acmecorp/infra/dev
You will now create an export in your second program that will output the value of the role name from your first program. This is to demonstrate how to retrieve output values from another stack for use in your program.
For the value of your export, you can retrieve it by taking your stack reference variable and using a Stack Reference function called getOutput() against it.
Update your code with the following:
"use strict";
const pulumi = require("@pulumi/pulumi");
// Retrieve the output values from the first stack
const stackRef = new pulumi.StackReference("acmecorp/infra/dev");
// Retrieve the role name from the output values
const roleName = stackRef.getOutput("roleName");
exports.roleName = roleName;
import * as pulumi from "@pulumi/pulumi";
// Retrieve the output values from the first stack
const stackRef = new pulumi.StackReference("acmecorp/infra/dev");
// Retrieve the role name from the output values
const roleName = stackRef.getOutput("roleName");
export const roleName = roleName;
import pulumi
# Retrieve the output values from the first stack
stack_ref = pulumi.StackReference("acmecorp/infra/dev")
# Retrieve the role name from the output values
role_name = stack_ref.get_output("roleName")
pulumi.export("roleName", role_name)
package main
import (
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
// Retrieve the output values from the first stack
stackRef, err := pulumi.NewStackReference(ctx, "acmecorp/infra/dev", nil)
if err != nil {
return err
}
// Retrieve the role name from the output values
roleName := stackRef.GetOutput(pulumi.String("roleName"))
ctx.Export("roleName", roleName)
return nil
})
}
using Pulumi;
return await Pulumi.Deployment.RunAsync(() =>
{
// Retrieve the output values from the first stack
var stackRef = new StackReference("acmecorp/infra/dev");
// Retrieve the role name from the output values
var roleName = stackRef.GetOutput("roleName");
return new Dictionary<string, object?>
{
["roleName"] = roleName
};
});
name: my-second-app-dev
runtime: yaml
description: A program to create a Stack Reference
resources:
# Retrieve the output values from the first stack
stack-ref:
type: pulumi:pulumi:StackReference
properties:
name: acmecorp/infra/dev
variables:
# Retrieve the role name from the output values
roleName: ${stack-ref.outputs["roleName"]}
outputs:
roleName: ${roleName}
To verify that your stack reference is working, run pulumi up
.
$ pulumi up -y
Previewing update (dev):
Type Name Plan
+ pulumi:pulumi:Stack my-second-app-dev create
Outputs:
roleName: output<string>
Resources:
+ 4 to create
Do you want to perform this update? yes
Updating (dev):
Type Name Status
+ pulumi:pulumi:Stack my-second-app-dev created (2s)
Outputs:
roleName: "bucketViewerRole"
Resources:
+ 4 created
Duration: 3s
You should see the name of your IAM role from your first program successfully outputted in the update details of your second program.
Use stack reference in resource definition
In this section, you will use everything you have learned in this tutorial to define a resource that uses a stack reference in the resource definition. In your second program, you will be defining a bucket object resource that will upload a file to the Storage Bucket that was created in your first program. Use the following steps as a guide for adding the Blob resource:
- Navigate to the Google Cloud Registry documentation page
- Search for the
gcp.storage.BucketObject
resource - Define the Bucket Object resource in your second program code
- Export required property values in your first program code
- Import required property values in your second program
- Save and deploy your first program code
- Then save and deploy your second program code
Once you have completed these steps, you can verify that the object was successfully created and uploaded to the conbuckettainer by navigating to Cloud Storage -> Buckets -> <YOUR_PROJECT_NAME> -> <YOUR_BUCKET_NAME>
in the Google Cloud Portal.
View complete solution
You can view the code for the complete solution below.
First program code
"use strict";
const pulumi = require("@pulumi/pulumi");
const gcp = require("@pulumi/gcp");
const bucket = new gcp.storage.Bucket("bucket", {
location: "US",
forceDestroy: true,
});
const role = new gcp.projects.IAMCustomRole("role", {
roleId: "bucketViewerRole",
title: "Bucket Viewer Role",
permissions: ["storage.objects.get", "storage.objects.list"],
stage: "GA",
});
const bucketViewerRoleAssignment = new gcp.storage.BucketIAMMember("bucketViewerRoleAssignment", {
bucket: bucket.name,
role: role.name,
member: "allAuthenticatedUsers",
});
exports.roleName = role.roleId;
exports.bucketName = bucket.name;
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const bucket = new gcp.storage.Bucket("bucket", {
location: "US",
forceDestroy: true,
});
const role = new gcp.projects.IAMCustomRole("role", {
roleId: "bucketViewerRole",
title: "Bucket Viewer Role",
permissions: ["storage.objects.get", "storage.objects.list"],
stage: "GA",
});
const bucketViewerRoleAssignment = new gcp.storage.BucketIAMMember("bucketViewerRoleAssignment", {
bucket: bucket.name,
role: role.name,
member: "allAuthenticatedUsers",
});
export const roleName1 = role.roleId;
export const bucketName1 = bucket.name;
import pulumi
from pulumi_gcp import storage, projects
role = projects.IAMCustomRole(
"bucketViewerRole",
role_id="bucketViewerRole",
title="Bucket Viewer Role",
permissions=[
"storage.objects.get",
"storage.objects.list"
],
stage="GA"
)
bucket = storage.Bucket(
"my-bucket",
location="US",
force_destroy=True
)
bucket_iam_member = storage.BucketIAMMember(
"bucketViewerRoleAssignment",
bucket=bucket.name,
role=role.name,
member="allAuthenticatedUsers"
)
pulumi.export("roleName", role.role_id)
pulumi.export("bucketName", bucket.name)
package main
import (
"fmt"
"github.com/pulumi/pulumi-gcp/sdk/v8/go/gcp/projects"
"github.com/pulumi/pulumi-gcp/sdk/v8/go/gcp/storage"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
bucket, err := storage.NewBucket(ctx, "bucket", &storage.BucketArgs{
Location: pulumi.String("US"),
ForceDestroy: pulumi.Bool(true),
})
if err != nil {
return err
}
role, err := projects.NewIAMCustomRole(ctx, "role", &projects.IAMCustomRoleArgs{
RoleId: pulumi.String("bucketViewerRole"),
Title: pulumi.String("Bucket Viewer Role"),
Permissions: pulumi.StringArray{
pulumi.String("storage.objects.get"),
pulumi.String("storage.objects.list"),
},
Stage: pulumi.String("GA"),
})
if err != nil {
return err
}
_, err = storage.NewBucketIAMMember(ctx, "bucketViewerRoleAssignment", &storage.BucketIAMMemberArgs{
Bucket: bucket.Name,
Role: role.Name,
Member: pulumi.String("allAuthenticatedUsers"),
})
if err != nil {
return err
}
ctx.Export("roleName", role.RoleId)
ctx.Export("bucketName", bucket.Name)
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var bucket = new Gcp.Storage.Bucket("bucket", new()
{
Location = "US",
ForceDestroy = true,
});
var role = new Gcp.Projects.IAMCustomRole("role", new()
{
RoleId = "bucketViewerRole",
Title = "Bucket Viewer Role",
Permissions = new[]
{
"storage.objects.get",
"storage.objects.list",
},
Stage = "GA",
});
var bucketViewerRoleAssignment = new Gcp.Storage.BucketIAMMember("bucketViewerRoleAssignment", new()
{
Bucket = bucket.Name,
Role = role.Name,
Member = "allAuthenticatedUsers",
});
return new Dictionary<string, object?>
{
["roleName"] = role.RoleId,
["bucketName"] = bucket.Name,
};
});
name: gcp-storage-bucket-object-yaml
description: An example that deploys a storage bucket and uploads a file on Google Cloud.
runtime: yaml
resources:
role:
type: gcp:projects:IAMCustomRole
properties:
roleId: bucketViewerRole
title: Bucket Viewer Role
permissions:
- storage.objects.get
- storage.objects.list
stage: GA
bucket:
type: gcp:storage:Bucket
properties:
location: US
forceDestroy: true
bucketViewerRoleAssignment:
type: gcp:storage:BucketIAMMember
properties:
bucket: ${bucket.name}
role: ${role.name}
member: allAuthenticatedUsers
outputs:
roleName: ${role.name}
bucketName: ${bucket.name}
Second program code
"use strict";
const pulumi = require("@pulumi/pulumi");
const stackRef = new pulumi.StackReference("acmecorp/infra/dev");
const roleName = stackRef.getOutput("roleName");
const bucketName = stackRef.getOutput("bucketName");
const bucketObject = new gcp.storage.BucketObject("bucketObject", {
bucket: bucketName,
content: pulumi.interpolate`My bucket role name is: ${roleName}`,
contentType: "text/plain",
});
import * as pulumi from "@pulumi/pulumi";
const stackRef = new pulumi.StackReference("acmecorp/infra/dev");
const roleName2 = stackRef.getOutput("roleName");
const bucketName2 = stackRef.getOutput("bucketName");
const bucketObject = new gcp.storage.BucketObject("bucketObject", {
bucket: bucketName,
content: pulumi.interpolate`My bucket role name is: ${roleName}`,
contentType: "text/plain",
});
import pulumi
stack_ref = pulumi.StackReference("acmecorp/infra/dev")
role_name = stack_ref.get_output("roleName")
bucket_name = stack_ref.get_output("bucketName")
bucket_object = storage.BucketObject(
"my-object",
bucket=bucket_name,
source=pulumi.StringAsset(file_content),
content_type="text/plain"
)
package main
import (
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
stackRef, err := pulumi.NewStackReference(ctx, "acmecorp/infra/dev", nil)
if err != nil {
return err
}
roleName := stackRef.GetOutput(pulumi.String("roleName"))
bucketName := stackRef.GetOutput(pulumi.String("bucketName"))
_, err = storage.NewBucketObject(ctx, "bucketObject", &storage.BucketObjectArgs{
Bucket: bucketName,
Content: roleName.ApplyT(func(roleName string) (string, error) {
return fmt.Sprintf("My bucket role name is: %v", roleName), nil
}).(pulumi.StringOutput),
ContentType: pulumi.String("text/plain"),
})
if err != nil {
return err
}
return nil
})
}
using Pulumi;
return await Pulumi.Deployment.RunAsync(() =>
{
var stackRef = new StackReference("acmecorp/infra/dev");
var roleName = stackRef.GetOutput("roleName");
var bucketName = stackRef.GetOutput("bucketName");
var bucketObject = new Gcp.Storage.BucketObject("bucketObject", new()
{
Bucket = bucketName,
Content = roleName.Apply(roleName => $"My bucket role name is: {roleName}"),
ContentType = "text/plain",
});
});
name: infra
runtime: yaml
description: A program to create a Stack Reference
resources:
stack-ref:
type: pulumi:pulumi:StackReference
properties:
name: acmecorp/infra/dev
bucketObject:
type: gcp:storage:BucketObject
properties:
bucket: ${bucketName}
content: "My bucket role name is: ${roleName}"
contentType: text/plain
variables:
roleName: ${stack-ref.outputs["roleName"]}
bucketName: ${stack-ref.outputs["bucketName"]}
Clean up
Before moving on, tear down the resources that are part of your stack to avoid incurring any charges.
- Run
pulumi destroy
to tear down all resources. You'll be prompted to make sure you really want to delete these resources. A destroy operation may take some time, since Pulumi waits for the resources to finish shutting down before it considers the destroy operation to be complete. - To delete the stack itself, run
pulumi stack rm
. Note that this command deletes all deployment history from the Pulumi Service.
Next steps
In this tutorial, you created a Google Cloud Storage Bucket and custom IAM role. You also referenced the documentation to create a storage object that would upload a file to the bucket. You exported resource properties into stack outputs, and referenced those outputs across stacks using stack references.
To learn more about creating and managing resources in Pulumi, take a look at the following resources:
- Learn more about creating resources in the Creating Resources on Google Cloud tutorial.
- Learn more about stack outputs and references in the Pulumi documentation.
- Learn more about Pulumi inputs and outputs in the Pulumi documentation.