Skip to content

Commit 03513bd

Browse files
authored
Merge pull request #32 from getindata/feature/add_warehouse_generation_support
feat: Add support for warehouse generation
2 parents 0640a78 + d06f13f commit 03513bd

File tree

8 files changed

+191
-3
lines changed

8 files changed

+191
-3
lines changed

AGENTS.md

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# AGENTS.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Module Overview
6+
7+
This is a Terraform module for Snowflake Warehouse management that:
8+
- Creates Snowflake warehouses with comprehensive configuration options
9+
- Manages role-based access control through default and custom roles
10+
- Uses CloudPosse context provider for flexible naming conventions
11+
- Integrates with getindata/role/snowflake module (v4.0.0) for role management
12+
13+
## Architecture
14+
15+
### Naming Convention System
16+
17+
The module uses CloudPosse context provider instead of deprecated `context.tf` (nulllabel):
18+
19+
1. **Context Provider Setup**: The `data.context_label.this` data source generates resource names based on templates
20+
2. **Template Resolution**: `context_templates` variable defines naming patterns (e.g., `{{.environment}}_{{.name}}`)
21+
3. **Name Scheme Configuration**: Each resource has configurable `name_scheme` with properties, delimiter, and template selection
22+
4. **Template Lookup**: `local.context_template` resolves which template to use from `var.context_templates`
23+
24+
Key files:
25+
- [locals.tf:1-3](locals.tf#L1-L3) - Template resolution logic
26+
- [main.tf:1-12](main.tf#L1-L12) - Context label data source usage
27+
28+
### Role Management Architecture
29+
30+
The module creates two types of roles through a merge-and-split pattern:
31+
32+
1. **Default Roles** ([locals.tf:14-42](locals.tf#L14-L42)): Pre-defined functional roles (admin, usage, monitor)
33+
2. **Custom Roles** ([locals.tf:44-47](locals.tf#L44-L47)): User-provided roles via `var.roles`
34+
3. **Deep Merge** ([locals.tf:68-73](locals.tf#L68-L73)): Uses `Invicton-Labs/deepmerge/null` to merge default + provided roles
35+
4. **Split Logic** ([locals.tf:50-57](locals.tf#L50-L57)): Separates merged roles into default vs custom for different module calls
36+
37+
Role modules are instantiated separately:
38+
- [main.tf:44-71](main.tf#L44-L71) - Default roles module
39+
- [main.tf:73-100](main.tf#L73-L100) - Custom roles module
40+
41+
### Resource Structure
42+
43+
- **Primary Resource**: `snowflake_warehouse.this` ([main.tf:14-39](main.tf#L14-L39))
44+
- **Role Grants**: Handled by nested `getindata/role/snowflake` modules with `account_objects_grants`
45+
- **State Migration**: `moved` block at [main.tf:40-43](main.tf#L40-L43) handles v2 to v3 upgrade
46+
47+
## Common Commands
48+
49+
### Development Workflow
50+
51+
```bash
52+
# Initialize module
53+
terraform init
54+
55+
# Validate configuration
56+
terraform validate
57+
58+
# Format code
59+
terraform fmt -recursive
60+
61+
# Run pre-commit hooks (validates, formats, lints, generates docs, security scan)
62+
pre-commit install
63+
pre-commit run --all-files
64+
```
65+
66+
### Testing with Examples
67+
68+
```bash
69+
# Simple example
70+
cd examples/simple
71+
make init
72+
make plan
73+
make apply
74+
75+
# Complete example (full configuration)
76+
cd examples/complete
77+
make init
78+
make plan
79+
make apply
80+
```
81+
82+
### Documentation Generation
83+
84+
```bash
85+
# Auto-generate README inputs/outputs tables
86+
terraform-docs .
87+
```
88+
89+
## Pre-commit Configuration
90+
91+
The module uses pre-commit hooks in this order:
92+
1. `terraform-validate` - Must run first (performs `terraform init` required by tflint)
93+
2. `terraform-fmt` - Code formatting
94+
3. `tflint` - Terraform linting
95+
4. `terraform-docs` - Auto-generates documentation
96+
5. `checkov` - Security scanning (skips CKV_TF_1 for module sources)
97+
98+
## Provider Version Requirements
99+
100+
- **Snowflake Provider**: `>= 2.7` (snowflakedb/snowflake)
101+
- **Context Provider**: `>= 0.4.0` (cloudposse/context)
102+
- **Terraform**: `>= 1.3`
103+
104+
**IMPORTANT**: ALWAYS use `snowflakedb/snowflake` provider. NEVER use `Snowflake-Labs/snowflake` provider. The Snowflake-Labs provider is deprecated and should not be used in any configuration or documentation queries.
105+
106+
## Breaking Changes
107+
108+
### v3.x Migration
109+
- Removed `context.tf` (nulllabel) - switched to context provider
110+
- Removed variables: `context`, `enabled`, `environment`, `namespace`, `tenant`, `stage`, `attributes`, `delimiter`, `tags`, `labels_as_tags`, etc.
111+
- Added: `context_templates` and `name_scheme` variables
112+
- State migration handled via `moved` blocks
113+
114+
### v4.x Migration
115+
- Provider source changed from `Snowflake-Labs/snowflake` to `snowflakedb/snowflake`
116+
117+
## Key Variables
118+
119+
### Required
120+
- `name` - Base name for the warehouse resource
121+
122+
### Naming Configuration
123+
- `name_scheme` - Object controlling naming behavior (properties, delimiter, template, regex, uppercase)
124+
- `context_templates` - Map of go-template strings for naming patterns (supersedes name_scheme properties/delimiter)
125+
126+
### Warehouse Configuration
127+
128+
- `warehouse_size`, `warehouse_type` - Warehouse compute settings
129+
- `generation` - Warehouse generation (only for STANDARD warehouses). Valid values: "1" or "2" (string type, not number - this is dictated by the Snowflake provider schema)
130+
- `auto_resume`, `auto_suspend`, `initially_suspended` - Power management
131+
- `min_cluster_count`, `max_cluster_count`, `scaling_policy` - Multi-cluster settings
132+
- `enable_query_acceleration`, `query_acceleration_max_scale_factor` - Query acceleration
133+
- `resource_monitor` - Credit quota monitoring
134+
135+
### Role Management
136+
- `create_default_roles` - Boolean to create admin/usage/monitor roles
137+
- `roles` - Map of role definitions with grants and assignments
138+
139+
## Examples Structure
140+
141+
- **simple/** - Minimal configuration showing basic warehouse creation
142+
- **complete/** - Full-featured example with:
143+
- Resource monitor integration
144+
- Default roles enabled
145+
- Custom role with specific privileges
146+
- Multiple naming scheme patterns
147+
- Context template usage
148+
- Generation 2 warehouse configuration (warehouse_3)
149+
150+
## Important Implementation Notes
151+
152+
### Generation Field
153+
154+
- Type: `string` (not `number`) - this is required by the Snowflake provider schema, not a design choice
155+
- Valid values: `"1"`, `"2"`
156+
- Only applicable to STANDARD warehouse type
157+
- Validation uses ternary operator to handle null: `var.generation == null ? true : contains(["1", "2"], var.generation)`
158+
- Added in provider version 2.7+
159+
- The string type requirement comes from how Snowflake's SQL interface and provider handle this parameter
160+
161+
### Variable Validation Pattern
162+
163+
When validating optional (nullable) variables with `contains()`, use ternary operator to avoid null evaluation errors:
164+
165+
```hcl
166+
validation {
167+
condition = var.field == null ? true : contains(["val1", "val2"], var.field)
168+
error_message = "Invalid value"
169+
}
170+
```
171+
172+
Do NOT use: `var.field == null || contains([...], var.field)` as it will fail when the value is null.

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@AGENTS.md

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ List od code and variable (API) changes:
115115
| <a name="input_context_templates"></a> [context\_templates](#input\_context\_templates) | Map of context templates used for naming conventions - this variable supersedes `naming_scheme.properties` and `naming_scheme.delimiter` configuration | `map(string)` | `{}` | no |
116116
| <a name="input_create_default_roles"></a> [create\_default\_roles](#input\_create\_default\_roles) | Whether the default roles should be created | `bool` | `false` | no |
117117
| <a name="input_enable_query_acceleration"></a> [enable\_query\_acceleration](#input\_enable\_query\_acceleration) | Specifies whether to enable the query acceleration service for queries that rely on this warehouse for compute resources. | `bool` | `true` | no |
118+
| <a name="input_generation"></a> [generation](#input\_generation) | Specifies the generation for the warehouse. Only available for standard warehouses. Valid values are: 1, 2, docs: <https://docs.snowflake.com/en/user-guide/warehouses-gen2>. | `string` | `null` | no |
118119
| <a name="input_initially_suspended"></a> [initially\_suspended](#input\_initially\_suspended) | Specifies whether the warehouse is created initially in the ‘Suspended’ state. | `bool` | `true` | no |
119120
| <a name="input_max_cluster_count"></a> [max\_cluster\_count](#input\_max\_cluster\_count) | Specifies the maximum number of server clusters for the warehouse. | `number` | `1` | no |
120121
| <a name="input_max_concurrency_level"></a> [max\_concurrency\_level](#input\_max\_concurrency\_level) | Object parameter that specifies the concurrency level for SQL statements (i.e. queries and DML) executed by a warehouse. | `number` | `null` | no |
@@ -150,15 +151,15 @@ List od code and variable (API) changes:
150151
| Name | Version |
151152
|------|---------|
152153
| <a name="provider_context"></a> [context](#provider\_context) | >=0.4.0 |
153-
| <a name="provider_snowflake"></a> [snowflake](#provider\_snowflake) | >= 0.95 |
154+
| <a name="provider_snowflake"></a> [snowflake](#provider\_snowflake) | >= 2.7 |
154155

155156
## Requirements
156157

157158
| Name | Version |
158159
|------|---------|
159160
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3 |
160161
| <a name="requirement_context"></a> [context](#requirement\_context) | >=0.4.0 |
161-
| <a name="requirement_snowflake"></a> [snowflake](#requirement\_snowflake) | >= 0.95 |
162+
| <a name="requirement_snowflake"></a> [snowflake](#requirement\_snowflake) | >= 2.7 |
162163

163164
## Resources
164165

examples/complete/main.tf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,5 +89,7 @@ module "terraform_snowflake_warehouse_3" {
8989
}
9090
}
9191

92+
generation = "2"
93+
9294
create_default_roles = false
9395
}

main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ resource "snowflake_warehouse" "this" {
1717

1818
warehouse_size = var.warehouse_size
1919
warehouse_type = var.warehouse_type
20+
generation = var.generation
2021

2122
auto_resume = var.auto_resume
2223
auto_suspend = var.auto_suspend

outputs.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ output "warehouse" {
66
comment = snowflake_warehouse.this.comment
77
warehouse_type = snowflake_warehouse.this.warehouse_type
88
warehouse_size = snowflake_warehouse.this.warehouse_size
9+
generation = snowflake_warehouse.this.generation
910
auto_resume = snowflake_warehouse.this.auto_resume
1011
auto_suspend = snowflake_warehouse.this.auto_suspend
1112
initially_suspended = snowflake_warehouse.this.initially_suspended

variables.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ variable "warehouse_type" {
2525
}
2626
}
2727

28+
variable "generation" {
29+
description = "Specifies the generation for the warehouse. Only available for standard warehouses. Valid values are: 1, 2, docs: <https://docs.snowflake.com/en/user-guide/warehouses-gen2>."
30+
type = string
31+
default = null
32+
validation {
33+
condition = var.generation == null ? true : contains(["1", "2"], var.generation)
34+
error_message = "Invalid generation. Possible values are: \"1\", \"2\""
35+
}
36+
}
37+
2838
variable "auto_resume" {
2939
description = "Specifies whether to automatically resume a warehouse when a SQL statement (e.g. query) is submitted to it."
3040
type = bool

versions.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ terraform {
33
required_providers {
44
snowflake = {
55
source = "snowflakedb/snowflake"
6-
version = ">= 0.95"
6+
version = ">= 2.7"
77
}
88
context = {
99
source = "cloudposse/context"

0 commit comments

Comments
 (0)