Skip to content
This repository has been archived by the owner on Dec 13, 2023. It is now read-only.

spanner support #14

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
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
29 changes: 1 addition & 28 deletions docs/common.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,35 +165,8 @@ As Platform Engineer, in Humanitec.

Create a dedicated Kubernetes `ServiceAccount` for all our Apps, one per Workload:
```bash
cat <<EOF > custom-service-account.yaml
apiVersion: core.api.humanitec.io/v1
kind: Definition
metadata:
id: custom-service-account
object:
name: custom-service-account
type: k8s-service-account
driver_type: humanitec/template
driver_inputs:
values:
templates:
init: |
name: {{ index (regexSplit "\\\\." "\$\${context.res.id}" -1) 1 }}
manifests: |-
service-account.yaml:
location: namespace
data:
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .init.name }}
outputs: |
name: {{ .init.name }}
criteria:
- {}
EOF
humctl create \
-f custom-service-account.yaml
-f resources/yaml/custom-service-account.yaml
```
<details>
<summary>With curl.</summary>
Expand Down
32 changes: 10 additions & 22 deletions docs/gke-advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -700,15 +700,6 @@ gcloud iam service-accounts add-iam-policy-binding ${SPANNER_DB_USER_GSA_ID} \
--role roles/iam.workloadIdentityUser
```

Get the Spanner database connection string:
```bash
SPANNER_DB_CONNECTION_STRING=$(gcloud spanner databases describe ${SPANNER_DATABASE_NAME} \
--instance ${SPANNER_INSTANCE_NAME} \
--format 'get(name)')
echo ${SPANNER_DB_CONNECTION_STRING}
```
_Note: re-run the above the command until you get the value._

## [PE-HUM] Create the Spanner access resource definition

As Platform Engineer, in Humanitec.
Expand All @@ -721,12 +712,13 @@ metadata:
id: ${SPANNER_INSTANCE_NAME}-${SPANNER_DATABASE_NAME}-${ENVIRONMENT}-spanner
object:
name: ${SPANNER_INSTANCE_NAME}-${SPANNER_DATABASE_NAME}-${ENVIRONMENT}-spanner
type: redis
type: spanner
driver_type: humanitec/static
driver_inputs:
values:
host: ${SPANNER_DB_CONNECTION_STRING}
user: ${SPANNER_DB_USER_GSA_ID}
project: ${PROJECT_ID}
instance: ${SPANNER_INSTANCE_NAME}
database: ${SPANNER_DATABASE_NAME}
criteria:
- env_id: ${ENVIRONMENT}
EOF
Expand All @@ -740,12 +732,13 @@ humctl create \
cat <<EOF > ${SPANNER_INSTANCE_NAME}-${SPANNER_DATABASE_NAME}-${ENVIRONMENT}-spanner.yaml
id: ${SPANNER_INSTANCE_NAME}-${SPANNER_DATABASE_NAME}-${ENVIRONMENT}-spanner
name: ${SPANNER_INSTANCE_NAME}-${SPANNER_DATABASE_NAME}-${ENVIRONMENT}-spanner
type: redis
type: spanner
driver_type: humanitec/static
driver_inputs:
values:
host: ${SPANNER_DB_CONNECTION_STRING}
user: ${SPANNER_DB_USER_GSA_ID}
project: ${PROJECT_ID}
instance: ${SPANNER_INSTANCE_NAME}
database: ${SPANNER_DATABASE_NAME}
criteria:
- env_id: ${ENVIRONMENT}
EOF
Expand All @@ -758,8 +751,6 @@ humctl create \
```
</details>

_Note: Here we create a Redis resource definition but in a near future, this will be a Spanner resource type._

## [PE-HUM] Update the custom Service Account resource definition with the Workload Identity annotation for `cartservice`

