forked from discdiver/demos
-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Automatically provision a Prefect Cloud account with resources for the debug tutorial #2
Draft
daniel-prefect
wants to merge
21
commits into
main
Choose a base branch
from
auto_provision_cloud
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
76cd060
Add a script to automatically provision a Prefect Cloud environment f…
djsauble aeb3b63
Add new lines at the end of files
djsauble 647147c
Update misleading description in the 'destroy_env.sh' script
djsauble 12d304c
Update .gitignore to only include the min required Terraform files
djsauble 6800f1d
Use a more robust way of getting the account handle for the active pr…
djsauble d5cb89f
Suppress Docker worker log output
djsauble 8c1e94d
Remove the account handle extraction from the destroy_env.sh script s…
djsauble 8ad77a0
Confirm that this is a Prefect account that supports multiple workspaces
djsauble 8ad3676
Merge branch 'main' into auto_provision_cloud
daniel-prefect 070f061
Restructure infra folder
daniel-prefect b0656fe
Update paths
daniel-prefect eb1aeb8
Merge branch 'main' into auto_provision_cloud
daniel-prefect 685528c
Refactor using modules
daniel-prefect 2be0fd2
Merge variables into the module file
daniel-prefect acae843
Revert "Merge variables into the module file"
daniel-prefect 429cb90
Add newlines to the end of files
daniel-prefect 5f31540
Remove ugly awk logic and update work pool names
daniel-prefect 00263f2
Let users customize the names of the production and staging workspaces
daniel-prefect fb2c95e
Confirm that jq is installed
daniel-prefect 199c901
Move setup_env.sh back to the root since otherwise simulate_failures.…
daniel-prefect ea7774b
Remove extra kill statements, since this is done automatically during…
daniel-prefect File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,11 @@ | ||
env | ||
# Python | ||
__pycache__ | ||
terraform* | ||
.terraform* | ||
env | ||
venv | ||
temp_venv | ||
|
||
# Terraform files | ||
.terraform | ||
*.tfstate | ||
*.tfstate.* | ||
.terraform.lock.hcl |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
terraform { | ||
required_providers { | ||
prefect = { | ||
source = "PrefectHQ/prefect" | ||
} | ||
} | ||
} | ||
|
||
# Module for creating a Prefect workspace and its default work pool | ||
resource "prefect_workspace" "workspace" { | ||
name = var.workspace_name | ||
handle = var.workspace_handle | ||
} | ||
|
||
resource "prefect_work_pool" "default" { | ||
name = var.work_pool_name | ||
workspace_id = prefect_workspace.workspace.id | ||
type = var.work_pool_type | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
output "workspace_id" { | ||
value = prefect_workspace.workspace.id | ||
description = "ID of the created workspace" | ||
} | ||
|
||
output "workspace_handle" { | ||
value = prefect_workspace.workspace.handle | ||
description = "Handle of the created workspace" | ||
} | ||
|
||
output "work_pool_id" { | ||
value = prefect_work_pool.default.id | ||
description = "ID of the created work pool" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
variable "workspace_name" { | ||
description = "Name of the workspace to create" | ||
type = string | ||
} | ||
|
||
variable "workspace_handle" { | ||
type = string | ||
description = "Handle (slug) for the Prefect workspace" | ||
} | ||
|
||
variable "work_pool_name" { | ||
type = string | ||
description = "Name of the default work pool" | ||
default = "my-work-pool" | ||
} | ||
|
||
variable "work_pool_type" { | ||
type = string | ||
description = "Type of the work pool" | ||
default = "docker" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
terraform { | ||
required_providers { | ||
prefect = { | ||
source = "PrefectHQ/prefect" | ||
} | ||
} | ||
} | ||
|
||
provider "prefect" { | ||
api_key = var.prefect_api_key | ||
account_id = var.prefect_account_id | ||
} | ||
|
||
# Create staging environment | ||
module "staging" { | ||
source = "./modules/workspace" | ||
workspace_name = "Staging" | ||
workspace_handle = var.staging_workspace | ||
} | ||
|
||
# Create production environment | ||
module "production" { | ||
source = "./modules/workspace" | ||
workspace_name = "Production" | ||
workspace_handle = var.prod_workspace | ||
} | ||
|
||
variable "prefect_api_key" { | ||
description = "Prefect Cloud API key" | ||
type = string | ||
sensitive = true | ||
} | ||
|
||
variable "prefect_account_id" { | ||
description = "Prefect Cloud Account ID" | ||
type = string | ||
} | ||
|
||
variable "prod_workspace" { | ||
description = "Name of the production workspace" | ||
type = string | ||
default = "production" | ||
} | ||
|
||
variable "staging_workspace" { | ||
description = "Name of the staging workspace" | ||
type = string | ||
default = "staging" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
#!/bin/bash | ||
|
||
############################################################################### | ||
# This script sets up a _paid_ Prefect Cloud account with resources: # | ||
# # | ||
# 1. Two workspaces: `production` and `staging` (customizable via env vars) # | ||
# 2. A Docker work pool in each workspace # | ||
# 3. A flow in each workspace # | ||
# 4. The flow in each workspace is run multiple times # | ||
# 5. The flow in `staging` has failures to demonstrate debugging # | ||
# # | ||
# NOTE: You must have Docker and Terraform installed # | ||
############################################################################### | ||
|
||
# Exit on any error | ||
set -e | ||
|
||
cleanup() { | ||
|
||
# Kill any remaining worker processes | ||
if [ ! -z "$PROD_WORKER_PID" ]; then | ||
kill $PROD_WORKER_PID 2>/dev/null || true | ||
fi | ||
if [ ! -z "$STAGING_WORKER_PID" ]; then | ||
kill $STAGING_WORKER_PID 2>/dev/null || true | ||
fi | ||
|
||
# Deactivate and remove virtual environment | ||
if [ -d "temp_venv" ]; then | ||
deactivate 2>/dev/null || true | ||
rm -rf temp_venv | ||
fi | ||
|
||
echo "🧹 Cleanup completed" | ||
|
||
} | ||
|
||
# Set up trap to call cleanup function on script exit (success or failure) | ||
trap cleanup EXIT | ||
|
||
############################################################################### | ||
# Check for dependencies | ||
############################################################################### | ||
|
||
# Check if Docker is running | ||
echo "🐳 Checking if Docker is running..." | ||
if ! docker info > /dev/null 2>&1; then | ||
echo "❌ Error: Docker is not running. Please start Docker and try again." | ||
exit 1 | ||
fi | ||
|
||
echo "✅ Docker is running" | ||
|
||
# Check if Terraform is installed | ||
echo "🔧 Checking if Terraform is installed..." | ||
if ! command -v terraform &> /dev/null; then | ||
echo "❌ Error: Terraform is not installed. Please install Terraform and try again." | ||
exit 1 | ||
fi | ||
|
||
echo "✅ Terraform is installed" | ||
|
||
# Check if Python is installed and determine the Python command | ||
echo "🐍 Checking if Python is installed..." | ||
if command -v python3 &> /dev/null; then | ||
PYTHON_CMD="python3" | ||
elif command -v python &> /dev/null; then | ||
PYTHON_CMD="python" | ||
else | ||
echo "❌ Error: Python is not installed. Please install Python 3.9 or higher and try again." | ||
exit 1 | ||
fi | ||
|
||
# Verify Python version is 3.9 or higher | ||
if ! $PYTHON_CMD -c "import sys; assert sys.version_info >= (3, 9), 'Python 3.9 or higher is required'" &> /dev/null; then | ||
echo "❌ Error: Python 3.9 or higher is required. Found $($PYTHON_CMD --version)" | ||
exit 1 | ||
fi | ||
|
||
echo "✅ Python $(${PYTHON_CMD} --version) is installed" | ||
|
||
# Check if jq is installed | ||
echo "🔧 Checking if jq is installed..." | ||
if ! command -v jq &> /dev/null; then | ||
echo "❌ Error: jq is not installed. Please install jq and try again." | ||
exit 1 | ||
fi | ||
|
||
echo "✅ jq is installed" | ||
|
||
############################################################################### | ||
# Establish account and workspace details | ||
############################################################################### | ||
|
||
echo "🔑 Fetching Prefect account details..." | ||
|
||
# Must have set TF_VAR_prefect_api_key and TF_VAR_prefect_account_id environment variables | ||
if [ -z "$TF_VAR_prefect_api_key" ]; then | ||
echo "❌ Error: TF_VAR_prefect_api_key environment variable is not set" | ||
exit 1 | ||
fi | ||
|
||
if [ -z "$TF_VAR_prefect_account_id" ]; then | ||
echo "❌ Error: TF_VAR_prefect_account_id environment variable is not set" | ||
exit 1 | ||
fi | ||
|
||
# Set default workspace names if not provided via environment variables | ||
PROD_WORKSPACE=${TF_VAR_prod_workspace:-"production"} | ||
STAGING_WORKSPACE=${TF_VAR_staging_workspace:-"staging"} | ||
|
||
# Export for Terraform to use | ||
export TF_VAR_prod_workspace=$PROD_WORKSPACE | ||
export TF_VAR_staging_workspace=$STAGING_WORKSPACE | ||
|
||
# Account details | ||
ACCOUNT_DETAILS=$(curl -s "https://api.prefect.cloud/api/accounts/$TF_VAR_prefect_account_id" \ | ||
-H "Authorization: Bearer $TF_VAR_prefect_api_key") | ||
|
||
# Get account handle and plan type using jq | ||
ACCOUNT_HANDLE=$(echo "$ACCOUNT_DETAILS" | jq -r '.handle') | ||
PLAN_TYPE=$(echo "$ACCOUNT_DETAILS" | jq -r '.plan_type') | ||
|
||
if [[ $PLAN_TYPE == "PERSONAL" ]]; then | ||
echo "❌ Error: This script requires a paid Prefect Cloud account with support for multiple workspaces." | ||
exit 1 | ||
fi | ||
|
||
############################################################################### | ||
# Set up virtual environment | ||
############################################################################### | ||
|
||
# Create and activate virtual environment | ||
echo "🌟 Setting up Python virtual environment..." | ||
$PYTHON_CMD -m venv temp_venv | ||
source temp_venv/bin/activate | ||
|
||
# Install requirements | ||
echo "📦 Installing Python packages..." | ||
pip install -r ./requirements.txt | ||
|
||
############################################################################### | ||
# Provision Prefect Cloud resources | ||
############################################################################### | ||
|
||
echo "🏗️ Running Terraform to provision infrastructure..." | ||
terraform -chdir=infra/workspaces init | ||
terraform -chdir=infra/workspaces apply -auto-approve | ||
|
||
############################################################################### | ||
# Run flows in production | ||
############################################################################### | ||
|
||
echo "🚀 Populate $PROD_WORKSPACE workspace..." | ||
|
||
# Start worker for production workspace with suppressed output | ||
prefect cloud workspace set --workspace "$ACCOUNT_HANDLE/$PROD_WORKSPACE" | ||
prefect worker start --pool "my-work-pool" > /dev/null 2>&1 & | ||
PROD_WORKER_PID=$! | ||
|
||
# Give workers time to start | ||
sleep 5 | ||
|
||
# Run in production workspace | ||
python ./simulate_failures.py & | ||
PROD_SIM_PID=$! | ||
|
||
# Wait for simulations to complete | ||
wait $PROD_SIM_PID | ||
|
||
############################################################################### | ||
# Run flows in staging | ||
############################################################################### | ||
|
||
echo "🚀 Populate $STAGING_WORKSPACE workspace..." | ||
|
||
# Start worker for staging workspace with suppressed output | ||
prefect cloud workspace set --workspace "$ACCOUNT_HANDLE/$STAGING_WORKSPACE" | ||
prefect worker start --pool "my-work-pool" > /dev/null 2>&1 & | ||
STAGING_WORKER_PID=$! | ||
|
||
# Give workers time to start | ||
sleep 5 | ||
|
||
# Run in staging workspace | ||
python ./simulate_failures.py --fail-at-run 3 & | ||
STAGING_SIM_PID=$! | ||
|
||
# Wait for simulations to complete | ||
wait $STAGING_SIM_PID | ||
|
||
echo "✅ All done!" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In practice a big part of this kind of setup work is creating all the related objects: blocks, variables, automations, etc.
It would be great to show an example of creating a few blocks as well as a simple "notify on failure" automation. I believe that can all be expressed in both Terraform and Python.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this script is in service of the debug tutorial, it depends what kind of scenario we want them to debug. If that scenario includes blocks and automations (the current scenario doesn't), it could make sense to provision more resources.