Skip to content

Commit 080c81f

Browse files
anshulsaoclaude
andauthored
feat(datastore/mysql): logical flavour (#359)
* feat(datastore/mysql): add reference flavour — passthrough of an existing mysql datastore's outputs (no resources) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PKZUrLtUbJS5GuEyRA8Vd5 * refactor(datastore/mysql): rename reference flavour to logical 'reference' clashed with Facets' cross-blueprint reference concept. 'logical' = a logical database hosted on a shared physical instance. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PKZUrLtUbJS5GuEyRA8Vd5 --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 5c575a2 commit 080c81f

4 files changed

Lines changed: 185 additions & 0 deletions

File tree

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
intent: mysql
2+
flavor: logical
3+
version: '1.0'
4+
clouds:
5+
- aws
6+
- gcp
7+
- azure
8+
description: Logical — a logical database hosted on an existing/shared MySQL instance;
9+
re-exposes its connection outputs (no resources created). Useful for staging database
10+
consolidation where several logical databases share one physical instance.
11+
intentDetails:
12+
type: Datastores
13+
description: A logical database on an existing/shared MySQL instance — re-exposes its connection outputs
14+
displayName: MySQL
15+
iconUrl: https://raw.githubusercontent.com/Facets-cloud/facets-modules-redesign/main/icons/mysql.svg
16+
spec:
17+
title: MySQL Logical Database
18+
description: Logical — a logical database hosted on an existing/shared MySQL
19+
instance; re-exposes its connection outputs (no resources created). Points at
20+
another MySQL resource (the source) and optionally overrides the logical database
21+
name in the connection string.
22+
type: object
23+
x-ui-order:
24+
- source
25+
- database_name
26+
properties:
27+
source:
28+
type: object
29+
title: Source MySQL Datastore
30+
description: The existing MySQL datastore whose outputs should be re-exposed.
31+
Resolves to the full outputs (attributes + interfaces) of the selected
32+
resource.
33+
x-ui-output-type: '@facets/mysql'
34+
database_name:
35+
type: string
36+
title: Logical Database Name
37+
description: Optional logical database to expose on the shared physical
38+
instance. When set, the re-emitted connection_string targets this database
39+
instead of the source's database.
40+
pattern: ^[a-zA-Z][a-zA-Z0-9_]*$
41+
minLength: 1
42+
maxLength: 64
43+
required:
44+
- source
45+
outputs:
46+
default:
47+
type: '@facets/mysql'
48+
title: MySQL Logical Database
49+
iac:
50+
validated_files:
51+
- main.tf
52+
- variables.tf
53+
- outputs.tf
54+
sample:
55+
kind: mysql
56+
flavor: logical
57+
version: '1.0'
58+
disabled: true
59+
spec:
60+
source: {}
61+
database_name: reporting
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
terraform {
2+
required_version = ">= 1.0"
3+
}
4+
5+
# This is a reference / passthrough flavour. It provisions NO cloud resources and
6+
# requires NO providers. It re-exposes the outputs of an existing MySQL datastore
7+
# (var.instance.spec.source) so that consumers can wire to a logical database that
8+
# shares a physical instance (e.g. staging database consolidation).
9+
#
10+
# All output wiring lives in outputs.tf.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
locals {
2+
source = var.instance.spec.source
3+
source_ifc = lookup(local.source, "interfaces", {})
4+
5+
source_reader = lookup(local.source_ifc, "reader", {})
6+
source_writer = lookup(local.source_ifc, "writer", {})
7+
8+
# Optional logical database override. When set, the connection_string is rebuilt
9+
# to target this database on the same physical host/port; otherwise the source's
10+
# connection_string and database are re-emitted unchanged.
11+
override_database = lookup(var.instance.spec, "database_name", null)
12+
13+
reader_host = lookup(local.source_reader, "host", null)
14+
reader_port = lookup(local.source_reader, "port", null)
15+
writer_host = lookup(local.source_writer, "host", null)
16+
writer_port = lookup(local.source_writer, "port", null)
17+
18+
reader_database = local.override_database != null ? local.override_database : lookup(local.source_reader, "database", null)
19+
writer_database = local.override_database != null ? local.override_database : lookup(local.source_writer, "database", null)
20+
21+
reader_connection_string = local.override_database != null ? format(
22+
"mysql://%s:%s/%s",
23+
local.reader_host,
24+
local.reader_port,
25+
local.override_database
26+
) : lookup(local.source_reader, "connection_string", null)
27+
28+
writer_connection_string = local.override_database != null ? format(
29+
"mysql://%s:%s/%s",
30+
local.writer_host,
31+
local.writer_port,
32+
local.override_database
33+
) : lookup(local.source_writer, "connection_string", null)
34+
35+
# Re-emit the @facets/mysql contract from the source.
36+
output_attributes = lookup(local.source, "attributes", {})
37+
38+
output_interfaces = {
39+
reader = {
40+
host = local.reader_host
41+
port = local.reader_port
42+
username = lookup(local.source_reader, "username", null)
43+
password = lookup(local.source_reader, "password", null)
44+
database = local.reader_database
45+
connection_string = local.reader_connection_string
46+
secrets = lookup(local.source_reader, "secrets", ["password", "connection_string"])
47+
}
48+
writer = {
49+
host = local.writer_host
50+
port = local.writer_port
51+
username = lookup(local.source_writer, "username", null)
52+
password = lookup(local.source_writer, "password", null)
53+
database = local.writer_database
54+
connection_string = local.writer_connection_string
55+
secrets = lookup(local.source_writer, "secrets", ["password", "connection_string"])
56+
}
57+
}
58+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
variable "instance" {
2+
description = "Reference (passthrough) to an existing MySQL datastore — re-exposes another MySQL resource's outputs without provisioning any cloud resource."
3+
type = object({
4+
kind = string
5+
flavor = string
6+
version = string
7+
spec = object({
8+
# source resolves (via x-ui-output-type: @facets/mysql) to the FULL outputs
9+
# of the selected MySQL resource: its attributes + interfaces (reader/writer).
10+
source = object({
11+
attributes = optional(any, {})
12+
interfaces = optional(object({
13+
reader = optional(object({
14+
host = optional(string)
15+
port = optional(number)
16+
username = optional(string)
17+
password = optional(string)
18+
database = optional(string)
19+
connection_string = optional(string)
20+
secrets = optional(list(string), [])
21+
}), {})
22+
writer = optional(object({
23+
host = optional(string)
24+
port = optional(number)
25+
username = optional(string)
26+
password = optional(string)
27+
database = optional(string)
28+
connection_string = optional(string)
29+
secrets = optional(list(string), [])
30+
}), {})
31+
}), {})
32+
})
33+
database_name = optional(string)
34+
})
35+
})
36+
}
37+
38+
variable "instance_name" {
39+
description = "The architectural name for the resource as added in the Facets blueprint designer."
40+
type = string
41+
}
42+
43+
variable "environment" {
44+
description = "An object containing details about the environment."
45+
type = object({
46+
name = string
47+
unique_name = string
48+
cloud_tags = map(string)
49+
})
50+
}
51+
52+
variable "inputs" {
53+
description = "A map of inputs requested by the module developer. This passthrough module requires none."
54+
type = object({})
55+
default = {}
56+
}

0 commit comments

Comments
 (0)