Demo project and how-to guide to use Pulumi as an IaC (Infrastructure as Code) tool for creating GCP sandbox projects with starting resources for demos, workshops, trainings, etc.
Learn more about the OSS Pulumi project: www.pulumi.com
Contact maintainer:
- Marcos Manuel Ortega: [email protected]
- LinkedIn: Marcos Manuel Ortega
You are running a GCP workshop, training course, sandbox, hackathon... and you need to create several individual projects for participants.
Those project need IAM roles for participants, APIs enabled by default, billing enabled, etc., and most importantly, maybe multiple resources already created following a template.
You don't want to setup each all of that for each user and project manually, then doing it all over again for each event, forgetting to setup something, fixing errors during the event...
You would prefer to have a template for creating projects automatically, just reusing it every time new environments are needed, and even collaborate sharing project templates.
- Clone repo and setup as working dir:
git clone REPO_URL
,cd gcp-training-projects
- Install Pulumi CLI: [https://github.com/pulumi/pulumi?tab=readme-ov-file#getting-started],
curl -fsSL https://get.pulumi.com/ | sh
- (Optional, works without it) Install Pulumi Python package:
- (Recommended) Create a Python virtual environment (eg. using venv):
python -m venv .venv
- Activate virtual environment:
source .venv/bin/activate
- Install Pulumi GCP Python package:
pip install -r requirements.txt
- (Recommended) Create a Python virtual environment (eg. using venv):
- You can login to Pulumi or manage stack states locally:
- State file in
$HOME/.pulumi
:pulumi login --local
(alias forpulumi login file://~
) - State file in another location:
pulumi login file://path/to/pulumi-state
- State file in
- If you want to use the code in this repo, don't create a new Pulumi project, as will rewrite
__main__.py
file.
- (Optional, works without it) Install Pulumi Python package:
- You can setup Pulumi passphrase so you don't have to input it every time:
export PULUMI_CONFIG_PASSPHRASE=passphrase && echo $PULUMI_CONFIG_PASSPHRASE
- Setup GCP authn Application Default Credentials (ADC) for Cloud SDK and Pulumi CLI:
gcloud auth application-default login
- You need a working Cloud SDK installation or use GCP Cloud Shell.
- Work under
stacks
dir:cd stacks
- Create a new Pulumi stack. You can use the lab name as the Pulumi stack name:
pulumi stack init STACK_NAME
- Include config in
Pulumi.STACK_NAME.yaml
(example file:example-Pulumi.stack_name-yaml
). Requires:- List of emails of attendees for access control to projects. Recommended to also include the first email for the instructor's project.
- List of roles to be assigned to all attendes in their projects.
- List of APIs/services to be enabled in all projects.
- IDs for organization & billing account, and folder name.
- Project prefix, e.g. Project IDs created
PROJECT_PREFIX-00-EMAIL_HASH_SUFFIX
, with00-99
pseudo-random integers for each project- Project prefix can e.g. reflect the name of the lab or workshop, so can also be the same as Pulumi stack name.
- GCP project IDs must be 6 to 30 with lowercase letters, digits, hyphens, start with a letter, and trailing hyphens are prohibited, so this also applies to project prefix.
- No underscores in GCP project IDs.
- Name of the infrastructure resources script to be imported:
- For clarity, you can use
STACK_NAME_infra
, but it's not enforced - e.g. this how-to guide useslab-project_infra
. - Don't add
.py
as it looks for the name of the Python module script, not the file itself.
- For clarity, you can use
- As we're creating a GCP folder and multiple projects, Pulumi config
gcp:project
is not used, so it can be skipped (Pulumi throwns a warning) or can be setup as any valid GCP project ID.
- Include IaC for creating template GCP resources in
STACK_NAME_infra.py
, along Pulumi exports as needed.
- Check Pulumi's preview of resources to be created:
pulumi preview
- Create resources with Pulumi CLI:
pulumi up
- Check resources created:
pulumi stack
- Destroy folder, projects and resources:
pulumi down
Sometimes you just want one lab environment for a single exercise, sometimes you're running an event/workshop/course composed of multiple lab exercises.
You can organize multiple exercises by using Pulumi projects and Pulumi Stacks:
- Using a new stack for each environment is easier as you don't have to create new Pulumi projects, but doesn't allow to organize multiple exercises together.
- Creating a different Pulumi project and then multiple stacks for each exercise allows to organize them together and represent a single reproducible event.
- Each stack uses a different
Pulumi.STACK_NAME.yaml
args andSTACK_NAME_infra.py
GCP resources files, whether using different Pulumi projects or not.Pulumi.lab-project.yaml
andlab-project_infra.py
files are provided as examples.
- You can have a main Pulumi project for multiple individual exercises/stacks, then also other Pulumi projects for specific multi-exercise/multi-stack events.
Beware: Creating a new Pulumi project rewrites __main__.py
, losing all code, so you'll need to copy the file again.
You can create a new Pulumi project with pulumi new
and use the GCP Python
provied template.
You can manage stacks with pulumi stack
(docs):
- Create:
pulumi stack init
- List:
pulumi stack ls
- Check stack state and GCP resources crated:
pulumi stack
- Choose current stack:
pulumi stack select
- Remove:
pulumi stack rm
Check stacks/requirements.txt
:
- Pulumi for Python v3
- Pulumi provider: Google Cloud (GCP) Classic v7
GNU GPLv3
Tested at the time of last commit:
- GCP project IDs are created using a deterministic hashed salt, which includes args set in
Pulumi.STACK_NAME.yaml
, as everytimepulumi up
is run it needs to match the same project IDs. As when a GCP project is deleted it enters a pending delete state for 30 d, if the same attendee or instructor is included in a different event using the same args, an error will be thrown when trying to create their project. In this case, just change some args likestack name
,project prefix
orfolder name
and a different hash will be produced. Checkmain.py
for more.
If you find any issues, please open a GitHub issue before, (optionally) open a PR to fix it, or contact the maintainer directly any way.
See to-dos in to-dos.md
.