Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions general-knowledge-base/google-saas-runtime/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Explore Google SaaS Runtime

Doc: <https://cloud.google.com/saas-runtime/docs>

## Hands on Lab

### Goals

* Define a SaaSRuntime Unit to create a basic GKE cluster.
* Define a SaaSRuntime Unit to deploy a sample K8S workload to the basic GKE
cluster.
* Build above blueprint as an OCI image. Follow
[this](https://cloud.google.com/saas-runtime/docs/create-upload-blueprint#manual_build_push)
documentation.

## References

* <https://cloud.google.com/saas-runtime/docs/overview>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
IMAGE_NAME=us-west2-docker.pkg.dev/daniellguo-anthos-dev/daniellguo-easysaas-ar/gke-cluster-bp:dev
ENGINE_TYPE=inframanager
ENGINE_VERSION=1.5.7

docker buildx build -t $IMAGE_NAME \
--platform linux/amd64,linux/arm64 \
--builder=container \
--push \
--annotation "com.easysaas.engine.type=$ENGINE_TYPE" \
--annotation "com.easysaas.engine.version=$ENGINE_VERSION" \
--provenance=false .
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Dockerfile used to build the terraform configuration files
FROM scratch
COPY --exclude=Dockerfile --exclude=.git --exclude=.gitignore --exclude=.terraform --exclude=.terraform.d . /
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# main.tf

# -----------------------------------------------------------------------------
# REQUIRED SAAS RUNTIME INPUT VARIABLES
# -----------------------------------------------------------------------------
# These variables are automatically populated by SaaS Runtime when a unit
# is created. You MUST declare them so Terraform can accept the values.
# -----------------------------------------------------------------------------

variable "tenant_project_id" {
type = string
description = "The project ID of the tenant project where resources will be deployed."
}

variable "tenant_project_number" {
type = string
description = "The project number of the tenant project."
}

# -----------------------------------------------------------------------------
# PROVIDER CONFIGURATION
# -----------------------------------------------------------------------------
# The provider now uses the injected 'project_id' from SaaS Runtime
# instead of a hardcoded value.
# -----------------------------------------------------------------------------

provider "google" {
project = var.tenant_project_id # USE THE VARIABLE HERE
region = "<replace>" # e.g., us-west2
}

# -----------------------------------------------------------------------------
# RESOURCE DEFINITION
# -----------------------------------------------------------------------------
# Your GKE cluster resource remains largely the same.
# -----------------------------------------------------------------------------

resource "google_container_cluster" "primary" {
# Add the project attribute here for clarity, using the passed-in variable.
project = var.tenant_project_id
name = "<replace>" # e.g., basic-gke-cluster
location = "<replace>" # e.g., us-west2

initial_node_count = 1

node_config {
machine_type = "e2-medium"
oauth_scopes = [
"https://www.googleapis.com/auth/cloud-platform"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# outputs.tf (FOR GKE CLUSTER UNIT)

output "gke_cluster_name" {
description = "The name of the created GKE cluster."
value = google_container_cluster.primary.name
}

output "gke_cluster_location" {
description = "The location (region) of the GKE cluster."
value = google_container_cluster.primary.location
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Dockerfile used to build the terraform configuration files
FROM scratch
COPY --exclude=Dockerfile --exclude=.git --exclude=.gitignore --exclude=.terraform --exclude=.terraform.d . /
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# main.tf (FOR K8S APP UNIT)

# -----------------------------------------------------------------------------
# PROVIDER CONFIGURATION
# -----------------------------------------------------------------------------

provider "google" {
project = var.tenant_project_id
}

# -----------------------------------------------------------------------------
# DATA SOURCE: GET GKE CLUSTER CREDENTIALS
# -----------------------------------------------------------------------------
# Use the input variables (from Unit 1) to find the cluster and get its auth data.
# -----------------------------------------------------------------------------

data "google_container_cluster" "cluster" {
project = var.tenant_project_id
name = var.gke_cluster_name
location = var.gke_cluster_location
}

# -----------------------------------------------------------------------------
# PROVIDER CONFIGURATION: KUBERNETES & HELM
# -----------------------------------------------------------------------------
# Configure the Kubernetes and Helm providers using the cluster data we just fetched.
# -----------------------------------------------------------------------------

provider "kubernetes" {
host = "https://${data.google_container_cluster.cluster.endpoint}"
cluster_ca_certificate = base64decode(data.google_container_cluster.cluster.master_auth[0].cluster_ca_certificate)
token = data.google_client_config.default.access_token
}

provider "helm" {
kubernetes = {
host = "https://${data.google_container_cluster.cluster.endpoint}"
cluster_ca_certificate = base64decode(data.google_container_cluster.cluster.master_auth[0].cluster_ca_certificate)
token = data.google_client_config.default.access_token
}
}

data "google_client_config" "default" {}

# -----------------------------------------------------------------------------
# RESOURCE: DEPLOY NGINX VIA HELM
# -----------------------------------------------------------------------------
# This creates a Helm release for NGINX from the public Bitnami chart repo.
# We set the service type to LoadBalancer so we can get an external IP.
# -----------------------------------------------------------------------------

resource "helm_release" "nginx_ingress" {
name = "my-nginx"
repository = "https://charts.bitnami.com/bitnami"
chart = "nginx"
version = "15.5.1" # Pinning version is best practice
namespace = "default"

# Set values for the Helm chart
set = [
{
name = "service.type"
value = "ClusterIP"
}
]
}

resource "time_sleep" "wait_for_service_ip" {
# This sleep will only start AFTER the helm release is "done"
depends_on = [helm_release.nginx_ingress]

create_duration = "60s"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# outputs.tf (Corrected for ClusterIP)

data "kubernetes_service" "nginx_service" {
metadata {
name = "${helm_release.nginx_ingress.name}-nginx"
namespace = helm_release.nginx_ingress.namespace
}
depends_on = [
helm_release.nginx_ingress,
time_sleep.wait_for_service_ip
]
}

output "nginx_internal_cluster_ip" {
description = "The internal cluster IP of the NGINX service."
# Read the .spec.cluster_ip instead of the load balancer status
value = data.kubernetes_service.nginx_service.spec[0].cluster_ip
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# -----------------------------------------------------------------------------
# REQUIRED SAAS RUNTIME INPUT VARIABLES
# -----------------------------------------------------------------------------
variable "tenant_project_id" {
type = string
description = "The project ID of the tenant project where resources will be deployed."
}

variable "tenant_project_number" {
type = string
description = "The project number of the tenant project."
}

# -----------------------------------------------------------------------------
# CUSTOM INPUT VARIABLES (FROM GKE CLUSTER UNIT)
# -----------------------------------------------------------------------------
# These variables will be populated by the outputs from Unit Kind 1.
# SaaS Runtime handles this mapping when you define the dependency.
# -----------------------------------------------------------------------------

variable "gke_cluster_name" {
type = string
description = "The name of the GKE cluster to deploy to (from GKE unit output)."
}

variable "gke_cluster_location" {
type = string
description = "The location of the GKE cluster (from GKE unit output)."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# versions.tf (FOR K8S APP UNIT)

terraform {
required_version = ">= 1.0"

required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.0.0"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = ">= 2.10.0"
}
helm = {
source = "hashicorp/helm"
version = ">= 2.5.0"
}
time = {
source = "hashicorp/time"
version = ">= 0.9.0"
}
}
}