|
8 | 8 | - [Making a contribution](#making-a-contribution) |
9 | 9 | - [Discuss a change with us!](#discuss-a-change-with-us) |
10 | 10 | - [Follow the code conventions inside the repository](#follow-the-code-conventions-inside-the-repository) |
11 | | - - [Introducing a new part of the SDK](#introducing-a-new-part-of-the-sdk) |
12 | 11 | - [Test the change](#test-the-change) |
13 | 12 | - [Describe the breaking changes](#describe-the-breaking-changes) |
14 | 13 | - [Before submitting the PR](#before-submitting-the-pr) |
15 | 14 | - [Naming and describing the PR](#naming-and-describing-the-pr) |
16 | 15 | - [Requesting the review](#requesting-the-review) |
| 16 | + - [Adding support for a new snowflake object](#adding-support-for-a-new-snowflake-object) |
| 17 | + - [Introducing a new part of the SDK](#add-the-object-to-the-sdk) |
17 | 18 | - [Advanced Debugging](#advanced-debugging) |
18 | 19 | - [Extending the migration script](#extending-the-migration-script) |
19 | 20 |
|
@@ -104,10 +105,6 @@ It's best to approach us through the GitHub issues: either by commenting the alr |
104 | 105 | ### Follow the code conventions inside the repository |
105 | 106 | We believe that code following the same conventions is easier to maintain and extend. When working on the given part of the provider try to follow the local solutions and not introduce too much new ideas. |
106 | 107 |
|
107 | | -### Introducing a new part of the SDK |
108 | | - |
109 | | -To create new objects in our SDK we use quickly created generator that outputs the majority of the files needed. These files should be later edited and filled with the missing parts. We plan to improve the generator later on, but it should be enough for now. Please read more in the [generator readme](pkg/sdk/generator/README.md). |
110 | | - |
111 | 108 | ### Test the change |
112 | 109 | Every introduced change should be tested. Depending on the type of the change it may require (any or mix of): |
113 | 110 | - adding/modifying existing unit tests (e.g. changing the behavior of validation in the SDK) |
@@ -144,8 +141,107 @@ We check for the new PRs in our repository every day Monday-Friday. We usually n |
144 | 141 |
|
145 | 142 | During our review we try to point out the unhandled special cases, missing tests, and deviations from the established conventions. Remember, review comment is like an invitation to dance: you don't have to agree but please provide the substantive reasons. |
146 | 143 |
|
| 144 | +Please do not resolve our comments. We prefer to resolve ourselves after the comments are followed up by the contributor. |
| 145 | + |
147 | 146 | **⚠️ Important ⚠️** Tests and checks are not run automatically after your PR. We run them manually, when we are happy with the state of the change (even if some corrections are still necessary). |
148 | 147 |
|
| 148 | +## Adding Support for a new Snowflake Object |
| 149 | +This guide describes the end-to-end process to add support for a new Snowflake object in the Terraform provider. Work is typically split into multiple PRs: SDK first, then SDK integration tests, followed by the Terraform resource, and finally the data source (SDK → integration tests → resource → data source). |
| 150 | + |
| 151 | +### Prerequisites and conventions |
| 152 | +- Use the SDK generator to define the object and produce the bulk of implementation and validations. See the SDK generator [README](pkg/sdk/generator/README.md) for file layout, generation parts, and commands. |
| 153 | + |
| 154 | +- Do not edit generated files; place any custom helpers or overrides in *_ext.go files. This is the pattern used across the SDK |
| 155 | + |
| 156 | +- Map both SHOW and DESCRIBE outputs. If the outputs differ, generate separate mapping structs and conversion paths; do not force a shared struct across both operations. |
| 157 | + |
| 158 | +### Add the object to the SDK |
| 159 | +- Create `<object_name_plural>_def.go` in the SDK generator defs directory |
| 160 | + |
| 161 | +- Use the DSL to configure operations: CREATE/ALTER/DROP, DESCRIBE, SHOW, and optional ShowById helpers. For example, notebooks use DescribeOperation, ShowOperation, and ShowByIdOperationWithFiltering to support both SHOW and DESCRIBE flows plus a by-ID retrieval. |
| 162 | + |
| 163 | +- If the server returns different shapes for SHOW and DESCRIBE, generate and map them separately. |
| 164 | + |
| 165 | +- From repository root, run make generate-sdk to build all parts |
| 166 | + |
| 167 | +- Expect the generator to create interface, DTOs, builders, validations, impl, and unit test placeholders (e.g., `_gen.go`, `_dto_gen.go`, `_dto_builders_gen.go`, `_validations_gen.go`, `_impl_gen.go`, `_gen_test.go`). |
| 168 | + |
| 169 | +- Avoid encoding server-side numeric ranges unless they are stable and guaranteed (rely on Snowflake for ranges/limits validations, check for only basic cases like integers being non-negative). |
| 170 | + |
| 171 | +- Implement unit tests. |
| 172 | + |
| 173 | +Take a look at [generator readme](pkg/sdk/generator/README.md) and an example [SDK implementation for notebooks](https://github.com/snowflakedb/terraform-provider-snowflake/pull/4084). |
| 174 | + |
| 175 | +### Add integration tests |
| 176 | +Add integration tests under the SDK’s testint package to validate the SDK behavior against a live Snowflake connection. |
| 177 | + |
| 178 | +Recommended coverage: |
| 179 | +- Lifecycle: create, show, describe, alter (set/unset combinations), rename, drop, and show-by-id where applicable. Prefer asserting fields you directly control (e.g., comment) and anything with server defaults you depend on. |
| 180 | + |
| 181 | +- Nil handling: ensure tests don’t panic on optional pointers (e.g., check for `nil` before calling `.Name()` on an identifier pointer). |
| 182 | + |
| 183 | +- ALTER validations: test both invalid “none set” and “more than one set” branches when you have ExactlyOneValueSet or AtLeastOneValueSet rules. |
| 184 | + |
| 185 | +- Error parity: assert the correct error kinds for missing objects (e.g., prefer consistent “object does not exist or not authorized” variants). |
| 186 | + |
| 187 | +- Assertion helpers: the generator can produce “object asserts” for SHOW/DESC outputs. Use generated assertion structs for concision, but add nil-checks to avoid panics in optional fields. |
| 188 | + |
| 189 | +- use `make generate-snowflake-object-assertions` to generate the assertions for the integration tests. |
| 190 | + |
| 191 | +Take a look at [generator readme](pkg/sdk/generator/README.md) and an example [Integration tests implementation for notebooks](https://github.com/snowflakedb/terraform-provider-snowflake/pull/4123). |
| 192 | + |
| 193 | +### Add resource |
| 194 | +Implement the resource schema, read/create/update/delete, acceptance tests, and docs. Use the SDK as the source of truth and mirror its SHOW/DESC coverage and validations. |
| 195 | + |
| 196 | +- Schema design |
| 197 | + - Prefer nested blocks for structured inputs. For example, “create from a stage” is modeled as a `from { stage = "<db>.<schema>.<stage>" path = "path/to/file" }` block rather than a flat string, to align with Snowflake semantics and improve validation. |
| 198 | + |
| 199 | + - Validate identifiers with the provider’s identifier validators (e.g., `IsValidIdentifier[...]`) and suppress quoting-only diffs for identifier fields (`suppressIdentifierQuoting`). |
| 200 | + |
| 201 | +- Update semantics |
| 202 | + - If it's possible, implement rename in-place (`ALTER … RENAME TO …`) rather than ForceNew. Align with how recently refactored resources handle renames. |
| 203 | + |
| 204 | + - Detect external changes for derived outputs via SHOW/DESC triggers when possible. If a particular field cannot be detected externally (e.g., notebooks “from” location due to Snowflake limitations), document that limitation explicitly in the resource docs. |
| 205 | + |
| 206 | +- Defaults and constraints surfaced in docs |
| 207 | + - Where Snowflake restricts identifier casing (e.g., only upper-case identifiers are valid for specific warehouse references), document it explicitly and add validators to prevent invalid inputs in plans. |
| 208 | + |
| 209 | +- Documentation and migration guide |
| 210 | + - Add a Migration Guide entry under the correct version, grouping object support under a single H3 “(new feature) snowflake_” heading with H4 subsections for “Added resource” and “Added data source”. |
| 211 | + |
| 212 | + - When server capabilities are incomplete, document current limitations and ensure Update/Create sequences handle supported paths without requiring double-applies. Remember to use the model builder and assertions that you can automatically generate. |
| 213 | + |
| 214 | +- Implement acceptance tests |
| 215 | + - Provide “basic” and “complete” cases; test rename, validations, and plan drift (ConfigPlanChecks). Avoid relying on “Safe” client wrappers for correctness checks; validate against the same paths real users hit. |
| 216 | + |
| 217 | +- use `make generate-show-output-schemas` to generate show schemas. |
| 218 | + |
| 219 | +- use `make generate-all-assertions-and-config-models` to generate assertions and config models. |
| 220 | + |
| 221 | +Take a look at an example [Resource implementation for notebooks](https://github.com/snowflakedb/terraform-provider-snowflake/pull/4195) |
| 222 | + |
| 223 | +### Add data source |
| 224 | +While not strictly required to “support” the object, a data source improves discoverability and enables read-only use cases. For parity with other objects, we recommend adding one. |
| 225 | + |
| 226 | +Example patterns validated by the data source: |
| 227 | +- Filtering aligned to SHOW |
| 228 | + - Support `like`, `starts_with`, and `limit { rows, from }` to mirror SHOW filters; include `with_describe` to optionally call DESCRIBE for each item. Keep `with_describe` default-on but allow turning it off to reduce calls in large accounts. |
| 229 | + |
| 230 | +- Output shape |
| 231 | + - Aggregate into a single `<object_name_plural>` collection with nested `show_output` (SHOW) and `describe_output` (DESCRIBE) blocks containing fields as strings/numbers |
| 232 | + |
| 233 | +- Documentation and examples |
| 234 | + - Provide simple, filter, and pagination examples; include a note about default behavior of `with_describe`. |
| 235 | + |
| 236 | +- Provider preview gate and migration guide |
| 237 | + - Add the “Added data source” H4 subsection under the same feature entry in the Migration Guide and link Snowflake’s SHOW docs where appropriate. |
| 238 | + |
| 239 | +- use `make generate-all-assertions-and-config-models` to generate config model. |
| 240 | + |
| 241 | +- use `make docs` to generate documentation based on the `.md.tmpl` file (which is the file you should edit instead of `.md` file). |
| 242 | + |
| 243 | +Take a look at [Data source implementation for notebooks](https://github.com/snowflakedb/terraform-provider-snowflake/pull/4209) and its follow up with extra tests [Extended test coverage for notebooks](https://github.com/snowflakedb/terraform-provider-snowflake/pull/4237) |
| 244 | + |
149 | 245 | ## Advanced Debugging |
150 | 246 |
|
151 | 247 | If you want to build and test the provider locally (manually, not through acceptance tests), build the binary first using `make build-local` or install to the proper local directory by invoking `make install-tf` (to uninstall run `make uninstall-tf`). |
|
0 commit comments