Manages a keystone Snowflake database (
snowflake_database.this) and the database roles scoped to its lifecycle (snowflake_database_role,for_each). Targetssnowflakedb/snowflake~> 2.17(verified against providerv2.18.0).
- βοΈ Creates exactly one keystone
snowflake_database.thisβ a standard (or transient) Snowflake database, with every account-inheritable parameter (retention, task defaults, log levels, Iceberg catalog/serialization settings) modeled as an explicit, deeply-typed variable. - π§© Creates zero or more
snowflake_database_rolechildren viafor_eachovervar.database_roles, keyed by role name β a database role only ever makes sense inside exactly one database, so its lifecycle lives here, not intf-mod-snowflake-role. - π Optionally references a
tf-mod-snowflake-external-volumeinstance'sfully_qualified_nameas this database's default Iceberg external volume β never creates the volume itself. - π Never accepts a grant, a credential, or an account/organization/role identifier as a
variable β grants are handled entirely by
tf-mod-snowflake-role-grant-bundleandtf-mod-snowflake-database-role-grant-bundle, and auth/role-context is the caller's provider configuration. - π§± Secure-by-default throughout: no implicit database roles, no forced retention override, no
destructive
PUBLIC-schema drop, no replication/failover unless explicitly configured.
π‘ Why it matters: every other data-platform module in this library β schemas, grant bundles, tags β ultimately anchors to a database's
fully_qualified_name. Getting this one composite right (secure defaults, an honest type contract, no silent account-level overrides) means every module built on top of it inherits that same discipline for free.
If these Terraform modules have been helpful to you or your organization, I'd appreciate your support in any of the following ways:
- β Star this repository to help others discover this Terraform module.
- π€ Connect with me on LinkedIn: linkedin.com/in/microsoftexpert
- β Buy me a coffee: buymeacoffee.com/microsoftexpert
Whether it's a star, a professional connection, or a coffee, every gesture helps keep these modules actively maintained and continually improving. Thank you for being part of the community!
graph TD
EXTVOL["tf-mod-snowflake-external-volume"] -->|"external_volume (optional input)"| DB
DB["tf-mod-snowflake-database (this module)"] --> KEYSTONE["snowflake_database.this"]
DB -->|"fully_qualified_name"| SCHEMA["tf-mod-snowflake-schema"]
DB -->|"fully_qualified_name"| ROLEGRANT["tf-mod-snowflake-role-grant-bundle"]
DB -->|"database_roles map"| DBROLEGRANT["tf-mod-snowflake-database-role-grant-bundle"]
style DB fill:#29B5E8,color:#ffffff
style KEYSTONE fill:#11567F,color:#ffffff
style EXTVOL fill:#EDEDED,color:#333333
style SCHEMA fill:#EDEDED,color:#333333
style ROLEGRANT fill:#EDEDED,color:#333333
style DBROLEGRANT fill:#EDEDED,color:#333333
Validated via the Mermaid Chart MCP (validate_and_render_mermaid_diagram) before embedding β
diagram type flowchart, valid: true.
graph TD
VARS["var.name, var.comment, var.is_transient,\nvar.data_retention_time_in_days,\nvar.replication,...(caller config)"] --> DB["snowflake_database.this"]
ROLES["var.database_roles\n(map, for_each)"] --> CHILD["snowflake_database_role.children[each.key]"]
DB -->|"fully_qualified_name (parent)"| CHILD
DB --> OUT1["fully_qualified_name / name / id"]
CHILD --> OUT2["database_roles map output"]
style DB fill:#11567F,color:#ffffff
style CHILD fill:#11567F,color:#ffffff
style VARS fill:#EDEDED,color:#333333
style ROLES fill:#EDEDED,color:#333333
style OUT1 fill:#29B5E8,color:#ffffff
style OUT2 fill:#29B5E8,color:#ffffff
Validated via the Mermaid Chart MCP β diagram type flowchart, valid: true.
Resource inventory
| Resource | Cardinality | Role |
|---|---|---|
snowflake_database.this |
Exactly 1 (keystone) | The database itself |
snowflake_database_role.children |
0..N (for_each over var.database_roles) |
Database roles scoped to this database |
| Requirement | Value |
|---|---|
| Terraform | >= 1.12.0 |
snowflakedb/snowflake provider |
~> 2.17 (Phase-1 grounding pulled and validated against v2.18.0) |
| Provider block | Not present in this module β the caller's root configuration owns provider "snowflake" {}, the account identifier, and every credential |
Schema notes that bite (resource-specific β see this module suite's cross-cutting notes for the provider-wide gotchas that apply to every module):
is_transientis force-new, and the provider does not detect external changes to database type β if a live database's transient/standard type diverges from this configuration outside Terraform, the fix is a manual destroy/recreate, not an in-placeapply.- A database cannot be dropped while it still has network-rule/network-policy associations β
destroying
snowflake_database.thisin that state fails atapplywith a Snowflake-side error (098507 (2BP01)), not a Terraform validation error; unassign the association first (see the provider's../guides/unassigning_policies). database(onsnowflake_database_role) accepts afully_qualified_namedirectly β confirmed against the provider's own Example Usage, which passessnowflake_database.test_database.fully_qualified_namestraight intodatabase. This module relies on that pass-through forsnowflake_database_role.children.database.- Both resources expose a provider-SDK
timeouts {}meta-block (create/delete/read/update), confirmed present in the live schema forsnowflake_databaseandsnowflake_database_role. Per this module suite's universal-tail convention (commentonly, nevertimeouts), this module does not expose it as a variable β this is a deliberate v1.0.0 scope decision, not an oversight. - The provider's own import guidance for
snowflake_databasereferences awith_managed_accessfield that does not exist anywhere in this resource's schema (it belongs tosnowflake_schema) β apparent documentation copy/paste artifact upstream. Onlyis_transientneeds to be set explicitly before import here; see π Troubleshooting. replicationis a Block List Max 1; its nestedenable_to_accountis a Block List Min 1 within that one block β adding/removing a replication target is a change to the singlereplicationblock as a whole, not an independentfor_eachresource.
βΉοΈ Neither
snowflake_databasenorsnowflake_database_role's own Terraform docs page carries a dedicated "required privileges" subsection (confirmed during Phase-1 grounding) β the list below is sourced from Snowflake's ownCREATE DATABASE/CREATE DATABASE ROLESQL reference, not the Terraform provider docs. Treat it as a least-privilege starting point, not an exhaustive, provider-guaranteed list.
CREATE DATABASEon the account β typicallySYSADMIN, or a role explicitly grantedCREATE DATABASEat the account level β to create the keystonesnowflake_database.this.CREATE DATABASE ROLEon the database (ownership of the database, or an explicit grant of this privilege) β to create eachfor_eachchild insnowflake_database_role.children.- If
var.replicationis populated: treats enabling replication as anACCOUNTADMIN-or-delegated-organization-privilege action. Settingreplication.ignore_edition_check = truebypasses an edition/compliance safeguard β route through Compliance/Legal before using it against a Business Critical (or higher) primary, per this organization's regulatory-flagging posture.
- No
preview_features_enabledflag required β bothsnowflake_databaseandsnowflake_database_roleare GA (subcategory: "Stable") as of providerv2.18.0. - If
var.external_volumeis set, the referenced external volume must already exist (created by atf-mod-snowflake-external-volumeinstance) β this module does not create or check for it at plan time. - If
var.replicationis populated, everyenable_to_account[*].account_identifiermust already be a member of the same Snowflake organization ("<organization_name>"."<account_name>"format). Replicating from a Business Critical (or higher) primary to a lower-edition secondary, or to an account with no equivalent HIPAA/HITRUST business associate agreement, is blocked unlessignore_edition_check = trueβ confirm the compliance implications first.
tf-mod-snowflake-database/
βββ providers.tf # required_providers + required_version β no provider {} block
βββ variables.tf # name, database-level parameters, replication, database_roles map
βββ main.tf # snowflake_database.this + snowflake_database_role.children (for_each)
βββ outputs.tf # fully_qualified_name, name, id, database_roles map
βββ README.md # this file
βββ SCOPE.md # cross-module contract, privileges, prerequisites, gotchas
βββ examples/ # runnable example call sites
module "core_database" {
source = "git::https://github.com/microsoftexpert/tf-mod-snowflake-database.git?ref=v1.0.0"
name = "ANALYTICS"
}The caller's root module configures provider "snowflake" {} (including any role alias) and
authentication β this module never declares either. The call above produces a standard
(non-transient) database, no explicit retention override (inherits the account default), no
database roles, and no replication β the safe, empty-call default.
Consumes
| Input | Type | Source module |
|---|---|---|
external_volume |
string (optional, fully_qualified_name) |
tf-mod-snowflake-external-volume |
Every other input (name, is_transient, retention/catalog/collation/serialization/log-level/
task-default parameters, replication, database_roles) is caller-authored configuration, not a
sibling-module reference.
Emits
| Output | Description | Consumed by |
|---|---|---|
fully_qualified_name |
The database's fully-qualified identifier | tf-mod-snowflake-schema (database input), tf-mod-snowflake-role-grant-bundle, tf-mod-snowflake-database-role-grant-bundle |
name |
The database's bare name | Documentation / display only |
id |
The database's Terraform resource id | Import / drift-detection tooling |
database_roles |
Map of role name -> { fully_qualified_name, id }, keyed identically to var.database_roles |
tf-mod-snowflake-database-role-grant-bundle |
1 Β· Smallest possible call
module "core_database" {
source = "git::https://github.com/microsoftexpert/tf-mod-snowflake-database.git?ref=v1.0.0"
name = "ANALYTICS"
}π‘ Every house-secure default applies:
is_transient = false,comment = null,data_retention_time_in_days = null(inherit account default),database_roles = {},replication = null.
2 Β· Explicit data retention override
module "compliance_database" {
source = "git::https://github.com/microsoftexpert/tf-mod-snowflake-database.git?ref=v1.0.0"
name = "COMPLIANCE_ARCHIVE"
data_retention_time_in_days = 90
comment = "Extended Time Travel retention for compliance archival"
}βΉοΈ The account default is left untouched everywhere else β only this database's retention is raised above whatever the account inherits.
3 Β· Transient database
module "scratch_database" {
source = "git::https://github.com/microsoftexpert/tf-mod-snowflake-database.git?ref=v1.0.0"
name = "ETL_SCRATCH"
is_transient = true
comment = "Ephemeral ETL staging β no Fail-safe protection, cost-optimized"
}
β οΈ is_transientis force-new and the provider does not detect external drift on this field β if someone runsCREATE OR REPLACE DATABASE... TRANSIENToutside Terraform, no diff will surface; correcting it requires a manual destroy/recreate. Set it explicitly before importing an existing database to avoid a surprise diff on the next plan.
4 Β· Referencing an external volume
module "iceberg_data" {
source = "git::https://github.com/microsoftexpert/tf-mod-snowflake-database.git?ref=v1.0.0"
name = "ICEBERG_DATA"
external_volume = module.iceberg_ext_volume.fully_qualified_name
}βΉοΈ
module.iceberg_ext_volumeis atf-mod-snowflake-external-volumeinstance, referenced here only by its documentedfully_qualified_nameoutput (per that module's own scaffold β it has not yet been code-authored in this library pass, so re-verify the output name once it has). This module never creates the volume itself; it must already exist.
5 Β· Database roles (a few, by name)
module "core_database" {
source = "git::https://github.com/microsoftexpert/tf-mod-snowflake-database.git?ref=v1.0.0"
name = "ANALYTICS"
database_roles = {
"ANALYST_RO" = { comment = "Read-only analyst access" }
"ETL_WRITER" = { comment = "ETL pipeline write access" }
}
}6 Β· Database roles at scale (for_each, generated)
locals {
# One database role per financial-services association's read-only analyst team.
association_codes = ["ASSOC01", "ASSOC02", "ASSOC03", "ASSOC04", "ASSOC05"]
}
module "core_database" {
source = "git::https://github.com/microsoftexpert/tf-mod-snowflake-database.git?ref=v1.0.0"
name = "ANALYTICS"
database_roles = {
for code in local.association_codes :
"${code}_ANALYST_RO" => { comment = "Read-only analyst access for ${code}" }
}
}π‘ Because
database_rolesis amap(object(...))iterated withfor_each(nevercount), adding a sixth association code tolocal.association_codescreates exactly one newsnowflake_database_roleand leaves the other five untouched.
7 Β· Task-default parameters overridden
module "pipeline_database" {
source = "git::https://github.com/microsoftexpert/tf-mod-snowflake-database.git?ref=v1.0.0"
name = "PIPELINE_ORCHESTRATION"
user_task_managed_initial_warehouse_size = "LARGE"
user_task_timeout_ms = 3600000
user_task_minimum_trigger_interval_in_seconds = 120
suspend_task_after_num_failures = 10
task_auto_retry_attempts = 3
}βΉοΈ
user_task_managed_initial_warehouse_sizecarries novalidation {}block in this module β the resource's own schema does not enumerate its legal values inline (see π₯ Inputs / SCOPE.md). A typo surfaces as a Snowflake-side error atapply, not atvalidate.
8 Β· Serialization / log-level enums, explicit
module "iceberg_observability_database" {
source = "git::https://github.com/microsoftexpert/tf-mod-snowflake-database.git?ref=v1.0.0"
name = "ICEBERG_OBSERVABLE"
storage_serialization_policy = "OPTIMIZED"
log_level = "WARN"
log_event_level = "ERROR"
trace_level = "ON_EVENT"
}βΉοΈ
trace_level's legal values (ALWAYS,ON_EVENT,PROPAGATE,OFF) are a different set thanlog_level/log_event_level's (TRACE,DEBUG,INFO,WARN,ERROR,FATAL,OFF) β each has its ownvalidation {}block; a value from the wrong set fails atterraform validate.
9 Β· Replication + failover
module "primary_database" {
source = "git::https://github.com/microsoftexpert/tf-mod-snowflake-database.git?ref=v1.0.0"
name = "CORE_LEDGER"
replication = {
enable_to_account = [
{ account_identifier = "\"casey_ORG\".\"casey_ACCOUNT_DR\"", with_failover = true }
]
ignore_edition_check = null
}
}π Enabling replication/failover is an elevated, organization-scoped operation β treats it as an
ACCOUNTADMIN-or-delegated-organization-privilege action (see π Required Snowflake Privileges).ignore_edition_checkis leftnullhere; setting it totruebypasses a Business-Critical-edition/BAA safeguard and requires Compliance/Legal sign-off first β never flip it without that review.
10 Β· Dropping the PUBLIC schema on creation
module "no_public_schema_database" {
source = "git::https://github.com/microsoftexpert/tf-mod-snowflake-database.git?ref=v1.0.0"
name = "LOCKED_DOWN_DB"
drop_public_schema_on_creation = true
}
β οΈ drop_public_schema_on_creationdefaults tofalse(house secure default β a destructive, creation-time-only option must never default to on). Only effective at creation; toggling it later on an existing database has no effect.
11 Β· Case-sensitivity / diagnostic toggles
module "legacy_migrated_database" {
source = "git::https://github.com/microsoftexpert/tf-mod-snowflake-database.git?ref=v1.0.0"
name = "LEGACY_MIGRATED"
quoted_identifiers_ignore_case = true
replace_invalid_characters = true
enable_console_output = true
}βΉοΈ
quoted_identifiers_ignore_casein particular is worth setting explicitly before importing an existing database β import does not always populate every optional field from live state, and this one changes case-folding behavior for every quoted identifier in the database.
12 Β· Metadata / governance fields
module "governed_database" {
source = "git::https://github.com/microsoftexpert/tf-mod-snowflake-database.git?ref=v1.0.0"
name = "GOVERNED_ANALYTICS"
comment = "Owned by Data Governance β see Confluence DG-142"
catalog = "OPEN_CATALOG_REF"
default_ddl_collation = "en_US"
}13 Β· ποΈ End-to-end composition
Wires this module's fully_qualified_name into tf-mod-snowflake-schema's database input, and
one entry of its database_roles output into tf-mod-snowflake-database-role-grant-bundle's
grant map, exactly as documented in this module's own SCOPE.md Emits table.
module "core_database" {
source = "git::https://github.com/microsoftexpert/tf-mod-snowflake-database.git?ref=v1.0.0"
name = "ANALYTICS"
database_roles = {
"ANALYST_RO" = { comment = "Read-only analyst access" }
"ETL_WRITER" = { comment = "ETL pipeline write access" }
}
}
module "reporting_schema" {
source = "git::https://github.com/microsoftexpert/tf-mod-snowflake-schema.git?ref=v1.0.0"
database = module.core_database.fully_qualified_name
name = "REPORTING"
}
module "analyst_ro_grants" {
source = "git::https://github.com/microsoftexpert/tf-mod-snowflake-database-role-grant-bundle.git?ref=v1.0.0"
database_role_fully_qualified_name = module.core_database.database_roles["ANALYST_RO"].fully_qualified_name
grants = {
"reporting_schema_usage" = {
on_schema = { schema_name = module.reporting_schema.fully_qualified_name }
privileges = ["USAGE"]
}
}
}βΉοΈ
tf-mod-snowflake-schema'sdatabaseinput is code-verified against its ownvariables.tfin this library.tf-mod-snowflake-database-role-grant-bundle'sdatabase_role_fully_qualified_name/grantsshape is sourced from that module's own SCOPE.md (that module has not yet been authored in this library) β re-verify field names once that module'svariables.tfexists.
Keystone (snowflake_database.this): name (required); is_transient, comment,
data_retention_time_in_days, max_data_extension_time_in_days, external_volume, catalog,
default_ddl_collation, storage_serialization_policy, replace_invalid_characters, log_level,
log_event_level, trace_level, suspend_task_after_num_failures, task_auto_retry_attempts,
user_task_managed_initial_warehouse_size, user_task_timeout_ms,
user_task_minimum_trigger_interval_in_seconds, quoted_identifiers_ignore_case,
enable_console_output, drop_public_schema_on_creation, replication (all optional).
Children: database_roles (optional map(object({ comment })), default {}).
Full object schemas
variable "name" {
type = string # required
}
variable "is_transient" {
type = bool
default = false
}
variable "comment" {
type = string
default = null
}
variable "data_retention_time_in_days" {
type = number
default = null
}
variable "max_data_extension_time_in_days" {
type = number
default = null
}
variable "external_volume" {
type = string # fully_qualified_name of a tf-mod-snowflake-external-volume instance
default = null
}
variable "catalog" {
type = string
default = null
}
variable "default_ddl_collation" {
type = string
default = null
}
variable "storage_serialization_policy" {
type = string # COMPATIBLE | OPTIMIZED
default = null
}
variable "replace_invalid_characters" {
type = bool
default = null
}
variable "log_level" {
type = string # TRACE | DEBUG | INFO | WARN | ERROR | FATAL | OFF
default = null
}
variable "log_event_level" {
type = string # TRACE | DEBUG | INFO | WARN | ERROR | FATAL | OFF
default = null
}
variable "trace_level" {
type = string # ALWAYS | ON_EVENT | PROPAGATE | OFF
default = null
}
variable "suspend_task_after_num_failures" {
type = number
default = null
}
variable "task_auto_retry_attempts" {
type = number
default = null
}
variable "user_task_managed_initial_warehouse_size" {
type = string # unvalidated β see SCOPE.md / README Β§6
default = null
}
variable "user_task_timeout_ms" {
type = number
default = null
}
variable "user_task_minimum_trigger_interval_in_seconds" {
type = number
default = null
}
variable "quoted_identifiers_ignore_case" {
type = bool
default = null
}
variable "enable_console_output" {
type = bool
default = null
}
variable "drop_public_schema_on_creation" {
type = bool
default = false
}
variable "replication" {
type = object({
enable_to_account = list(object({
account_identifier = string
with_failover = optional(bool, false)
}))
ignore_edition_check = optional(bool, null)
})
default = null
}
variable "database_roles" {
type = map(object({
comment = optional(string, null)
}))
default = {}
}| Output | Description | Sensitive? |
|---|---|---|
fully_qualified_name |
The database's fully-qualified identifier β the safe cross-reference for sibling modules | No |
name |
The database's bare name | No |
id |
The database's Terraform resource id | No |
database_roles |
Map of role name -> { fully_qualified_name, id }, keyed identically to var.database_roles |
No |
is_transientis force-new and drift-blind. Changing it in configuration destroys and recreatessnowflake_database.thisand everydatabase_roleschild beneath it; a live out-of-band type change produces no plan diff at all (see β Schema notes that bite). Set it deliberately, and set it explicitly before anyterraform import.database_rolesis keyed by role name, never a synthetic index.for_each(nevercount) means adding or removing one entry from the map creates or destroys exactly that onesnowflake_database_role, leaving every sibling role's state untouched β this is the property the wholemap(object(...))+for_eachpattern exists to guarantee.replicationis rendered as adynamicblock wrapping a nesteddynamicblock. The outerdynamic "replication"is gated onvar.replication != null; the innerdynamic "enable_to_account"is keyed internally byaccount_identifierso that reordering entries doesn't necessarily force-replace unrelated ones β but togglingreplicationitself on/off always touches the singlereplicationblock as a whole (see SCOPE.md Provider gotchas).snowflake_database_role.children.databasealways referencessnowflake_database.this.fully_qualified_name, confirmed accepted directly by the provider's own Example Usage β never a barename, and never a caller-supplied variable, since this module is the database's own owner.- No secret-bearing field exists on either resource β nothing in this module's variable schema
needs
sensitive = true.
This module follows this module suite's Secure-by-default convention. Applied here:
| Concern | Secure default in this module | Opt-out |
|---|---|---|
| Object comment | comment = null |
Caller sets it explicitly |
| Data retention | data_retention_time_in_days = null (inherit account default, never forced to 0) |
Caller sets an explicit value |
| Database type | is_transient = false (keeps Fail-safe protection) |
Caller sets true explicitly |
| Destructive schema drop | drop_public_schema_on_creation = false |
Caller sets true explicitly, creation-time only |
| Role hierarchy | database_roles = {} (no implicit roles) |
Caller populates the map explicitly, per role |
| Replication | replication = null (no cross-account replication) |
Caller populates the full object explicitly |
| Failover | replication.enable_to_account[*].with_failover = false |
Caller sets true per account entry |
| Edition-check bypass | replication.ignore_edition_check = null (check enforced) |
Caller sets true explicitly, after Compliance review |
| Grant scope | Not modeled here at all β see tf-mod-snowflake-role-grant-bundle / tf-mod-snowflake-database-role-grant-bundle |
N/A |
| Secrets-bearing resources | Not applicable β neither resource accepts credential material | N/A |
Worked example. The empty call in Example 1 β
module "core_database" {
source = "git::https://github.com/microsoftexpert/tf-mod-snowflake-database.git?ref=v1.0.0"
name = "ANALYTICS"
}β produces a standard, non-transient database with no explicit retention override, no database
roles, and no replication. Nothing is destroyed on creation, nothing replicates to another
account, and nothing grants itself to anyone. A caller who wants the transient, cost-optimized
variant, or cross-account replication, has to type that explicitly β and that line reads as a
deliberate, reviewable decision in the diff, exactly as the warehouse module's worked example
demonstrates for auto_suspend.
cd C:\GitHubCode\newsnowflakemodules\tf-mod-snowflake-database
terraform init -backend=false
terraform validate
terraform fmt -checkThis module is plan-only in this authoring pipeline β no terraform apply is ever run here. A
human applies from a governed CI pipeline, pinning source = "...?ref=v1.0.0" (never a branch).
terraform init -backend=false/validate/fmt -checkprove type correctness and HCL syntax β everyobjectschema parses, everyvalidation {}block'sconditionis syntactically valid, and formatting matches canonicalterraform fmtoutput.- What these three commands cannot prove: whether the executing role actually holds
CREATE DATABASE/CREATE DATABASE ROLE, whether a referencedexternal_volumeactually exists, whetherreplication.enable_to_account[*].account_identifierresolves to a real organization member account, or whether a live account's edition permits the replication configured in Example 9. Those are only exercised by a realterraform plan/applyagainst a live Snowflake account, which this authoring pipeline deliberately never performs.
$ terraform output
database_roles = {
"ANALYST_RO" = {
"fully_qualified_name" = "\"ANALYTICS\".\"ANALYST_RO\""
"id" = "ANALYTICS\"|\"ANALYST_RO"
}
"ETL_WRITER" = {
"fully_qualified_name" = "\"ANALYTICS\".\"ETL_WRITER\""
"id" = "ANALYTICS\"|\"ETL_WRITER"
}
}
fully_qualified_name = "\"ANALYTICS\""
id = "ANALYTICS"
name = "ANALYTICS"
| Symptom | Cause | Fix |
|---|---|---|
terraform destroy fails with 098507 (2BP01) |
The database (or an object inside it) still has a network rule/network policy association | Unassign the association first β see the provider's ../guides/unassigning_policies guide β then retry the destroy |
| Plan shows no diff even though the live database's transient/standard type was changed manually | The provider does not detect external drift on is_transient |
Manually reconcile: terraform destroy + recreate, or terraform state rm + re-import against corrected configuration |
Import leaves is_transient (or other optional fields) unset in the freshly-generated configuration |
Provider import does not always populate every optional field from live state | Set is_transient (and any field you know the live value of) explicitly in configuration before the first post-import plan, per the provider's own migration-guide note |
Following the provider's snowflake_database import note about with_managed_access produces a Terraform error ("no argument named with_managed_access") |
Upstream documentation artifact β with_managed_access belongs to snowflake_schema, not snowflake_database |
Ignore that part of the provider's import note for this resource; only is_transient needs to be set explicitly before import |
terraform validate rejects a name or database_roles key with a ` |
/./"` character |
This module's own validation {} blocks catch the provider's documented identifier-parsing limitation before apply |
apply fails with a Snowflake-side error on user_task_managed_initial_warehouse_size |
This field has no validation {} block in this module (legal values aren't enumerated in the resource's own schema) |
Confirm the exact warehouse-size string against Snowflake's USER_TASK_MANAGED_INITIAL_WAREHOUSE_SIZE parameter docs before setting it |
Replication apply fails citing an edition/BAA restriction |
The primary account's edition or BAA status doesn't meet the secondary account's requirements | Confirm with Compliance/Legal before setting ignore_edition_check = true β do not bypass this check unreviewed |
- Provider resource docs:
snowflake_database,snowflake_database_role - Sibling modules:
tf-mod-snowflake-schema,tf-mod-snowflake-external-volume,tf-mod-snowflake-role-grant-bundle,tf-mod-snowflake-database-role-grant-bundle - This module's
SCOPE.md