Update the Kubernetes `ServiceAccount` to add the Workload Identity annotation for allowing the `cartservice` to access the Spanner database:
Expand All @@ -785,10 +776,8 @@ object:
apiVersion: v1
kind: ServiceAccount
metadata:
{{if hasPrefix "projects/" \${resources.redis.outputs.host} }}
annotations:
iam.gke.io/gcp-service-account: \${resources.redis.outputs.user}
{{end}}
name: {{ .init.name }}
outputs: |
name: {{ .init.name }}
Expand All @@ -799,8 +788,6 @@ humctl apply \
-f custom-service-account.yaml
```

_Note: Here we test if the `${resources.redis.outputs.host}` starts with `projects/` which is the beginning of a the connection string of the Spanner database. In a near future, we will leverage the Spanner resource type instead._

## [DE-HUM] Deploy the `cartservice` connected to the Spanner database

```bash
Expand All @@ -812,7 +799,8 @@ score-humanitec delta \
--deploy \
--retry \
-f samples/onlineboutique/cartservice/score-spanner.yaml \
--extensions samples/onlineboutique/cartservice/humanitec.score.yaml
--overrides samples/onlineboutique/cartservice/score-spanner.yaml \
--extensions samples/onlineboutique/cartservice/humanitec.score-spanner.yaml
```

## Test the Online Boutique website
Expand Down
50 changes: 50 additions & 0 deletions resources/terraform/gcp-spanner-service-account/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
## Test the Google Cloud Spanner Service Account Terraform locally

```bash
terraform init
terraform plan -var-file terraform.tfvars.example
```

## Deploy the Google Cloud Spanner Service Account Terraform Resource Definition

```bash
HUMANITEC_ORG=
LOCATION=
RESOURCE_GROUP=
AZURE_SUBCRIPTION_ID=
AZURE_SUBCRIPTION_TENANT_ID=
AZURE_SERVICE_PRINCIPAL_ID=
AZURE_SERVICE_PRINCIPAL_SECRET=

cat <<EOF > azure-blob-terraform.yaml
apiVersion: core.api.humanitec.io/v1
kind: Definition
metadata:
id: azure-blob-terraform
object:
name: azure-blob-terraform
type: azure-blob
driver_type: ${HUMANITEC_ORG}/terraform
driver_inputs:
values:
source:
path: terraform/azure-blob/
rev: refs/heads/main
url: https://github.com/mathieu-benoit/hello-humanitec.git
variables:
storage_account_location: ${LOCATION}
resource_group_name: ${RESOURCE_GROUP}
secrets:
variables:
credentials:
azure_subscription_id: ${AZURE_SUBCRIPTION_ID}
azure_subscription_tenant_id: ${AZURE_SUBCRIPTION_TENANT_ID}
service_principal_id: ${AZURE_SERVICE_PRINCIPAL_ID}
service_principal_password: ${AZURE_SERVICE_PRINCIPAL_SECRET}
criteria:
- {}
EOF

