Stage 03 · IaC · 5 min
Infra as Code
Generate Terraform and Ansible to provision and configure the OpenShift environment
TALKING POINT · #21
- Before anything can be deployed, the infrastructure needs to exist. Instead of clicking through a console or running ad-hoc scripts, we'll ask Bob to generate the infrastructure as code — repeatable, version-controlled, and auditable.
- We'll use Terraform to provision the OpenShift namespace and resources, and Ansible to configure the environment — applying policies, setting up service accounts, and preparing the namespace for the payment app.
TIP · #45
Bob generates these files only — we're not executing them live. But the output is production-ready and can be committed to the repo alongside the application code.
Prompts
PRESENTER NOTE · #23
Before we generate the infrastructure files, let's ask Bob to visualize the full IaC flow — so the audience can see how Terraform, Ansible, and the deployment pipeline connect.
3a · IaC Architecture Diagram
▼
Generate a Mermaid diagram showing the full infrastructure and deployment flow for the payment application.
Note: Mermaid does not support `\n` inside node labels — use `
` for line breaks within labels. Cluster: single OpenShift cluster — 5 worker nodes, 16 vCPU and 64 GB RAM each. Two namespaces: bob-demo-staging and bob-demo-prod. Image registry: OpenShift internal image registry (image-registry.openshift-image-registry.svc:5000). The diagram should show: Infrastructure layer (Terraform): - Both namespaces on the same cluster - Per namespace: ResourceQuota, NetworkPolicy, ServiceAccount - Per namespace: PostgreSQL Deployment + ClusterIP Service (port 5432, internal only) + PersistentVolumeClaim (5Gi) - NetworkPolicy rules: payment-service → postgres-service on port 5432 allowed, all other ingress/egress denied by default Configuration layer (Ansible): - PostgreSQL credentials Secret injected per namespace - ConfigMap for app configuration - PostgreSQL readiness wait before pre-flight health check CI/CD and deployment flow: - CI builds image → pushes to OpenShift internal registry under bob-demo-staging - CD auto-deploys payment-service to bob-demo-staging → connects to postgres-service in same namespace - Image promoted via oc tag within internal registry to bob-demo-prod - Manual approval gates production deployment - payment-service in bob-demo-prod connects to its own postgres-service Output the diagram as a .md file: payment-app-java17/infra/IaCArchitecture.md Once the file is saved, display the Mermaid diagram directly in the chat so we can see it immediately.
` for line breaks within labels. Cluster: single OpenShift cluster — 5 worker nodes, 16 vCPU and 64 GB RAM each. Two namespaces: bob-demo-staging and bob-demo-prod. Image registry: OpenShift internal image registry (image-registry.openshift-image-registry.svc:5000). The diagram should show: Infrastructure layer (Terraform): - Both namespaces on the same cluster - Per namespace: ResourceQuota, NetworkPolicy, ServiceAccount - Per namespace: PostgreSQL Deployment + ClusterIP Service (port 5432, internal only) + PersistentVolumeClaim (5Gi) - NetworkPolicy rules: payment-service → postgres-service on port 5432 allowed, all other ingress/egress denied by default Configuration layer (Ansible): - PostgreSQL credentials Secret injected per namespace - ConfigMap for app configuration - PostgreSQL readiness wait before pre-flight health check CI/CD and deployment flow: - CI builds image → pushes to OpenShift internal registry under bob-demo-staging - CD auto-deploys payment-service to bob-demo-staging → connects to postgres-service in same namespace - Image promoted via oc tag within internal registry to bob-demo-prod - Manual approval gates production deployment - payment-service in bob-demo-prod connects to its own postgres-service Output the diagram as a .md file: payment-app-java17/infra/IaCArchitecture.md Once the file is saved, display the Mermaid diagram directly in the chat so we can see it immediately.
PRESENTER NOTE · #24
Walk the audience through the diagram layer by layer — Terraform (namespaces, quotas, network policies, PostgreSQL + PVC), Ansible (credentials, config, readiness checks), and the CI/CD flow (build → staging → oc tag → prod).
TIP · #46
If you have infra or platform engineers in the room, this is their moment — they'll immediately recognize the Terraform structure, the NetworkPolicy rules, and the PVC setup. This diagram speaks their language. Let them react before moving on.
TIP · #47
Cost: ~0.1 bobcoins.
3b · Terraform — Full Infrastructure + GitHub Secrets
▼
Based on the IaC architecture diagram in payment-app-java17/infra/IaCArchitecture.md, generate a complete Terraform configuration to provision the OpenShift environment and GitHub Actions secrets for the payment application.
## Infrastructure Overview
**Cluster**: Single OpenShift cluster — 5 worker nodes, each with 16 vCPU and 64 GB RAM (80 vCPU / 320 GB RAM total)
**Namespaces**: bob-demo-staging and bob-demo-prod
## Output Files
All files under payment-app-java17/infra/terraform/:
### 1. provider.tf — Provider configuration
- Kubernetes/OpenShift provider (hashicorp/kubernetes ~> 2.27)
- GitHub provider (integrations/github ~> 6.0)
- Null provider for local-exec provisioners
### 2. variables.tf — Input variables
- OpenShift: cluster URL, token
- GitHub: token, owner, repository
- Namespaces: staging/prod names (defaults: bob-demo-staging, bob-demo-prod)
- ResourceQuota settings
- PostgreSQL configuration
- All sensitive values with no defaults (must be supplied via TF_VAR_* at runtime)
### 3. main.tf — OpenShift infrastructure
Provision for **each namespace** (staging and prod):
- **Namespace** with labels and annotations
- **ResourceQuota**:
- requests.cpu: 4, limits.cpu: 8
- requests.memory: 8Gi, limits.memory: 16Gi
- **NetworkPolicy**:
- Default-deny all ingress/egress
- Allow ingress to payment-service from within namespace only
- Allow payment-service to connect to postgres-service on port 5432
- **ServiceAccount** — payment-service-sa with least-privilege RBAC (Role + RoleBinding)
- **PostgreSQL** (separate instance per namespace, no sharing):
- PersistentVolumeClaim — 5Gi storage
- Deployment — postgres:15, single replica, resource limits (1 CPU, 2Gi memory)
- Service — postgres-service on port 5432 (ClusterIP, internal only)
### 4. github-secrets.tf — GitHub Actions secrets
Provision five secrets for CI/CD pipeline:
- OPENSHIFT_SERVER — OpenShift cluster API URL
- OPENSHIFT_TOKEN — Service account token for authentication
- OPENSHIFT_REGISTRY — Internal registry URL (from: oc get route default-route -n openshift-image-registry --template='{{ .spec.host }}')
- NAMESPACE_STAGING — bob-demo-staging
- NAMESPACE_PROD — bob-demo-prod
All values read from environment variables (TF_VAR_* prefix).
### 5. outputs.tf — Output values
- Namespace names (staging/prod)
- Cluster endpoint
- PostgreSQL service endpoints (staging/prod)
- PostgreSQL ClusterIPs
- ServiceAccount names
- PVC names
- GitHub secrets status (optional)
### 6. .env.example — Environment variable template
Document all required TF_VAR_* variables with descriptions:
- TF_VAR_cluster_url — OpenShift API server URL
- TF_VAR_cluster_token — Service account token
- TF_VAR_github_token — GitHub PAT with repo scope
- TF_VAR_github_owner — GitHub organization or user
- TF_VAR_github_repository — Repository name
- TF_VAR_openshift_server — OpenShift cluster API URL (for GitHub secrets)
- TF_VAR_openshift_token — Service account token (for GitHub secrets)
- TF_VAR_openshift_registry — Internal registry URL
## Requirements
- Use placeholder values for all sensitive data — supplied via environment variables at runtime
- No hardcoded secrets in .tf files
- Separate PostgreSQL instance per namespace (no sharing between staging and prod)
- Single Terraform workspace manages both OpenShift infrastructure and GitHub secrets
- Do not apply or run any Terraform commands
PRESENTER NOTE · #25
Point out the six files — this is the complete infrastructure story in one Terraform workspace: namespaces, quotas, network policies, RBAC, PostgreSQL per namespace, and GitHub Actions secrets all wired up together. Highlight the .env.example — anyone onboarding to this repo knows exactly what they need to supply before running terraform apply.
TALKING POINT · #22
Ansible handles the configuration layer — PostgreSQL credentials, config maps, and pre-flight checks. Everything the app needs injected at runtime, wired up before the first deploy.
3c · Ansible — Configure the Environment
▼
Based on the IaC architecture diagram in payment-app-java17/infra/IaCArchitecture.md, generate an Ansible playbook to configure the OpenShift environment after Terraform provisioning.
Single cluster, two namespaces: bob-demo-staging and bob-demo-prod.
Each namespace has its own PostgreSQL instance provisioned by Terraform.
Output all files under payment-app-java17/infra/ansible/:
1. playbook.yml — main playbook targeting both namespaces
2. inventory/hosts.yml — single OpenShift cluster inventory
3. roles/payment-app/tasks/main.yml — configuration tasks for each namespace:
- Create Kubernetes Secret for PostgreSQL credentials:
DB_URL: jdbc:postgresql://postgres-service:5432/paymentdb
DB_USER: payment_user
DB_PASSWORD:
- Create ConfigMap for application configuration
- Verify service account permissions
- Wait for PostgreSQL pod to be ready before proceeding
- Run a pre-flight health check to confirm namespace is ready for deployment
Note: No image pull secret needed — OpenShift internal registry automatically grants pull access to the default service account within the same namespace.
Use placeholder values for all credentials.
Do not run the playbook.
PRESENTER NOTE · #26
Two things worth highlighting here: the PostgreSQL readiness wait — Ansible won't proceed until the database pod is actually ready, preventing the app from starting with no DB to connect to. And the pre-flight health check — the namespace must pass before the CI/CD pipeline is ever allowed to deploy into it.
TIP · #48
Talking point: "Terraform provisions the infrastructure, Ansible configures it, and the CI/CD pipeline deploys into it. Bob generated all three."
TIP · #49
You don't have to run all three prompts in a real demo — pick the one that resonates most with your audience. Infra engineers? Show the Terraform. Ops-focused? Lead with Ansible. Short on time? The diagram alone tells the full story.
Bob Produces
payment-app-java17/infra/terraform/main.tf — namespaces, quotas, network policies, RBAC, PostgreSQL + PVC per namespace
payment-app-java17/infra/terraform/provider.tf, variables.tf, outputs.tf
payment-app-java17/infra/terraform/github-secrets.tf — GitHub Actions secrets
payment-app-java17/infra/terraform/.env.example — required TF_VAR_* variables
payment-app-java17/infra/ansible/playbook.yml — PostgreSQL credentials, configmaps, readiness wait, pre-flight check
payment-app-java17/infra/ansible/inventory/hosts.yml
payment-app-java17/infra/ansible/roles/payment-app/tasks/main.yml
Demo Prep
If you want to demonstrate deployment to a live OpenShift cluster, use this environment to provision a cluster with 5 worker nodes, each configured with 16 vCPU and 64 GB RAM, for a total of 80 vCPU and 320 GB RAM.