Skip to content

Add Kubernetes Terraform recipe for Radius.Data/mongoDatabases - #375

Open
pujitha24 wants to merge 1 commit into
radius-project:mainfrom
pujitha24:mongodb-kubernetes-terraform-recipe
Open

pujitha24 wants to merge 1 commit into
radius-project:mainfrom
pujitha24:mongodb-kubernetes-terraform-recipe

Conversation

@pujitha24

Copy link
Copy Markdown

Summary

Adds a Kubernetes Recipe in Terraform (main.tf + var.tf) for Radius.Data/mongoDatabases, which until now only had the Azure (Cosmos DB for MongoDB) Recipe in the AKS pack. The resource type itself already exists, so acceptance criterion 1 is met and the schema is unchanged.

This picks up #21 after the earlier attempt in #51 was closed; it takes the review feedback there into account. The module lives at Data/mongoDatabases/recipes/kubernetes/terraform/. It is a Radius Recipe: it reads the context variable and returns a result output, with no separate outputs file. No properties are added to the schema, no workflow is added, and the README follows the contributing guide's structure.

The module follows the existing Terraform Kubernetes Recipes (redisCaches, postgreSqlDatabases):

  • the same hashicorp/kubernetes >= 2.37.1 constraint and locals / labels layout;
  • kubernetes_deployment with the Recreate strategy, a ClusterIP kubernetes_service, and a credentials kubernetes_secret;
  • a sensitive result output.

It behaves the same as the Bicep Recipe proposed for #20 in #374: same image, settings, probe and outputs. The one difference is the password, which comes from random_password and is kept in the Terraform state.

  • Engine: one MongoDB server from the official mongo:7.0 image. Storage is an emptyDir, matching the other non-persistent in-cluster Recipes. The WiredTiger cache is capped at 0.25 GB, and the memory request is 512Mi.
  • Why 7.0 and not 8.x: on my test VM (kernel 7.0), mongo:8.0, 8.3 and 9.0 all exit at startup with "Linux kernel versions 6.19 and newer has a known incompatibility with this version of MongoDB" (SERVER-121912). mongo:7.0 does not have that check, so it also starts on current kernels.
  • Authentication: the schema has no credential properties, so the Recipe generates the administrator password.
    • random_password (32 characters, no special characters) is stored with the user name admin in a <name>-credentials Secret. This adds a hashicorp/random >= 3.6.0 provider requirement.
    • The container reads the credentials through secret_key_ref as MONGO_INITDB_ROOT_USERNAME / MONGO_INITDB_ROOT_PASSWORD.
    • The image creates the administrator in the admin database on first start and then runs mongod with --auth.
    • The password stays in the Terraform state, so running the Recipe again keeps the password, the Pod and its data. A Pod-template annotation holds a hash of the password, so if the password is ever replaced, the Pod restarts with a matching administrator.
  • Readiness: a tcp_socket probe on the named mongodb port. While the entrypoint creates the administrator, it runs a temporary server bound to 127.0.0.1 only, so the port on the Pod IP opens only once the final server is up with authentication on.
  • Outputs:
    • values.endpoint is <name>.<namespace>.svc.cluster.local:27017.
    • values.database is database (default mongo_db, also when database is null), as the PostgreSQL Recipe returns it.
    • secrets.connectionString is mongodb://admin:<password>@<endpoint>/<database>?authSource=admin. This is the key Data/mongoDatabases/test/app.bicep already binds with secretKeyRef.
    • MongoDB creates database on the first write; the Recipe does not create it in advance.
  • Docs:
    • Adds a Kubernetes Recipe section to Data/mongoDatabases/README.md.
    • Adds a Recipe README in the Recipe directory, as the contributing guide asks.
    • Small description updates in mongoDatabases.yaml so the type description, endpoint and connectionString also describe the Kubernetes Recipe. These are description-only, with no schema change, and match the Bicep PR's text exactly.

About the Kubernetes Recipe Pack: this PR leaves recipe-packs/kubernetes/default.bicep unchanged. #21 does not ask for a pack entry. That pack has one entry per resource type, and every entry is kind: 'bicep' with a ghcr.io/radius-project/kube-recipes/... OCI source; nothing in the repository publishes Terraform modules to a registry. The pack's Radius.Data/mongoDatabases entry is added by the Bicep Recipe for #20 (#374). The CI-generated terraformrecipepack picks this module up automatically.

Reason for change

Radius.Data/mongoDatabases had no Terraform Recipe for Kubernetes.

Fixes #21

How to test

On a cluster with Radius installed:

make build-resource-type TYPE_FOLDER=Data/mongoDatabases
RECIPE_PLATFORM_FILTER=kubernetes make build
RECIPE_PLATFORM_FILTER=kubernetes make generate-recipe-pack PACK_NAME=terraformrecipepack OUTPUT_FILE=recipe-pack-terraform.bicep
make deploy-recipe-pack BICEP_FILE=recipe-pack-terraform.bicep
make update-env-recipe-pack RECIPE_PACK_NAME=terraformrecipepack
./.github/scripts/test-recipe.sh Data/mongoDatabases/recipes/kubernetes/terraform default

To check authentication by hand after rad deploy Data/mongoDatabases/test/app.bicep:

CS=$(kubectl get secret -n <namespace> <mongo-secrets-name> -o jsonpath='{.data.connectionString}' | base64 -d)
kubectl exec -n <namespace> deploy/mongo -- mongosh "$CS" --quiet --eval 'db.items.insertOne({a: 1}); db.items.countDocuments()'

What I validated locally:

  • terraform fmt -check on the Recipe directory (Terraform 1.16.4): clean.
  • terraform init -backend=false and terraform validate: valid. The providers resolved to hashicorp/kubernetes 3.3.0 and hashicorp/random 3.9.1. The only warnings are the provider's deprecation notices for kubernetes_deployment / kubernetes_service / kubernetes_secret (use the _v1 variants), which the existing Redis and PostgreSQL Terraform Recipes also produce. I kept the unversioned resources to match them.
  • terraform console with sample Recipe contexts: local.database resolves to mongo_db when database is absent or null, and to the given name otherwise. local.host is <name>.<namespace>.svc.cluster.local.
  • make validate-recipe-packs: pass. cspell 10.3.2 with .github/linters/.cspell.yml on the changed files: 0 issues. mongoDatabases.yaml parses as YAML.
  • Checked the settings against the mongo 7.0 image's docker-entrypoint.sh: how it handles MONGO_INITDB_ROOT_*, --auth, the 127.0.0.1-only init server and --bind_ip_all.

Live test on a cluster: I ran the same steps as the terraform matrix of Validate Resource Types and Recipes, on a local kind cluster created with make create-radius-cluster (Radius CLI edge):

RECIPE_PLATFORM_FILTER=kubernetes make build
RECIPE_PLATFORM_FILTER=kubernetes make generate-recipe-pack PACK_NAME=terraformrecipepack OUTPUT_FILE=recipe-pack-terraform.bicep
make deploy-recipe-pack BICEP_FILE=recipe-pack-terraform.bicep
make update-env-recipe-pack RECIPE_PACK_NAME=terraformrecipepack ENVIRONMENT=default
RECIPE_PLATFORM_FILTER=kubernetes make test RESOURCE_TYPE_ROOT=Data/mongoDatabases ENVIRONMENT=default RECIPE_TYPE=terraform

Data/mongoDatabases/test/app.bicep deployed with mongo (Radius.Data/mongoDatabases) and democontainer (Radius.Compute/containers, which reads secrets.connectionString), and the run reported Passed: 1, Failed: 0. The cleanup step then deleted the Deployments, Services and secrets.

rad deploy does not wait for the MongoDB Pod to become ready, so I also deployed the test app by hand on the same cluster and checked:

  • The mongo Pod became ready, and the resource showed endpoint mongo.<namespace>.svc.cluster.local:27017 and database mongo_db.
  • mongosh with the connection string from the managed secret, going through the Service DNS name, wrote and read a document in mongo_db.
  • Without credentials, insert failed with "requires authentication", and a wrong password failed with "Authentication failed".
  • After a second rad deploy, the password was unchanged, the same Pod was still running, and the document was still there.

The test VM is arm64 and ghcr.io/radius-project/samples/demo is amd64-only, so democontainer itself could not run there (exec format error). That is why the client check above used mongosh. The CI workflow repeats the test on amd64 once a maintainer approves it.

Automated coverage: no new test file is needed. Data/mongoDatabases/test/app.bicep already exists. The terraform matrix builds every */recipes/kubernetes/terraform Recipe into a generated pack and deploys each type's test/app.bicep, so this PR puts the MongoDB Terraform Recipe into that run. The test app binds secrets.connectionString through secretKeyRef, so the run fails if the Recipe does not return that key.

File change summary

File Summary of change
Data/mongoDatabases/recipes/kubernetes/terraform/main.tf New Kubernetes Terraform Recipe: MongoDB 7.0 kubernetes_deployment with authentication + ClusterIP kubernetes_service + credentials kubernetes_secret from random_password, sensitive result with endpoint, database and secrets.connectionString.
Data/mongoDatabases/recipes/kubernetes/terraform/var.tf The context variable, as in the Redis Terraform Recipe.
Data/mongoDatabases/recipes/kubernetes/terraform/README.md New Recipe README: description and how to register the module in a Recipe Pack.
Data/mongoDatabases/README.md Adds a Kubernetes Recipe section (behavior, limits, outputs, and how to wire the Terraform module into a pack).
Data/mongoDatabases/mongoDatabases.yaml Description-only: mentions the Kubernetes Recipe and what endpoint / connectionString contain on Kubernetes.

🤖 Generated with Claude Code

Add a Kubernetes Recipe in Terraform that runs a single MongoDB 7.0
server from the official mongo image, with authentication enabled. The
administrator password comes from random_password and is kept in the
Terraform state, stored in a Kubernetes Secret, and returned inside
secrets.connectionString together with endpoint and database.

Document the Recipe in the resource type README and a Recipe README.

Fixes radius-project#21

Signed-off-by: Pujitha Paladugu <10557236+pujitha24@users.noreply.github.com>
Assisted-by: claude-opus-5-5 (via Claude Code)
@pujitha24
pujitha24 requested review from a team as code owners October 2, 2026 22:19
Copilot AI balanced review requested due to automatic review settings October 2, 2026 22:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Database input handling can produce unusable connection strings or select an unintended database.

Review effort: Balanced
Findings: 2 Medium severity

Open (2)
What changed in this PR

Adds a Kubernetes Terraform recipe for the existing Radius.Data/mongoDatabases resource type, addressing #21.

Changes:

  • Deploys an authenticated MongoDB server with ephemeral storage, a Service, and generated credentials.
  • Returns endpoint, database, and secret-backed connection details.
  • Documents usage and updates schema descriptions without changing the schema contract.
File Description
Data/​mongoDatabases/​recipes/​kubernetes/​terraform/​var.tf Defines the Radius context input.
Data/​mongoDatabases/​recipes/​kubernetes/​terraform/​README.md Documents recipe behavior and registration.
Data/​mongoDatabases/​recipes/​kubernetes/​terraform/​main.tf Implements MongoDB deployment, credentials, and outputs.
Data/​mongoDatabases/​README.md Adds Kubernetes behavior, limitations, and usage guidance.
Data/​mongoDatabases/​mongoDatabases.yaml Updates descriptions for Kubernetes support.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

tag = "7.0"
username = "admin"
database_input = try(var.context.resource.properties.database, null)
database = local.database_input != null ? local.database_input : "mongo_db"
# string sets authSource=admin and selects `database` as the default
# database. Radius materializes it into the managed Radius.Security/secrets
# resource; it is never written onto the resource.
connectionString = "mongodb://${local.username}:${random_password.password.result}@${local.host}:${local.port}/${local.database}?authSource=admin"

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Kubernetes MongoDB Recipe - Terraform

2 participants