Conversion functions
The pure helpers exported by nix-tf-schema, one section per file,
rendered from their doc-comments. Every function exercised by the
conversion-test.nix suite is documented here.
Terraform schema conversion (conversion.nix)
Terraform conversion helpers: translate between Terraform provider schemas and Nix options.
tf-schema.conversion.withContext
Tag a value with an error-trace breadcrumb, so a failure deep in a schema walk says which resource, attribute or block it was walking.
The message is prefixed with [nix-tf-schema], which is what makes the
breadcrumbs greppable out of an otherwise enormous --show-trace:
nix ... --show-trace 2> >(grep "… \[nix-tf-schema\]")
builtins.addErrorContext covers a value's evaluation only as far as weak
head normal form, so wrapping a whole tree once would catch almost nothing.
The walks below therefore tag each recursion step -- the point where the
attribute or block name is still in scope -- and the trace reads back as the
path, innermost first.
Inputs
what- What was being done, as a phrase completing "while ..." (e.g.
"reading attribute
host"). value- The value to evaluate under that context.
Type
withContext :: String -> a -> a
Example
withContext "converting resource `netbox_cluster`" (resourceToOptionTypes schema)
=> <the options, or a failure whose trace names the resource>
tf-schema.conversion.wrapTfType
Fold a (possibly nested) Terraform type spec into its string form, e.g.
[ "list" "string" ] becomes "list(string)".
Inputs
tfType- A Terraform type spec: either a bare type string, or a (possibly nested) list of type constructors innermost-last.
Type
wrapTfType :: (List | String) -> String
Example
wrapTfType [ "list" "string" ]
=> "list(string)"
wrapTfType "string"
=> "string"
tf-schema.conversion.wrapTfAttr
Normalize a single Terraform attribute schema into a tfvars variable
declaration: drop schema-only keys, wrap the type, and default optionals to
null.
Inputs
attr- A single Terraform attribute schema (with a
typeand the boolean schema flags such asoptional/computed).
Type
wrapTfAttr :: AttrSet -> AttrSet
Example
wrapTfAttr { type = [ "list" "string" ]; optional = true; description = "hosts"; }
=> { type = "list(string)"; description = "hosts"; default = null; }
tf-schema.conversion.wrapTfAttrs
Wrap a set of Terraform attributes into a tfvars variable block,
excluding purely-computed attributes.
Inputs
tfAttrs- Attribute set of Terraform attribute schemas, keyed by attribute name.
Type
wrapTfAttrs :: AttrSet -> AttrSet
Example
wrapTfAttrs {
host = { type = "string"; };
id = { type = "string"; computed = true; };
}
=> { variable = { host = { type = "string"; }; }; } # `id` dropped (computed)
tf-schema.conversion.wrapTfSourceSchemas
Wrap each source schema's block attributes via
wrapTfAttrs.
Inputs
sourceSchemas- Attribute set of Terraform source schemas (each with a
block.attributes), keyed by data-source or resource name.
Type
wrapTfSourceSchemas :: AttrSet -> AttrSet
Example
wrapTfSourceSchemas {
incus_instance = { block.attributes = { name = { type = "string"; }; }; };
}
=> { incus_instance = { variable = { name = { type = "string"; }; }; }; }
tf-schema.conversion.wrapTfProvider
Wrap a provider schema's data-source and resource schemas.
Inputs
schema- A single provider's schema, as found under
provider_schemas.<provider>intofu providers schema -jsonoutput.
Type
wrapTfProvider :: AttrSet -> AttrSet
Example
wrapTfProvider {
resource_schemas.incus_instance = { block.attributes = { name = { type = "string"; }; }; };
data_source_schemas = { };
}
=> {
resource_schemas.incus_instance = { variable = { name = { type = "string"; }; }; };
data_source_schemas = { };
}
tf-schema.conversion.wrapTfProviderSchema
Wrap a full tofu providers schema -json output, stripping the
registry.opentofu.org/ prefix from provider keys.
Inputs
output- The parsed
tofu providers schema -jsonoutput (an attribute set with aprovider_schemasfield keyed by fully-qualified provider address).
Type
wrapTfProviderSchema :: AttrSet -> AttrSet
Example
wrapTfProviderSchema {
provider_schemas."registry.opentofu.org/lxc/incus" = { resource_schemas = { }; data_source_schemas = { }; };
}
=> { "lxc/incus" = { resource_schemas = { }; data_source_schemas = { }; }; }
tf-schema.conversion.tfAttrType
Module type validating a single Terraform attribute schema (its type,
description, and the boolean schema flags such as computed/optional).
Type
tfAttrType :: ModuleType
tf-schema.conversion.fromTfTypes
Convert a (possibly nested) Terraform type spec to the corresponding Nix
module type, e.g. [ "list" "string" ] to listOf str.
Inputs
tfTypes- A flattened Terraform type spec as a list of constructors, outermost first
(e.g.
[ "list" "string" ]).
Type
fromTfTypes :: List -> ModuleType
Example
fromTfTypes [ "list" "string" ]
=> listOf str # the nixpkgs option type
tf-schema.conversion.fromTfVar
Convert a single (validated) Terraform attribute to a Nix mkOption.
Throws for computed attributes, which cannot be set from Nix.
Inputs
tfAttr- A single Terraform attribute schema (validated against
tfAttrType): itstype,description, and thecomputed/optional/requiredflags.
Type
fromTfVar :: AttrSet -> Option
Example
fromTfVar { type = "string"; description = "host"; optional = true; }
=> lib.mkOption { type = nullOr str; default = null; description = "host"; }
tf-schema.conversion.fromTfVars
Convert a set of Terraform attributes to a submodule type, skipping
computed and deprecated attributes (and sensitive ones unless
allowSensitive).
Inputs
allowSensitive- Whether to keep attributes flagged
sensitive. tfAttrs- Attribute set of Terraform attribute schemas, keyed by attribute name.
Type
fromTfVars :: Bool -> AttrSet -> ModuleType
Example
fromTfVars false {
host = { type = "string"; optional = true; description = "host"; };
id = { type = "string"; computed = true; };
}
=> submodule { options.host = mkOption { type = nullOr str; default = null; }; }
# `id` dropped (computed)
tf-schema.conversion.fromTfSourceSchemas
Convert a set of source schemas to a submodule whose options are each source's variables.
Inputs
allowSensitive- Whether to keep attributes flagged
sensitive. schemas- Attribute set of Terraform source schemas (each with
block.attributes), keyed by data-source or resource name.
Type
fromTfSourceSchemas :: Bool -> AttrSet -> ModuleType
Example
fromTfSourceSchemas false {
incus_instance = { block.attributes.name = { type = "string"; required = true; description = "name"; }; };
}
=> submodule { options.incus_instance = mkOption { type = submodule { ... }; }; }
# the inner submodule carries a `name` option
tf-schema.conversion.fromTfProvider
Convert a provider schema to a submodule covering its data-source and resource schemas.
Inputs
allowSensitive- Whether to keep attributes flagged
sensitive. schema- A single provider's schema (with
resource_schemas/data_source_schemas).
Type
fromTfProvider :: Bool -> AttrSet -> ModuleType
Example
fromTfProvider false {
resource_schemas.incus_instance = { block.attributes.name = { type = "string"; required = true; description = "name"; }; };
data_source_schemas = { };
}
=> submodule {
options.resource_schemas = mkOption { ... }; # one submodule per resource
options.data_source_schemas = mkOption { ... };
}
tf-schema.conversion.fromTfProviderSchema
Convert a full tofu providers schema -json output to a submodule keyed by
provider, stripping the registry.opentofu.org/ prefix.
Inputs
allowSensitive- Whether to keep attributes flagged
sensitive. output- The parsed
tofu providers schema -jsonoutput (withprovider_schemas).
Type
fromTfProviderSchema :: Bool -> AttrSet -> ModuleType
Example
fromTfProviderSchema false {
provider_schemas."registry.opentofu.org/lxc/incus" = { resource_schemas = { }; data_source_schemas = { }; };
}
=> submodule { options."lxc/incus" = mkOption { ... }; } # one option per provider
tf-schema.conversion.mkTfModuleJson
Generate a complete Terraform module as JSON with variable blocks and
var.* references. Values flow through TF_VAR_* env vars at runtime,
keeping runtime override capability.
Inputs
spec- An attribute set describing the module:
providers(required-provider blocks),variables(a list of names or a pre-builtvariableset), optionaldata, andresource/outputblocks.
Type
mkTfModuleJson :: AttrSet -> AttrSet
Example
mkTfModuleJson {
providers = { netbox = { source = "e-breuninger/netbox"; version = "= 5.0.0"; }; };
variables = [ "name" "slug" ];
resource = { netbox_cluster_type.type = { name = "\${var.name}"; }; };
output = { id.value = "\${netbox_cluster_type.type.id}"; };
}
=> {
terraform.required_providers.netbox = { source = "e-breuninger/netbox"; version = "= 5.0.0"; };
terraform.backend.http = { };
variable = { name = { }; slug = { }; };
resource.netbox_cluster_type.type.name = "\${var.name}";
output.id.value = "\${netbox_cluster_type.type.id}";
}
tf-schema.conversion.unbrace
Strip the ${ ... } splice from a Terraform reference expression, so it
can be embedded inside a larger one.
Anything that is not spliced is returned unchanged, so this is safe to apply to a literal.
Inputs
value- A reference (or anything with a
__toString), or a plain string.
Type
unbrace :: (String | Reference) -> String
Example
unbrace (ref.var "cluster_id")
=> "var.cluster_id"
unbrace "plain"
=> "plain"
tf-schema.conversion.referenceType
A module type for a Terraform reference expression: a string spliced as
${...}, which Terraform evaluates rather than takes literally.
It accepts both a bare string written by hand and a ref chain
(an attrset carrying __toString), and merges to the rendered string, so a
definition can be handed straight to builtins.toJSON.
Warning
This is an authoring primitive for the parts of a Terraform module that are
written by hand -- data, output, extra resource attributes -- not for
schema-derived options. Those are shipped to Terraform as TF_VAR_*
environment variables, and Terraform reads a variable's value as a literal:
a ${...} placed in one lands in the plan verbatim and is never
interpolated. Schema-derived types are deliberately not widened to accept
references (which is where this departs from tofunix, whose values are baked
into the module JSON and so can hold references anywhere).
Type
referenceType :: OptionType
Example
cast (attrsOf referenceType) { id = ref.var "cluster_id"; }
=> { id = "\${var.cluster_id}"; }
tf-schema.conversion.refOr
Widen a type to also accept a Terraform reference expression.
Use it on hand-written module JSON, where a value may equally be a literal
or a pointer at another resource. See referenceType for
why schema-derived options are not widened this way.
Inputs
type- The literal type to widen.
Type
refOr :: OptionType -> OptionType
Example
cast (refOr int) 3
=> 3
cast (refOr int) (ref.var "count")
=> "\${var.count}"
tf-schema.conversion.ref
Build a Terraform reference expression by application, one path segment at a
time: ref "netbox_cluster" "main" "id" is "\${netbox_cluster.main.id}".
The result is a chain that is simultaneously callable and renderable, so
there is no terminator to remember -- every prefix of a chain is itself a
valid reference. Terraform's own top-level scopes (var, local, data,
module, each, count, self, path, terraform) are pre-seeded as
attributes, so they read as ref.var "cluster_id".
A segment that is an int, another reference, or "*" renders as a bracket
index rather than a dotted attribute.
Nothing here consults a schema: a reference is only checked by Terraform, at plan time.
Type
ref :: String -> Reference
Example
toString (ref "netbox_cluster" "main" "id")
=> "\${netbox_cluster.main.id}"
toString (ref.data "netbox_cluster" "main" "id")
=> "\${data.netbox_cluster.main.id}"
toString (ref "netbox_prefix" "pool" "*" "prefix")
=> "\${netbox_prefix.pool[*].prefix}"
toString (ref "netbox_prefix" "pool" (ref.count "index") "prefix")
=> "\${netbox_prefix.pool[count.index].prefix}"
tf-schema.conversion.resourceAttrsToOptions
Convert the settable attributes of a Terraform resource schema to Nix options.
Inputs
tfAttrs- Attribute set of Terraform resource attribute schemas, keyed by attribute name. Purely-computed attributes are skipped.
Type
resourceAttrsToOptions :: AttrSet -> AttrSet
Example
resourceAttrsToOptions {
name = { type = "string"; required = true; description = "name"; };
id = { type = "string"; computed = true; };
}
=> { name = mkOption { type = str; description = "name"; }; } # `id` dropped (computed)
tf-schema.conversion.resourceAttrsToVarRefs
Generate ${var.<name>} references for every settable attribute of a
Terraform resource schema.
Inputs
tfAttrs- Attribute set of Terraform resource attribute schemas, keyed by attribute name. Purely-computed attributes are skipped.
Type
resourceAttrsToVarRefs :: AttrSet -> AttrSet
Example
resourceAttrsToVarRefs { name = { type = "string"; required = true; }; }
=> { name = "\${var.name}"; }
tf-schema.conversion.settableTree
Recursively describe the user-settable surface of one resource schema as a tree of nodes, covering both schema dialects a provider may speak.
The dialects differ in exactly three places, and agree everywhere else -- which is why one walk handles both rather than two parallel readers:
| terraform-plugin-sdk/v2 | terraform-plugin-framework | |
|---|---|---|
| nested objects live in | block.block_types.<k> |
block.attributes.<k>.nested_type |
| "required" is spelled | min_items >= 1 |
required = true on the attribute |
| a singleton is | a list/set with max_items == 1, still encoded as a one-element list |
nesting_mode = "single", encoded as a plain object |
The singleBlock flag records that third row: it is true only for the
sdk/v2 case, and it is the one fact a renderer cannot recover from the Nix
type alone.
blockSyntax records the first row, which a renderer needs for the same
reason: an sdk/v2 nested object is a block, which configuration syntax
cannot fill from a variable and a generator must therefore emit a dynamic
block for, while a plugin-framework one is an ordinary attribute whose value
happens to be an object -- assignable directly. The nesting alone does not
tell them apart: a plural sdk/v2 block and a framework list-of-objects
attribute both read list.
The two are not alternatives to pick between per provider -- a single
resource can carry both, as incus_instance does (sdk/v2 device/file
blocks alongside a framework exec attribute), so both readers recurse
into the same plain-attribute reader.
Purely-computed attributes (those computed without optional) are
dropped, matching
settableAttrs.
Every node carries the same key set, so consumers need not branch on
dialect: path (the dotted path from the resource's root, which is what the
generators name in their error breadcrumbs), kind ("attr" or "block"),
tfType (the Terraform type spec, null for blocks), required,
optional, sensitive, description, nesting (null for plain
attributes), singleBlock, and blockSyntax. block nodes additionally
carry children, a nested tree of the same shape.
Inputs
resourceSchema- One resource schema, as found under
provider_schemas.<provider>.resource_schemas.<resource>intofu providers schema -jsonoutput.
Type
settableTree :: AttrSet -> AttrSet
Example
settableTree {
block = {
attributes.name = { type = "string"; required = true; };
block_types.smtp_server = {
nesting_mode = "list";
max_items = 1;
block.attributes.host = { type = "string"; required = true; };
};
};
}
=> {
name = { path = "name"; kind = "attr"; tfType = "string"; required = true; ... };
smtp_server = {
path = "smtp_server"; kind = "block"; nesting = "list"; singleBlock = true;
children.host = { path = "smtp_server.host"; kind = "attr"; tfType = "string"; ... };
...
};
}
tf-schema.conversion.settablePaths
Flatten settableTree
into a map from dotted path to node, dropping the children key. Nested
blocks appear both as a path of their own and via their children's paths,
so the result is a complete inventory of what a user may set on a resource
-- the input to schema-drift checks and to per-path overrides.
Inputs
resourceSchema- One resource schema (see
settableTree).
Type
settablePaths :: AttrSet -> AttrSet
Example
settablePaths {
block.block_types.smtp_server = {
nesting_mode = "list";
max_items = 1;
block.attributes.host = { type = "string"; required = true; };
};
}
=> {
"smtp_server" = { kind = "block"; singleBlock = true; ... };
"smtp_server.host" = { kind = "attr"; tfType = "string"; ... };
}
tf-schema.conversion.nodeToOptionType
Convert one
settableTree node
to a Nix module type. Plain attributes go through
fromTfTypes; nested
blocks become a submodule built recursively from their children, wrapped
per nesting mode:
nesting |
Nix type |
|---|---|
single / group |
submodule |
list / set |
listOf (submodule ...) |
map |
attrsOf (submodule ...) |
A singleBlock node is typed as a bare submodule: the user writes one
object, and it is the renderer's job to encode it as the one-element list
Terraform expects.
Inputs
node- One node of a
settableTree.
Type
nodeToOptionType :: AttrSet -> ModuleType
Example
nodeToOptionType { kind = "attr"; tfType = [ "list" "string" ]; }
=> listOf str
tf-schema.conversion.nodeToOption
Convert one
settableTree node
to a Nix option: required nodes get the bare type, optional ones a nullOr
defaulting to null, so an unset option is distinguishable from an empty
one and can be dropped from the generated Terraform config.
Note
There is deliberately no way to say "explicitly null" as distinct from
"unset". Terraform does not need one for what this generates: a resource
argument set to null behaves exactly as if it had been omitted. The
optional(...) constraints
tfTypeConstraint
renders carry no default -- a provider schema has none to give -- so the two
coincide inside object types too. tofunix
carries an unset sentinel because it bakes literals into the module JSON,
where an unset option would otherwise emit a null key into blocks that
reject one; here an unset value is simply absent from the environment and
its variable falls back to null.
Revisit if a code path ever renders optional(T, default), or needs a key
absent from a JSON payload rather than present-and-null.
Inputs
node- One node of a
settableTree.
Type
nodeToOption :: AttrSet -> Option
Example
nodeToOption { kind = "attr"; tfType = "string"; optional = true; description = "host"; }
=> lib.mkOption { type = nullOr str; default = null; description = "host"; }
tf-schema.conversion.resourceToOptionTypes
Convert a whole resource schema to Nix options, one per settable top-level attribute or nested block, recursing through both schema dialects. The schema-driven counterpart of a hand-written option set.
Inputs
resourceSchema- One resource schema (see
settableTree).
Type
resourceToOptionTypes :: AttrSet -> AttrSet
Example
resourceToOptionTypes {
block.attributes = {
name = { type = "string"; required = true; };
id = { type = "string"; computed = true; };
};
}
=> { name = mkOption { type = str; }; } # `id` dropped (computed)
tf-schema.conversion.tfTypeConstraint
Render a Terraform type spec as the HCL type-constraint expression a
variable block takes. The structural counterpart of
wrapTfType, which
only handles the collection constructors; this one also carries the
structural types (object, tuple) a schema may nest inside them.
An object spec may carry a third element listing the attributes that are
optional; those are wrapped in optional(...), without which Terraform
would read them as required and reject a value that omits them.
Inputs
tfType- A Terraform type spec: a bare type string, or a constructor list such as
[ "list" "string" ]or[ "object" { a = "string"; } [ "a" ] ].
Type
tfTypeConstraint :: (String | List) -> String
Example
tfTypeConstraint [ "map" [ "list" "string" ] ]
=> "map(list(string))"
tf-schema.conversion.nodeToTfTypeConstraint
Render one
settableTree node
as the HCL type constraint of the variable carrying it. Plain attributes
come from their Terraform type spec; a block becomes an object over its
children, with optional(...) around every non-required one, wrapped per
nesting mode:
nesting |
constraint |
|---|---|
singleton / single / group |
object({ ... }) |
list / set |
list(object({ ... })) |
map |
map(object({ ... })) |
A set block is typed as a list, matching
nodeToOptionType's
listOf: Nix has no unordered collection to feed a set(...) from.
Inputs
node- One node of a
settableTree.
Type
nodeToTfTypeConstraint :: AttrSet -> String
Example
nodeToTfTypeConstraint {
kind = "block"; nesting = "set"; singleBlock = false;
children.name = { kind = "attr"; tfType = "string"; required = true; };
}
=> "list(object({ name = string }))"
tf-schema.conversion.resourceToVariables
Convert a whole resource schema to Terraform variable blocks, one per
settable top-level attribute or nested block -- the input side of the
resource body
resourceToResourceBody
renders.
A non-required node gets default = null, so a caller that supplies no
value for it leaves the variable unset rather than failing tofu on an
unassigned variable -- and, for a block, renders as no block at all.
A type is emitted only for nested objects. A plain attribute stays untyped
(Terraform's any), which is both what the values arriving through
TF_VAR_* already validate as and what keeps the generated JSON identical
to a hand-listed variable set. A nested object's type, by contrast, is
load-bearing: without it Terraform reads the TF_VAR_* value as the string
it arrives as, rather than the object a dynamic block iterates or an
attribute takes.
Inputs
resourceSchema- One resource schema (see
settableTree).
Type
resourceToVariables :: AttrSet -> AttrSet
Example
resourceToVariables {
block.attributes = {
name = { type = "string"; required = true; };
slug = { type = "string"; optional = true; };
};
}
=> { name = { }; slug = { default = null; }; }
tf-schema.conversion.resourceToResourceBody
Convert a whole resource schema to the body of a Terraform resource
block, wiring every settable node to the variable
resourceToVariables
declares for it.
A plain attribute becomes a ${var.<name>} reference. So does a
plugin-framework nested object: it is an attribute whose value happens to be
an object, so one reference carries the whole of it.
An sdk/v2 nested object is a genuine block, which configuration syntax
cannot fill from a variable at all, so it becomes a dynamic block over
that variable. That also lets one rendering serve all three arities: an
unset optional block iterates an empty list and so renders as absent, a
singleton iterates a one-element list, and a plural block iterates the
collection itself. A literal skeleton of ${var.x} leaves could express
neither of the first two -- an unset block would still render as
present-with-null-fields.
The iterator is named after the block type rather than left at each, so a
block nested inside a block still names its own level unambiguously. A
map-nested block takes its map key as a block label, which dynamic
spells as an explicit labels.
Inputs
resourceSchema- One resource schema (see
settableTree).
Type
resourceToResourceBody :: AttrSet -> AttrSet
Example
resourceToResourceBody {
block = {
attributes.name = { type = "string"; required = true; };
block_types.domain = {
nesting_mode = "set";
block.attributes.name = { type = "string"; required = true; };
};
};
}
=> {
name = "\${var.name}";
dynamic.domain = {
for_each = "\${var.domain == null ? [] : var.domain}";
content.name = "\${domain.value.name}";
};
}
tf-schema.conversion.metaArgOptions
Options for Terraform's resource meta-arguments: the arguments every resource takes regardless of its schema, because they are handled by Terraform rather than by the provider.
Deliberately kept apart from
resourceToOptionTypes:
schema-derived options become TF_VAR_* variables, and none of these can be
one. lifecycle, depends_on and provider may not reference a variable
at all -- Terraform resolves them before variables are known -- and routing
count/for_each through a variable would put a value in the environment
that only ever describes the module's own shape. They render straight into
the resource body instead, via
metaArgsToResourceBody.
Every option defaults to null, meaning "do not emit".
Type
metaArgOptions :: AttrSet
Example
submodule { options = metaArgOptions; }
=> # a type accepting `{ count = 2; lifecycle.prevent_destroy = true; }`
tf-schema.conversion.metaArgsToResourceBody
Render meta-argument values into the fragment of a Terraform resource body
they correspond to, dropping everything left unset.
Merge it over the schema-derived body from
resourceToResourceBody;
the two cannot collide, since Terraform reserves these names.
depends_on and lifecycle.replace_triggered_by hold bare references --
HCL spells them unspliced, and the JSON syntax follows -- so a
ref handed to either is
unbraced on the way out.
Inputs
meta- Values for (a subset of)
metaArgOptions.
Type
metaArgsToResourceBody :: AttrSet -> AttrSet
Example
metaArgsToResourceBody {
count = 2;
depends_on = [ (ref "netbox_cluster" "main") ];
lifecycle.prevent_destroy = true;
}
=> {
count = 2;
depends_on = [ "netbox_cluster.main" ];
lifecycle.prevent_destroy = true;
}
tf-schema.conversion.mkProviderSchemaFile
Build a normalized provider-schema JSON file in a sandboxed derivation, for vendoring into a consumer's source tree.
Unlike
extractProviderSchemas
this returns the file itself rather than importing it, so consumers commit
the result and read it with builtins.fromJSON -- no import-from-derivation,
and therefore no need to run a provider binary during evaluation (which a
cross-architecture evaluation could not do anyway).
The output drops the data-source and provider-configuration blocks, keeps
only resource_schemas, and injects the source and version that
tofu providers schema -json does not itself report -- so the file is
self-identifying and a consumer can assert it still matches its provider.
Inputs
provider- A packaged Terraform/OpenTofu provider, as accepted by
pkgs.opentofu.withPlugins. Itsversionis used to pin and to stamp the output. source- The provider's registry source address, e.g.
"keycloak/keycloak".
Type
mkProviderSchemaFile :: { provider :: Derivation, source :: String } -> Derivation
Example
mkProviderSchemaFile { provider = pkgs.terraform-providers.keycloak_keycloak; source = "keycloak/keycloak"; }
=> <derivation provider-schema-keycloak-keycloak.json>
tf-schema.conversion.extractProviderSchemas
Extract provider schemas at build time by running tofu providers schema
in a sandboxed derivation, returning the raw schema, the wrapped
tfvars form, and the converted Nix module type.
Inputs
allowSensitive- Whether the
convertedmodule type keeps attributes flaggedsensitive. pluginFn- A plugin selector
providers: [ ... ], as accepted bypkgs.opentofu.withPlugins, choosing which providers' schemas to extract.
Type
extractProviderSchemas :: Bool -> (Providers -> List) -> AttrSet
Example
extractProviderSchemas false (p: [ p.incus ])
=> {
schema = { ... }; # raw `tofu providers schema -json` output
wrapped = { ... }; # `tfvars` variable blocks
converted = { ... }; # Nix submodule type for the provider
}
Vendored lib helpers (lib.nix)
Minimal lib helpers vendored from Fediversity's core/lib/lib.nix so this
repo has no dependency back on Fediversity's core/lib. Just the two functions
the conversion library (and its test) need: evalOption and cast.
tf-schema.lib.evalOption
Evaluate a value against a NixOS option declaration, returning the resulting config value (with the option's defaults applied).
Inputs
opts- An option declaration (e.g. the result of
lib.mkOption). conf- The value to assign to that option.
Type
evalOption :: Option -> a -> b
Example
evalOption (lib.mkOption { type = lib.types.int; }) 3
=> 3
tf-schema.lib.cast
Evaluate a value against a NixOS option type, applying the type's defaults.
A thin wrapper around evalOption
that wraps the bare type in an option declaration for you.
Inputs
type- A NixOS option type (e.g.
lib.types.int, or asubmodule). a- The value to evaluate against
type.
Type
cast :: Type -> a -> b
Example
cast (lib.types.submodule { options.x = lib.mkOption { default = 1; }; }) { }
=> { x = 1; } # the submodule's default applied