The gcp:organizations/project:Project resource, part of the Pulumi GCP provider, creates a GCP project and places it within an organization or folder hierarchy. This guide focuses on three capabilities: organization-level project creation, folder-based organization, and resource manager tagging.
Projects must belong to a GCP organization and require IAM permissions (roles/resourcemanager.projectCreator). The examples are intentionally small. Combine them with your own billing accounts, network configuration, and labels.
Create a project under an organization
Most deployments start by creating a project directly under an organization, establishing the top-level container for resources and billing.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const myProject = new gcp.organizations.Project("my_project", {
name: "My Project",
projectId: "your-project-id",
orgId: "1234567",
});
import pulumi
import pulumi_gcp as gcp
my_project = gcp.organizations.Project("my_project",
name="My Project",
project_id="your-project-id",
org_id="1234567")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := organizations.NewProject(ctx, "my_project", &organizations.ProjectArgs{
Name: pulumi.String("My Project"),
ProjectId: pulumi.String("your-project-id"),
OrgId: pulumi.String("1234567"),
})
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 myProject = new Gcp.Organizations.Project("my_project", new()
{
Name = "My Project",
ProjectId = "your-project-id",
OrgId = "1234567",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.Project;
import com.pulumi.gcp.organizations.ProjectArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var myProject = new Project("myProject", ProjectArgs.builder()
.name("My Project")
.projectId("your-project-id")
.orgId("1234567")
.build());
}
}
resources:
myProject:
type: gcp:organizations:Project
name: my_project
properties:
name: My Project
projectId: your-project-id
orgId: '1234567'
The projectId must be globally unique across all GCP projects. The orgId places the project at the organization’s top level. The name property sets the human-readable display name shown in the console.
Create a project under a folder
Organizations often group projects into folders to reflect departmental structure or environment boundaries.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const department1 = new gcp.organizations.Folder("department1", {
displayName: "Department 1",
parent: "organizations/1234567",
});
const myProject_in_a_folder = new gcp.organizations.Project("my_project-in-a-folder", {
name: "My Project",
projectId: "your-project-id",
folderId: department1.name,
});
import pulumi
import pulumi_gcp as gcp
department1 = gcp.organizations.Folder("department1",
display_name="Department 1",
parent="organizations/1234567")
my_project_in_a_folder = gcp.organizations.Project("my_project-in-a-folder",
name="My Project",
project_id="your-project-id",
folder_id=department1.name)
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
department1, err := organizations.NewFolder(ctx, "department1", &organizations.FolderArgs{
DisplayName: pulumi.String("Department 1"),
Parent: pulumi.String("organizations/1234567"),
})
if err != nil {
return err
}
_, err = organizations.NewProject(ctx, "my_project-in-a-folder", &organizations.ProjectArgs{
Name: pulumi.String("My Project"),
ProjectId: pulumi.String("your-project-id"),
FolderId: department1.Name,
})
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 department1 = new Gcp.Organizations.Folder("department1", new()
{
DisplayName = "Department 1",
Parent = "organizations/1234567",
});
var myProject_in_a_folder = new Gcp.Organizations.Project("my_project-in-a-folder", new()
{
Name = "My Project",
ProjectId = "your-project-id",
FolderId = department1.Name,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.Folder;
import com.pulumi.gcp.organizations.FolderArgs;
import com.pulumi.gcp.organizations.Project;
import com.pulumi.gcp.organizations.ProjectArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var department1 = new Folder("department1", FolderArgs.builder()
.displayName("Department 1")
.parent("organizations/1234567")
.build());
var myProject_in_a_folder = new Project("myProject-in-a-folder", ProjectArgs.builder()
.name("My Project")
.projectId("your-project-id")
.folderId(department1.name())
.build());
}
}
resources:
myProject-in-a-folder:
type: gcp:organizations:Project
name: my_project-in-a-folder
properties:
name: My Project
projectId: your-project-id
folderId: ${department1.name}
department1:
type: gcp:organizations:Folder
properties:
displayName: Department 1
parent: organizations/1234567
The folderId property places the project within a folder hierarchy instead of directly under the organization. Only one of orgId or folderId may be specified. The Folder resource creates the parent folder, which itself references the organization.
Apply resource manager tags at creation
Resource manager tags provide organization-wide metadata for governance, cost allocation, and conditional access policies.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const myProject = new gcp.organizations.Project("my_project", {
name: "My Project",
projectId: "your-project-id",
orgId: "1234567",
tags: {
"1234567/env": "staging",
},
});
import pulumi
import pulumi_gcp as gcp
my_project = gcp.organizations.Project("my_project",
name="My Project",
project_id="your-project-id",
org_id="1234567",
tags={
"1234567/env": "staging",
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := organizations.NewProject(ctx, "my_project", &organizations.ProjectArgs{
Name: pulumi.String("My Project"),
ProjectId: pulumi.String("your-project-id"),
OrgId: pulumi.String("1234567"),
Tags: pulumi.StringMap{
"1234567/env": pulumi.String("staging"),
},
})
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 myProject = new Gcp.Organizations.Project("my_project", new()
{
Name = "My Project",
ProjectId = "your-project-id",
OrgId = "1234567",
Tags =
{
{ "1234567/env", "staging" },
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.Project;
import com.pulumi.gcp.organizations.ProjectArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var myProject = new Project("myProject", ProjectArgs.builder()
.name("My Project")
.projectId("your-project-id")
.orgId("1234567")
.tags(Map.of("1234567/env", "staging"))
.build());
}
}
resources:
myProject:
type: gcp:organizations:Project
name: my_project
properties:
name: My Project
projectId: your-project-id
orgId: '1234567'
tags:
1234567/env: staging
The tags property applies resource manager tags at project creation. Tag keys must follow the format tagKeys/{tag_key_id} and values must use tagValues/{tag_value_id}. Tags are immutable; changing them after creation triggers project recreation. For mutable metadata, use the labels property instead.
Beyond these examples
These snippets focus on specific project-level features: organization and folder placement, and resource manager tags. They’re intentionally minimal rather than full project configurations.
The examples require pre-existing infrastructure such as a GCP organization with numeric ID, IAM permissions (roles/resourcemanager.projectCreator), and resource manager tag keys for the tagging example. They focus on project placement and identity rather than provisioning billing or networking.
To keep things focused, common project patterns are omitted, including:
- Billing account attachment (billingAccount)
- Default network control (autoCreateNetwork)
- Labels for resource-level metadata
- Deletion policies and lifecycle management
These omissions are intentional: the goal is to illustrate how project placement and tagging are wired, not provide drop-in project modules. See the GCP Project resource reference for all available configuration options.
Let's create and Manage GCP Projects
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Project Creation & Hierarchy
projectId and tags properties are immutable. Changing projectId forces a new project to be created, and modifying tags triggers resource replacement. To apply tags to an existing project, use the gcp.tags.TagValue resource instead.orgId to create the project at the organization’s top level, or folderId to create it under a specific folder. Changing orgId forces a new project, while changing folderId migrates the project to the new folder.orgId forces a new project to be created, while changing folderId migrates the existing project to the new folder.Permissions & Billing
roles/resourcemanager.projectCreator on the organization and at least roles/billing.user on the billing account.pulumi up and pulumi preview operation, so you must maintain permissions on the billing account throughout the project’s lifecycle.Networking & Default Resources
autoCreateNetwork is false, you need 1 network slot available because the default network exists momentarily before being deleted. The recommended approach is to use the constraints/compute.skipDefaultNetworkCreation organization policy constraint instead.constraints/compute.skipDefaultNetworkCreation organization policy constraint rather than setting autoCreateNetwork to false.Labels & Tags
labels field only manages labels present in your Pulumi configuration. Other labels applied through different clients or services won’t be removed. Use effectiveLabels to see all labels present on the resource.tags property after creation, as it’s immutable and triggers resource replacement. Instead, use the gcp.tags.TagValue resource to apply tags to existing projects.Using a different cloud?
Explore integration guides for other cloud providers: