diff --git a/Data/redisCaches/README.md b/Data/redisCaches/README.md new file mode 100644 index 00000000..473caaa8 --- /dev/null +++ b/Data/redisCaches/README.md @@ -0,0 +1,30 @@ +## Overview + +The Radius.Data/redisCaches Resource Type represents Redis, an in-memory, key/value store used as an application cache. This Resource Type allows developers to create and easily connect to Redis caches as part of their Radius applications. + +Developer documentation is embedded in the Resource Type definition YAML file. Developer documentation is accessible via `rad resource-type show Radius.Data/redisCaches`. + +## Recipes + +A list of available Recipes for this Resource Type, including links to the Bicep and Terraform templates: + +|Platform| IaC Language| Recipe Name | Stage | +|---|---|---|---| +| Kubernetes | Bicep | kubernetes-redis.bicep | Alpha | +| Kubernetes | Terraform | kubernetes/main.tf | Alpha | + +## Recipe Input Properties + +Properties for the redisCaches resource are provided to the Recipe via the [Recipe Context](https://docs.radapp.io/reference/context-schema/) object. These properties include: + +- `context.properties.capacity`(enum, optional): The capacity of the Redis server. Available options are S-Small, M-Medium, and L-Large. This property allows the developer to specify the size of the Redis cache instance. If not specified, Recipes should assume `S` as the capacity. + +## Recipe Output Properties + +The RedisCaches Resource Type expects the following output properties to be set in the Results object in the Recipe: + +- `context.properties.host` (string): The hostname used to connect to the Redis server. +- `context.properties.port` (integer): The port number used to connect to the Redis server. +- `context.properties.tls` (boolean): Indicates if TLS is enabled for the Redis server. +- `context.properties.username` (string): The username for connecting to the Redis server. +- `context.properties.password` (string): The password for connecting to the Redis server. diff --git a/Data/redisCaches/recipes/kubernetes/bicep/kubernetes-redis.bicep b/Data/redisCaches/recipes/kubernetes/bicep/kubernetes-redis.bicep new file mode 100644 index 00000000..547f9acd --- /dev/null +++ b/Data/redisCaches/recipes/kubernetes/bicep/kubernetes-redis.bicep @@ -0,0 +1,109 @@ +@description('Information about the resource calling this Recipe. Generated by Radius. For more information visit https://docs.radapp.io/reference/context-schema/ ') +param context object + +extension kubernetes with { + kubeConfig: '' + namespace: context.runtime.kubernetes.namespace +} as kubernetes + +@description('Memory limits for the Redis container') +var memory ={ + S: { + memoryRequest: '512Mi' + memoryLimit: '1024Mi' + } + M: { + memoryRequest: '1Gi' + memoryLimit: '2Gi' + } + L: { + memoryRequest: '2Gi' + memoryLimit: '4Gi' + } +} + +resource redis 'apps/Deployment@v1' = { + metadata: { + name: 'redis-${uniqueString(context.resource.id)}' + } + spec: { + selector: { + matchLabels: { + app: 'redis' + resource: context.resource.name + } + } + template: { + metadata: { + labels: { + app: 'redis' + resource: context.resource.name + } + } + spec: { + containers: [ + { + name: 'redis' + image: 'redis' + ports: [ + { + containerPort: 6379 + } + ] + resources: { + requests: { + memory: memory[context.resource.properties.?capacity ?? 'S'].memoryRequest + } + limits: { + memory: memory[context.resource.properties.?capacity ?? 'S'].memoryLimit + } + } + } + { + // This container will connect to redis and stream logs to stdout for aid in development. + name: 'redis-monitor' + image: 'redis' + args: [ + 'redis-cli' + '-h' + 'localhost' + 'MONITOR' + ] + } + ] + } + } + } +} + +resource svc 'core/Service@v1' = { + metadata: { + name: 'redis-${uniqueString(context.resource.id)}' + } + spec: { + type: 'ClusterIP' + selector: { + app: 'redis' + resource: context.resource.name + } + ports: [ + { + port: 6379 + } + ] + } +} + +output result object = { + // This workaround is needed because the deployment engine omits Kubernetes resources from its output. + // This allows Kubernetes resources to be cleaned up when the resource is deleted. + // Once this gap is addressed, users won't need to do this. + resources: [ + '/planes/kubernetes/local/namespaces/${svc.metadata.namespace}/providers/core/Service/${svc.metadata.name}' + '/planes/kubernetes/local/namespaces/${redis.metadata.namespace}/providers/apps/Deployment/${redis.metadata.name}' + ] + values: { + host: '${svc.metadata.name}.${svc.metadata.namespace}.svc.cluster.local' + port: 6379 + } +} diff --git a/Data/redisCaches/recipes/kubernetes/terraform/main.tf b/Data/redisCaches/recipes/kubernetes/terraform/main.tf new file mode 100644 index 00000000..2b5efa98 --- /dev/null +++ b/Data/redisCaches/recipes/kubernetes/terraform/main.tf @@ -0,0 +1,85 @@ +terraform { + required_providers { + kubernetes = { + source = "hashicorp/kubernetes" + version = ">= 2.0" + } + } +} + +locals { + uniqueName = "redis-${substr(sha1(var.context.resource.id), 0, 8)}" + port = 6379 + namespace = var.context.runtime.kubernetes.namespace +} + +resource "kubernetes_deployment" "redis" { + metadata { + name = local.uniqueName + namespace = local.namespace + labels = { + app = "redis" + } + } + spec { + selector { + match_labels = { + app = "redis" + resource = local.uniqueName + } + } + template { + metadata { + labels = { + app = "redis" + resource = local.uniqueName + } + } + spec { + container { + name = "redis" + image = "redis:6" + resources { + requests = { + memory = var.memory[try(var.context.resource.properties.capacity, "S")].memoryRequest + } + limits = { + memory= var.memory[try(var.context.resource.properties.capacity, "S")].memoryLimit + } + } + port { + container_port = local.port + } + + } + } + } + } +} + +resource "kubernetes_service" "redis" { + metadata { + name = local.uniqueName + namespace = local.namespace + } + spec { + type = "ClusterIP" + selector = { + app = "redis" + resource = local.uniqueName + } + port { + port = local.port + target_port = local.port + } + } +} + +output "result" { + value = { + values = { + host = "${kubernetes_service.redis.metadata[0].name}.${kubernetes_service.redis.metadata[0].namespace}.svc.cluster.local" + port = local.port + } + } +} \ No newline at end of file diff --git a/Data/redisCaches/recipes/kubernetes/terraform/var.tf b/Data/redisCaches/recipes/kubernetes/terraform/var.tf new file mode 100644 index 00000000..6e000b07 --- /dev/null +++ b/Data/redisCaches/recipes/kubernetes/terraform/var.tf @@ -0,0 +1,26 @@ +variable "context" { + description = "Information about the resource calling this Recipe. Generated by Radius. For more information visit https://docs.radapp.io/reference/context-schema/" + type = any +} + +variable "memory" { + description = "Memory limits for the Redis container" + type = map(object({ + memoryRequest = string + memoryLimit = string + })) + default = { + S = { + memoryRequest = "512Mi" + memoryLimit = "1024Mi" + }, + M = { + memoryRequest = "1Gi" + memoryLimit = "2Gi" + } + L = { + memoryRequest = "2Gi" + memoryLimit = "4Gi" + } + } +} \ No newline at end of file diff --git a/Data/redisCaches/redisCaches.yaml b/Data/redisCaches/redisCaches.yaml new file mode 100644 index 00000000..a231ac62 --- /dev/null +++ b/Data/redisCaches/redisCaches.yaml @@ -0,0 +1,74 @@ +namespace: Radius.Data +types: + redisCaches: + description: | + The Radius.Data/redisCaches Resource Type deploys Redis, an in-memory, key/value store used as an application cache. + + To deploy a new Redis cache, add a RedisCaches resource to the application definition Bicep file. + + param environment string + resource redisCache 'Radius.Data/redisCaches@2025-08-01-preview' = { + name: 'redisCache' + properties: { + environment: environment + } + } + + When `capacity` is not set, the value is assumed to be `S`(Small) in Recipes. + + To connect your application to the Redis Cache, establish a connection from the container to the Redis Cache as shown below. Once connected, all Redis Cache properties are automatically injected as environment variables into the container. + + resource myContainer 'Radius.Compute/containers@2025-08-01-preview' = { + name: 'myContainer' + properties: { + environment: environment + application: myApplication.id + containers: { + frontend: { + image: 'frontend:1.25' + } + } + connections: { + redis:{ + source: redis.id + } + } + } + } + apiVersions: + '2025-08-01-preview': + schema: + type: object + properties: + environment: + type: string + description: (Required) The Radius Environment ID. Typically set by the rad CLI. Typically value should be `environment`. + application: + type: string + description: (Optional) The Radius Application ID. `myApplication.id` for example. + capacity: + type: string + enum: [S, M, L] + description: (Optional) The capacity of the Redis server. + host: + type: string + description: (Read-Only) The hostname used to connect to the Redis server. + readOnly: true + port: + type: integer + description: (Read-Only) The port used to connected to the Redis server. + readOnly: true + tls: + type: boolean + description: (Read-Only) Set to true if the Redis server requires a TLS/SSL connection. + readOnly: true + username: + type: string + description: (Read-Only) The username used to connected to the Redis server. + readOnly: true + password: + type: string + description: (Read-Only) The password used to connected to the Redis server. + readOnly: true + required: + - environment