diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1f08dec..62f2029 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,26 +1,26 @@ repos: - repo: https://github.com/gruntwork-io/pre-commit # When updating, also check if tflint version in pre-commit workflow can be updated. - rev: "v0.1.23" # Get the latest from: https://github.com/gruntwork-io/pre-commit/releases + rev: "v0.1.25" # Get the latest from: https://github.com/gruntwork-io/pre-commit/releases hooks: - id: terraform-validate # It should be the first step as it runs terraform init required by tflint - id: terraform-fmt - id: tflint - repo: https://github.com/terraform-docs/terraform-docs - rev: "v0.18.0" # Get the latest from: https://github.com/terraform-docs/terraform-docs/releases + rev: "v0.19.0" # Get the latest from: https://github.com/terraform-docs/terraform-docs/releases hooks: - id: terraform-docs-go args: ["."] - repo: https://github.com/bridgecrewio/checkov.git - rev: "3.2.192" # Get the latest from: https://github.com/bridgecrewio/checkov/releases + rev: "3.2.350" # Get the latest from: https://github.com/bridgecrewio/checkov/releases hooks: - id: checkov args: [--skip-check, "CKV_TF_1"] # Terraform module sources do not use a git url with a commit hash revision - repo: https://github.com/pre-commit/pre-commit-hooks - rev: "v4.6.0" # Get the latest from: https://github.com/pre-commit/pre-commit-hooks/releases + rev: "v5.0.0" # Get the latest from: https://github.com/pre-commit/pre-commit-hooks/releases hooks: - id: check-merge-conflict args: ["--assume-in-merge"] diff --git a/README.md b/README.md index b060e9a..21e6b05 100644 --- a/README.md +++ b/README.md @@ -116,11 +116,11 @@ List od code and variable (API) changes: | [log\_level](#input\_log\_level) | Specifies the severity level of messages that should be ingested and made available in the active event table. Valid options are: [TRACE DEBUG INFO WARN ERROR FATAL OFF] | `string` | `null` | no | | [max\_data\_extension\_time\_in\_days](#input\_max\_data\_extension\_time\_in\_days) | Object parameter that specifies the maximum number of days for which Snowflake can extend the data retention period for tables in the database to prevent streams on the tables from becoming stale | `number` | `null` | no | | [name](#input\_name) | Name of the resource | `string` | n/a | yes | -| [name\_scheme](#input\_name\_scheme) | Naming scheme configuration for the resource. This configuration is used to generate names using context provider:
- `properties` - list of properties to use when creating the name - is superseded by `var.context_templates`
- `delimiter` - delimited used to create the name from `properties` - is superseded by `var.context_templates`
- `context_template_name` - name of the context template used to create the name
- `replace_chars_regex` - regex to use for replacing characters in property-values created by the provider - any characters that match the regex will be removed from the name
- `extra_values` - map of extra label-value pairs, used to create a name |
object({
properties = optional(list(string), ["environment", "name"])
delimiter = optional(string, "_")
context_template_name = optional(string, "snowflake-database")
replace_chars_regex = optional(string, "[^a-zA-Z0-9_]")
extra_values = optional(map(string))
})
| `{}` | no | +| [name\_scheme](#input\_name\_scheme) | Naming scheme configuration for the resource. This configuration is used to generate names using context provider:
- `properties` - list of properties to use when creating the name - is superseded by `var.context_templates`
- `delimiter` - delimited used to create the name from `properties` - is superseded by `var.context_templates`
- `context_template_name` - name of the context template used to create the name
- `replace_chars_regex` - regex to use for replacing characters in property-values created by the provider - any characters that match the regex will be removed from the name
- `extra_values` - map of extra label-value pairs, used to create a name
- `uppercase` - convert name to uppercase |
object({
properties = optional(list(string), ["environment", "name"])
delimiter = optional(string, "_")
context_template_name = optional(string, "snowflake-database")
replace_chars_regex = optional(string, "[^a-zA-Z0-9_]")
extra_values = optional(map(string))
uppercase = optional(bool, true)
})
| `{}` | no | | [quoted\_identifiers\_ignore\_case](#input\_quoted\_identifiers\_ignore\_case) | If true, the case of quoted identifiers is ignored | `bool` | `null` | no | | [replace\_invalid\_characters](#input\_replace\_invalid\_characters) | Specifies whether to replace invalid UTF-8 characters with the Unicode replacement character () in query results for an Iceberg table | `bool` | `null` | no | -| [roles](#input\_roles) | Roles created in the database scope |
map(object({
name_scheme = optional(object({
properties = optional(list(string))
delimiter = optional(string)
context_template_name = optional(string)
replace_chars_regex = optional(string)
extra_labels = optional(map(string))
}))
comment = optional(string)
role_ownership_grant = optional(string)
granted_roles = optional(list(string))
granted_to_roles = optional(list(string))
granted_to_users = optional(list(string))
database_grants = optional(object({
all_privileges = optional(bool)
with_grant_option = optional(bool, false)
privileges = optional(list(string), null)
}))
schema_grants = optional(list(object({
all_privileges = optional(bool)
with_grant_option = optional(bool, false)
privileges = optional(list(string), null)
all_schemas_in_database = optional(bool, false)
future_schemas_in_database = optional(bool, false)
schema_name = optional(string, null)
})))
schema_objects_grants = optional(map(list(object({
all_privileges = optional(bool)
with_grant_option = optional(bool)
privileges = optional(list(string), null)
object_name = optional(string)
on_all = optional(bool, false)
schema_name = optional(string)
on_future = optional(bool, false)
}))), {})
}))
| `{}` | no | -| [schemas](#input\_schemas) | Schemas to be created in the database |
map(object({
name_scheme = optional(object({
properties = optional(list(string))
delimiter = optional(string)
context_template_name = optional(string)
replace_chars_regex = optional(string)
extra_labels = optional(map(string))
}))
skip_schema_creation = optional(bool, false)
comment = optional(string, null)
data_retention_time_in_days = optional(number, null)
max_data_extension_time_in_days = optional(number, null)
is_transient = optional(bool, null)
with_managed_access = optional(bool, null)
external_volume = optional(string, null)
catalog = optional(string, null)
replace_invalid_characters = optional(bool, null)
default_ddl_collation = optional(string, null)
storage_serialization_policy = optional(string, null)
log_level = optional(string, null)
trace_level = optional(string, null)
suspend_task_after_num_failures = optional(number, null)
task_auto_retry_attempts = optional(number, null)
user_task_managed_initial_warehouse_size = optional(string, null)
user_task_timeout_ms = optional(number, null)
user_task_minimum_trigger_interval_in_seconds = optional(number, null)
quoted_identifiers_ignore_case = optional(bool, null)
enable_console_output = optional(bool, null)
pipe_execution_paused = optional(bool, null)
create_default_roles = optional(bool)
stages = optional(map(object({
name_scheme = optional(object({
properties = optional(list(string))
delimiter = optional(string)
context_template_name = optional(string)
replace_chars_regex = optional(string)
extra_labels = optional(map(string))
}))
aws_external_id = optional(string)
comment = optional(string)
copy_options = optional(string)
credentials = optional(string)
directory = optional(string)
encryption = optional(string)
file_format = optional(string)
snowflake_iam_user = optional(string)
storage_integration = optional(string)
url = optional(string)
create_default_roles = optional(bool)
roles = optional(map(object({
name_scheme = optional(object({
properties = optional(list(string))
delimiter = optional(string)
context_template_name = optional(string)
replace_chars_regex = optional(string)
extra_labels = optional(map(string))
}))
with_grant_option = optional(bool)
granted_to_roles = optional(list(string))
granted_to_database_roles = optional(list(string))
granted_database_roles = optional(list(string))
stage_grants = optional(list(string))
all_privileges = optional(bool)
})), {})
})), {})
roles = optional(map(object({
name_scheme = optional(object({
properties = optional(list(string))
delimiter = optional(string)
context_template_name = optional(string)
replace_chars_regex = optional(string)
extra_labels = optional(map(string))
}))
comment = optional(string)
granted_to_roles = optional(list(string))
granted_to_database_roles = optional(list(string))
granted_database_roles = optional(list(string))
schema_grants = optional(list(object({
all_privileges = optional(bool)
with_grant_option = optional(bool, false)
privileges = optional(list(string), null)
})))
schema_objects_grants = optional(map(list(object({
all_privileges = optional(bool)
with_grant_option = optional(bool)
privileges = optional(list(string), null)
object_name = optional(string)
on_all = optional(bool, false)
on_future = optional(bool, false)
}))), {})
})), {})
}))
| `{}` | no | +| [roles](#input\_roles) | Roles created in the database scope |
map(object({
name_scheme = optional(object({
properties = optional(list(string))
delimiter = optional(string)
context_template_name = optional(string)
replace_chars_regex = optional(string)
extra_labels = optional(map(string))
uppercase = optional(bool)
}))
comment = optional(string)
role_ownership_grant = optional(string)
granted_roles = optional(list(string))
granted_to_roles = optional(list(string))
granted_to_users = optional(list(string))
database_grants = optional(object({
all_privileges = optional(bool)
with_grant_option = optional(bool, false)
privileges = optional(list(string), null)
}))
schema_grants = optional(list(object({
all_privileges = optional(bool)
with_grant_option = optional(bool, false)
privileges = optional(list(string), null)
all_schemas_in_database = optional(bool, false)
future_schemas_in_database = optional(bool, false)
schema_name = optional(string, null)
})))
schema_objects_grants = optional(map(list(object({
all_privileges = optional(bool)
with_grant_option = optional(bool)
privileges = optional(list(string), null)
object_name = optional(string)
on_all = optional(bool, false)
schema_name = optional(string)
on_future = optional(bool, false)
}))), {})
}))
| `{}` | no | +| [schemas](#input\_schemas) | Schemas to be created in the database |
map(object({
name_scheme = optional(object({
properties = optional(list(string))
delimiter = optional(string)
context_template_name = optional(string)
replace_chars_regex = optional(string)
extra_labels = optional(map(string))
uppercase = optional(bool)
}))
skip_schema_creation = optional(bool, false)
comment = optional(string, null)
data_retention_time_in_days = optional(number, null)
max_data_extension_time_in_days = optional(number, null)
is_transient = optional(bool, null)
with_managed_access = optional(bool, null)
external_volume = optional(string, null)
catalog = optional(string, null)
replace_invalid_characters = optional(bool, null)
default_ddl_collation = optional(string, null)
storage_serialization_policy = optional(string, null)
log_level = optional(string, null)
trace_level = optional(string, null)
suspend_task_after_num_failures = optional(number, null)
task_auto_retry_attempts = optional(number, null)
user_task_managed_initial_warehouse_size = optional(string, null)
user_task_timeout_ms = optional(number, null)
user_task_minimum_trigger_interval_in_seconds = optional(number, null)
quoted_identifiers_ignore_case = optional(bool, null)
enable_console_output = optional(bool, null)
pipe_execution_paused = optional(bool, null)
create_default_roles = optional(bool)
stages = optional(map(object({
name_scheme = optional(object({
properties = optional(list(string))
delimiter = optional(string)
context_template_name = optional(string)
replace_chars_regex = optional(string)
extra_labels = optional(map(string))
uppercase = optional(bool)
}))
aws_external_id = optional(string)
comment = optional(string)
copy_options = optional(string)
credentials = optional(string)
directory = optional(string)
encryption = optional(string)
file_format = optional(string)
snowflake_iam_user = optional(string)
storage_integration = optional(string)
url = optional(string)
create_default_roles = optional(bool)
roles = optional(map(object({
name_scheme = optional(object({
properties = optional(list(string))
delimiter = optional(string)
context_template_name = optional(string)
replace_chars_regex = optional(string)
extra_labels = optional(map(string))
uppercase = optional(bool)
}))
with_grant_option = optional(bool)
granted_to_roles = optional(list(string))
granted_to_database_roles = optional(list(string))
granted_database_roles = optional(list(string))
stage_grants = optional(list(string))
all_privileges = optional(bool)
})), {})
})), {})
roles = optional(map(object({
name_scheme = optional(object({
properties = optional(list(string))
delimiter = optional(string)
context_template_name = optional(string)
replace_chars_regex = optional(string)
extra_labels = optional(map(string))
uppercase = optional(bool)
}))
comment = optional(string)
granted_to_roles = optional(list(string))
granted_to_database_roles = optional(list(string))
granted_database_roles = optional(list(string))
schema_grants = optional(list(object({
all_privileges = optional(bool)
with_grant_option = optional(bool, false)
privileges = optional(list(string), null)
})))
schema_objects_grants = optional(map(list(object({
all_privileges = optional(bool)
with_grant_option = optional(bool)
privileges = optional(list(string), null)
object_name = optional(string)
on_all = optional(bool, false)
on_future = optional(bool, false)
}))), {})
})), {})
}))
| `{}` | no | | [storage\_serialization\_policy](#input\_storage\_serialization\_policy) | The storage serialization policy for Iceberg tables that use Snowflake as the catalog. Valid options are: [COMPATIBLE OPTIMIZED] | `string` | `null` | no | | [suspend\_task\_after\_num\_failures](#input\_suspend\_task\_after\_num\_failures) | How many times a task must fail in a row before it is automatically suspended. 0 disables auto-suspending | `number` | `null` | no | | [task\_auto\_retry\_attempts](#input\_task\_auto\_retry\_attempts) | Maximum automatic retries allowed for a user task | `number` | `null` | no | @@ -134,9 +134,9 @@ List od code and variable (API) changes: | Name | Source | Version | |------|--------|---------| | [roles\_deep\_merge](#module\_roles\_deep\_merge) | Invicton-Labs/deepmerge/null | 0.1.5 | -| [snowflake\_custom\_role](#module\_snowflake\_custom\_role) | getindata/database-role/snowflake | 2.0.1 | -| [snowflake\_default\_role](#module\_snowflake\_default\_role) | getindata/database-role/snowflake | 2.0.1 | -| [snowflake\_schema](#module\_snowflake\_schema) | getindata/schema/snowflake | 3.0.0 | +| [snowflake\_custom\_role](#module\_snowflake\_custom\_role) | getindata/database-role/snowflake | 2.1.0 | +| [snowflake\_default\_role](#module\_snowflake\_default\_role) | getindata/database-role/snowflake | 2.1.0 | +| [snowflake\_schema](#module\_snowflake\_schema) | getindata/schema/snowflake | 3.1.0 | ## Outputs @@ -169,7 +169,7 @@ List od code and variable (API) changes: | Name | Version | |------|---------| | [context](#provider\_context) | >=0.4.0 | -| [snowflake](#provider\_snowflake) | ~> 0.95 | +| [snowflake](#provider\_snowflake) | >= 0.95 | ## Requirements @@ -177,7 +177,7 @@ List od code and variable (API) changes: |------|---------| | [terraform](#requirement\_terraform) | >= 1.3 | | [context](#requirement\_context) | >=0.4.0 | -| [snowflake](#requirement\_snowflake) | ~> 0.95 | +| [snowflake](#requirement\_snowflake) | >= 0.95 | ## Resources diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 931f380..3da8b16 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -35,6 +35,9 @@ module "database" { stages = { example = { comment = "my example stage" + name_scheme = { + uppercase = false + } } } roles = { @@ -43,6 +46,9 @@ module "database" { } readonly = { granted_to_roles = [snowflake_account_role.dev_role.name] + name_scheme = { + uppercase = false + } } } } @@ -74,5 +80,14 @@ module "project_database" { extra_values = { project = "project" } + uppercase = false } + + + comment = "test database" + data_retention_time_in_days = 1 + is_transient = false + + create_default_roles = true + database_ownership_grant = snowflake_account_role.admin_role.name } diff --git a/examples/simple/README.md b/examples/simple/README.md index 96df73e..13133de 100644 --- a/examples/simple/README.md +++ b/examples/simple/README.md @@ -41,7 +41,7 @@ No providers. | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.3 | -| [snowflake](#requirement\_snowflake) | ~> 0.95 | +| [snowflake](#requirement\_snowflake) | >= 0.95 | ## Resources diff --git a/examples/simple/versions.tf b/examples/simple/versions.tf index 0929444..659976c 100644 --- a/examples/simple/versions.tf +++ b/examples/simple/versions.tf @@ -3,7 +3,7 @@ terraform { required_providers { snowflake = { source = "Snowflake-Labs/snowflake" - version = "~> 0.95" + version = ">= 0.95" } } } diff --git a/locals.tf b/locals.tf index 435b4b6..ecb9258 100644 --- a/locals.tf +++ b/locals.tf @@ -7,6 +7,7 @@ locals { extra_values = { database = var.name } + uppercase = var.name_scheme.uppercase } #This needs to be the same as an object in roles variable diff --git a/main.tf b/main.tf index c8d8c43..3d216a0 100644 --- a/main.tf +++ b/main.tf @@ -12,7 +12,7 @@ data "context_label" "this" { } resource "snowflake_database" "this" { - name = data.context_label.this.rendered + name = var.name_scheme.uppercase ? upper(data.context_label.this.rendered) : data.context_label.this.rendered is_transient = var.is_transient comment = var.comment @@ -43,7 +43,7 @@ module "snowflake_default_role" { for_each = local.default_roles source = "getindata/database-role/snowflake" - version = "2.0.1" + version = "2.1.0" database_name = snowflake_database.this.name context_templates = var.context_templates @@ -67,7 +67,7 @@ module "snowflake_custom_role" { for_each = local.custom_roles source = "getindata/database-role/snowflake" - version = "2.0.1" + version = "2.1.0" database_name = snowflake_database.this.name context_templates = var.context_templates @@ -91,12 +91,13 @@ module "snowflake_schema" { for_each = var.schemas source = "getindata/schema/snowflake" - version = "3.0.0" + version = "3.1.0" context_templates = var.context_templates name = each.key name_scheme = merge({ + uppercase = var.name_scheme.uppercase extra_values = { database = var.name } }, @@ -137,7 +138,7 @@ resource "snowflake_grant_ownership" "database_ownership" { count = var.database_ownership_grant != null ? 1 : 0 account_role_name = var.database_ownership_grant - outbound_privileges = "REVOKE" + outbound_privileges = "COPY" on { object_type = "DATABASE" object_name = snowflake_database.this.name diff --git a/variables.tf b/variables.tf index 4712cdd..b3816f0 100644 --- a/variables.tf +++ b/variables.tf @@ -126,6 +126,7 @@ variable "roles" { context_template_name = optional(string) replace_chars_regex = optional(string) extra_labels = optional(map(string)) + uppercase = optional(bool) })) comment = optional(string) role_ownership_grant = optional(string) @@ -167,6 +168,7 @@ variable "schemas" { context_template_name = optional(string) replace_chars_regex = optional(string) extra_labels = optional(map(string)) + uppercase = optional(bool) })) skip_schema_creation = optional(bool, false) comment = optional(string, null) @@ -197,6 +199,7 @@ variable "schemas" { context_template_name = optional(string) replace_chars_regex = optional(string) extra_labels = optional(map(string)) + uppercase = optional(bool) })) aws_external_id = optional(string) comment = optional(string) @@ -216,6 +219,7 @@ variable "schemas" { context_template_name = optional(string) replace_chars_regex = optional(string) extra_labels = optional(map(string)) + uppercase = optional(bool) })) with_grant_option = optional(bool) granted_to_roles = optional(list(string)) @@ -232,6 +236,7 @@ variable "schemas" { context_template_name = optional(string) replace_chars_regex = optional(string) extra_labels = optional(map(string)) + uppercase = optional(bool) })) comment = optional(string) granted_to_roles = optional(list(string)) @@ -275,6 +280,7 @@ variable "name_scheme" { - `context_template_name` - name of the context template used to create the name - `replace_chars_regex` - regex to use for replacing characters in property-values created by the provider - any characters that match the regex will be removed from the name - `extra_values` - map of extra label-value pairs, used to create a name + - `uppercase` - convert name to uppercase EOT type = object({ properties = optional(list(string), ["environment", "name"]) @@ -282,6 +288,7 @@ variable "name_scheme" { context_template_name = optional(string, "snowflake-database") replace_chars_regex = optional(string, "[^a-zA-Z0-9_]") extra_values = optional(map(string)) + uppercase = optional(bool, true) }) default = {} } diff --git a/versions.tf b/versions.tf index 8ffc6ba..1227607 100644 --- a/versions.tf +++ b/versions.tf @@ -3,7 +3,7 @@ terraform { required_providers { snowflake = { source = "Snowflake-Labs/snowflake" - version = "~> 0.95" + version = ">= 0.95" } context = { source = "cloudposse/context"