diff --git a/modules/datastore/redis/logical/1.0/facets.yaml b/modules/datastore/redis/logical/1.0/facets.yaml new file mode 100644 index 00000000..2960f967 --- /dev/null +++ b/modules/datastore/redis/logical/1.0/facets.yaml @@ -0,0 +1,64 @@ +intent: redis +flavor: logical +version: '1.0' +clouds: +- aws +- gcp +- azure +description: Logical — a logical redis datastore hosted on an existing/shared instance + (optional db_index); re-exposes its connection outputs (no resources created). Useful + for staging consolidation where a logical cache points at a shared physical instance, + optionally on a separate logical DB index. +intentDetails: + type: Datastores + description: Logical redis datastore hosted on an existing/shared instance (no resources + created) + displayName: Redis + iconUrl: https://raw.githubusercontent.com/Facets-cloud/facets-modules-redesign/main/icons/redis.svg +spec: + title: Redis Logical (Shared Instance) + description: Logical — a logical redis datastore hosted on an existing/shared instance + (optional db_index); re-exposes its connection outputs (no resources created). + Select a source Redis resource whose full outputs are resolved into this resource; + optionally target a different logical DB index on the shared instance. + type: object + x-ui-order: + - source + - db_index + properties: + source: + type: object + title: Source Redis Datastore + description: The existing Redis datastore whose outputs this reference re-exposes. + Resolves to the selected resource's full outputs. + x-ui-output-type: '@facets/redis' + db_index: + type: number + title: Logical DB Index + description: Redis logical database index to target on the shared instance. Use + a distinct index to separate this logical cache from others sharing the same + physical instance. + minimum: 0 + maximum: 15 + default: 0 + required: + - source +inputs: {} +outputs: + default: + type: '@facets/redis' + title: Redis Reference (Passthrough) +iac: + validated_files: + - main.tf + - variables.tf + - locals.tf + - outputs.tf +sample: + kind: redis + flavor: logical + version: '1.0' + disabled: true + spec: + source: {} + db_index: 0 diff --git a/modules/datastore/redis/logical/1.0/locals.tf b/modules/datastore/redis/logical/1.0/locals.tf new file mode 100644 index 00000000..0c95e0ed --- /dev/null +++ b/modules/datastore/redis/logical/1.0/locals.tf @@ -0,0 +1,19 @@ +locals { + # Full outputs of the selected source @facets/redis datastore, resolved into + # var.instance.spec.source via the `x-ui-output-type: @facets/redis` spec field. + source_cluster = lookup(lookup(var.instance.spec.source, "interfaces", {}), "cluster", {}) + + source_endpoint = lookup(local.source_cluster, "endpoint", null) + source_connection_string = lookup(local.source_cluster, "connection_string", null) + source_auth_token = lookup(local.source_cluster, "auth_token", null) + source_port = lookup(local.source_cluster, "port", null) + source_secrets = lookup(local.source_cluster, "secrets", []) + + db_index = lookup(var.instance.spec, "db_index", 0) + + # Reflect the logical DB index in the connection string. The source + # @facets/redis connection_string has the form redis://:@: + # (no DB path), so we append / to target the logical DB. If the + # source did not expose a connection_string, leave it null. + connection_string = local.source_connection_string == null ? null : "${local.source_connection_string}/${local.db_index}" +} diff --git a/modules/datastore/redis/logical/1.0/main.tf b/modules/datastore/redis/logical/1.0/main.tf new file mode 100644 index 00000000..60e7d63e --- /dev/null +++ b/modules/datastore/redis/logical/1.0/main.tf @@ -0,0 +1,11 @@ +terraform { + required_version = ">= 1.0" +} + +# Reference (passthrough) flavour. +# +# This module deliberately declares NO resources and requires NO providers. +# It simply re-exposes the outputs of an existing Redis datastore (resolved +# into var.instance.spec.source via the `x-ui-output-type: @facets/redis` +# spec field) as a separate logical resource. See locals.tf / outputs.tf for +# the passthrough wiring. diff --git a/modules/datastore/redis/logical/1.0/outputs.tf b/modules/datastore/redis/logical/1.0/outputs.tf new file mode 100644 index 00000000..624de370 --- /dev/null +++ b/modules/datastore/redis/logical/1.0/outputs.tf @@ -0,0 +1,15 @@ +locals { + output_attributes = {} + + # Pure passthrough of the source Redis datastore's @facets/redis interface, + # with db_index reflected into the connection_string. No resources are created. + output_interfaces = { + cluster = { + endpoint = local.source_endpoint + connection_string = local.connection_string + auth_token = local.source_auth_token + port = local.source_port + secrets = local.source_secrets + } + } +} diff --git a/modules/datastore/redis/logical/1.0/variables.tf b/modules/datastore/redis/logical/1.0/variables.tf new file mode 100644 index 00000000..666c5c4a --- /dev/null +++ b/modules/datastore/redis/logical/1.0/variables.tf @@ -0,0 +1,50 @@ +variable "instance" { + description = "Logical Redis datastore hosted on an existing/shared instance — re-exposes an existing Redis datastore's outputs without provisioning any resource" + type = object({ + kind = string + flavor = string + version = string + spec = object({ + # Resolved full outputs of the selected source @facets/redis datastore. + source = object({ + attributes = optional(object({}), {}) + interfaces = optional(object({ + cluster = optional(object({ + endpoint = optional(string) + connection_string = optional(string) + auth_token = optional(string) + port = optional(string) + secrets = optional(list(string), []) + }), {}) + }), {}) + }) + # Logical Redis DB index to target on the shared instance. + db_index = optional(number, 0) + }) + }) + + validation { + condition = lookup(var.instance.spec, "db_index", 0) >= 0 && lookup(var.instance.spec, "db_index", 0) <= 15 + error_message = "db_index must be between 0 and 15" + } +} + +variable "instance_name" { + description = "The architectural name for the resource as added in the Facets blueprint designer." + type = string +} + +variable "environment" { + description = "An object containing details about the environment." + type = object({ + name = string + unique_name = string + cloud_tags = map(string) + }) +} + +variable "inputs" { + description = "A map of inputs requested by the module developer. This reference flavour requires no inputs." + type = object({}) + default = {} +}