humctl create \
-f azure-blob-terraform.yaml
```
23 changes: 23 additions & 0 deletions resources/terraform/gcp-spanner-service-account/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# https://registry.terraform.io/providers/hashicorp/google/latest/docs/data-sources/service_account
resource "google_service_account" "spanner_access" {
account_id = "spanner-${var.kubernetes_namespace}-${var.kubernetes_service_account}"
description = "Account used to access the Spanner Database"
}

# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/spanner_database_iam
resource "google_spanner_database_iam_member" "spanner_access" {
instance = var.spanner_instance
database = var.spanner_database
role = "roles/spanner.databaseUser"
member = "serviceAccount:${google_service_account.spanner_access.email}"
}

#
resource "google_service_account_iam_binding" "spanner_access" {
service_account_id = google_service_account.spanner_access.name
role = "roles/iam.workloadIdentityUser"

members = [
"serviceAccount:${var.credentials.project_id}.svc.id.goog[${var.kubernetes_namespace}/${var.kubernetes_service_account}]",
]
}
3 changes: 3 additions & 0 deletions resources/terraform/gcp-spanner-service-account/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "email" {
value = google_service_account.spanner_access.email
}
14 changes: 14 additions & 0 deletions resources/terraform/gcp-spanner-service-account/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.78.0"
}
}

required_version = ">= 1.1.0"
}

provider "google" {
project = var.credentials.project_id
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
spanner_instance = "test"
spanner_database = "test"
kubernetes_namespace = "test"
kubernetes_service_account = "test"
credentials = {
project_id = "test"
}
27 changes: 27 additions & 0 deletions resources/terraform/gcp-spanner-service-account/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
variable "credentials" {
description = "The credentials for connecting to Azure."
type = object({
project_id = string
})
sensitive = true
}

variable "spanner_instance" {
description = "ID of the Google Cloud Spanner Instance that the Service Account should have access"
type = string
}

variable "spanner_database" {
description = "ID of the Google Cloud Spanner Database that the Service Account should have access"
type = string
}

variable "kubernetes_namespace" {
description = "Kubernetes namespace where the workload is"
type = string
}

variable "kubernetes_service_account" {
description = "Kubernetes service account used by the workload"
type = string
}
50 changes: 50 additions & 0 deletions resources/terraform/gcp-spanner/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
## Test the Google Cloud Spanner Service Account Terraform locally

```bash
terraform init
terraform plan -var-file terraform.tfvars.example
```

## Deploy the Google Cloud Spanner Service Account Terraform Resource Definition

```bash
HUMANITEC_ORG=
LOCATION=
RESOURCE_GROUP=
AZURE_SUBCRIPTION_ID=
AZURE_SUBCRIPTION_TENANT_ID=
AZURE_SERVICE_PRINCIPAL_ID=
AZURE_SERVICE_PRINCIPAL_SECRET=

cat <<EOF > azure-blob-terraform.yaml
apiVersion: core.api.humanitec.io/v1
kind: Definition
metadata:
id: azure-blob-terraform
object:
name: azure-blob-terraform
type: azure-blob
driver_type: ${HUMANITEC_ORG}/terraform
driver_inputs:
values:
source:
path: terraform/azure-blob/
rev: refs/heads/main
url: https://github.com/mathieu-benoit/hello-humanitec.git
variables:
storage_account_location: ${LOCATION}
resource_group_name: ${RESOURCE_GROUP}
secrets:
variables:
credentials:
azure_subscription_id: ${AZURE_SUBCRIPTION_ID}
azure_subscription_tenant_id: ${AZURE_SUBCRIPTION_TENANT_ID}
service_principal_id: ${AZURE_SERVICE_PRINCIPAL_ID}
service_principal_password: ${AZURE_SERVICE_PRINCIPAL_SECRET}
criteria:
- {}
EOF

humctl create \
-f azure-blob-terraform.yaml
```
31 changes: 31 additions & 0 deletions resources/terraform/gcp-spanner/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
resource "random_string" "spanner_instance_name" {
length = 10
special = false
lower = true
upper = false
}

resource "random_string" "spanner_database_name" {
length = 10
special = false
lower = true
upper = false
}

# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/spanner_instance
resource "google_spanner_instance" "instance" {
name = spanner_instance_name.result
config = "regional-europe-west1"
num_nodes = 1
}

# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/spanner_database
resource "google_spanner_database" "database" {
instance = google_spanner_instance.instance.name
name = spanner_database_name.result
database_dialect = "GOOGLE_STANDARD_SQL"
ddl = [
"CREATE TABLE CartItems (userId STRING(1024), productId STRING(1024), quantity INT64) PRIMARY KEY (userId, productId)",
"CREATE INDEX CartItemsByUserId ON CartItems(userId)"
]
}
3 changes: 3 additions & 0 deletions resources/terraform/gcp-spanner/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "email" {
value = google_service_account.spanner_access.email
}
19 changes: 19 additions & 0 deletions resources/terraform/gcp-spanner/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.78.0"
}

random = {
source = "hashicorp/random"
version = "~>3.0"
}
}

required_version = ">= 1.1.0"
}

provider "google" {
project = var.credentials.project_id
}
7 changes: 7 additions & 0 deletions resources/terraform/gcp-spanner/terraform.tfvars.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
spanner_instance = "test"
spanner_database = "test"
kubernetes_namespace = "test"
kubernetes_service_account = "test"
credentials = {
project_id = "test"
}
Loading