From f4ae38086c9a17259aff698f80a21e8d14f748e7 Mon Sep 17 00:00:00 2001 From: Artur Sawicki Date: Mon, 5 Aug 2024 14:19:36 +0200 Subject: [PATCH] feat: Add user parameters to resource (#2968) This is the first of the next few changes being a part of the user resource rework. It includes: - adding user parameters to the user resource schema - adding the `parameters` collection to user schema - testing the behavior of parameters on user - a bunch of TODOs to move parameters definitions was left for the next PRs (this one is already too big) - missing assertions and config builders generated Checks for setting `TIMEZONE` may fail (skip added to the test messing with our account; it was cleaned with `ALTER ACCOUNT UNSET TIMEZONE` but still this test from other branches may interfere). Additionally: - logic to handle parameters has been slightly improved and made a bit more generic (with changes to databases and schemas; function to read database parameters was replaced with a more generic solution fixing SNOW-1480106) - one of the account parameters was messing with the change, so the test was temporarily skipped - new github issues added to the known issues list It does not include (it will be handled in the following PRs): - checking quotes for `DATE_INPUT_FORMAT` and `DATE_OUTPUT_FORMAT` - checking if zero is allowed for `CLIENT_MEMORY_LIMIT` - handling `snowflake_network_policy_attachment` - handling `snowflake_user_public_keys` - setting diff suppressions and validations for the parameters (it will be handled in the next PR) - moving the parameters logic fully to the SDK - reworking other attributes on the user resource - adding more acceptance tests --- MIGRATION_GUIDE.md | 72 ++ docs/resources/schema.md | 2 +- docs/resources/user.md | 855 ++++++++++++++++++ .../resourceassert/user_resource_gen.go | 580 ++++++++++++ .../config/model/user_model_ext.go | 62 ++ .../config/model/user_model_gen.go | 672 +++++++++++++- pkg/datasources/databases.go | 6 +- pkg/datasources/parameters_acceptance_test.go | 18 +- pkg/datasources/schemas.go | 6 +- pkg/datasources/warehouses.go | 6 +- .../account_parameter_acceptance_test.go | 2 + pkg/resources/custom_diffs.go | 18 +- pkg/resources/database.go | 60 +- pkg/resources/database_commons.go | 227 ++--- ...twork_policy_attachment_acceptance_test.go | 50 +- .../object_parameter_acceptance_test.go | 28 +- pkg/resources/resource_parameters_commons.go | 95 ++ .../resource_parameters_commons_test.go | 19 + pkg/resources/schema.go | 142 +-- pkg/resources/schema_parameters.go | 160 ++++ pkg/resources/secondary_database.go | 60 +- .../session_parameter_acceptance_test.go | 28 +- pkg/resources/shared_database.go | 54 +- pkg/resources/user.go | 282 ++++-- pkg/resources/user_acceptance_test.go | 308 +++++++ pkg/resources/user_parameters.go | 392 ++++++++ pkg/resources/user_parameters_test.go | 14 + .../user_public_keys_acceptance_test.go | 2 +- pkg/resources/warehouse.go | 34 +- pkg/schemas/user_parameters.go | 89 ++ pkg/sdk/databases.go | 9 + pkg/sdk/parameters.go | 102 +++ pkg/sdk/parsers.go | 2 +- pkg/sdk/parsers_test.go | 32 +- pkg/sdk/schemas.go | 9 + pkg/sdk/testint/databases_integration_test.go | 15 +- pkg/sdk/testint/schemas_integration_test.go | 12 +- pkg/sdk/testint/users_integration_test.go | 35 +- .../testint/warehouses_integration_test.go | 11 +- pkg/sdk/users.go | 9 + pkg/sdk/users_test.go | 328 +++++++ pkg/sdk/warehouses.go | 9 + templates/resources/user.md.tmpl | 32 + v1-preparations/CHANGES_BEFORE_V1.md | 2 +- v1-preparations/ESSENTIAL_GA_OBJECTS.MD | 2 +- v1-preparations/REMAINING_GA_OBJECTS.MD | 6 +- 46 files changed, 4321 insertions(+), 637 deletions(-) create mode 100644 pkg/acceptance/bettertestspoc/config/model/user_model_ext.go create mode 100644 pkg/resources/resource_parameters_commons.go create mode 100644 pkg/resources/resource_parameters_commons_test.go create mode 100644 pkg/resources/schema_parameters.go create mode 100644 pkg/resources/user_parameters.go create mode 100644 pkg/resources/user_parameters_test.go create mode 100644 pkg/schemas/user_parameters.go create mode 100644 templates/resources/user.md.tmpl diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index c417090a0a..0082d9442c 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -4,6 +4,78 @@ This document is meant to help you migrate your Terraform config to the new newe describe deprecations or breaking changes and help you to change your configuration to keep the same (or similar) behavior across different versions. +## v0.94.x ➞ v0.95.0 + +### snowflake_warehouse resource changes + +#### *(breaking change)* user parameters added to snowflake_user resource + +On our road to V1 we changed the approach to Snowflake parameters on the object level; now, we add them directly to the resource. This is a **breaking change** because now: +- Leaving the config empty does not set the default value on the object level but uses the one from hierarchy on Snowflake level instead (so after version bump, the diff running `UNSET` statements is expected). +- This change is not compatible with `snowflake_object_parameter` - you have to set the parameter inside `snowflake_user` resource **IF** you manage users through terraform **AND** you want to set the parameter on the user level. + +For more details, check the [Snowflake parameters](./v1-preparations/CHANGES_BEFORE_V1.md#snowflake-parameters). + +The following set of [parameters](https://docs.snowflake.com/en/sql-reference/parameters) was added to the `snowflake_user` resource: + - [ABORT_DETACHED_QUERY](https://docs.snowflake.com/en/sql-reference/parameters#abort-detached-query) + - [AUTOCOMMIT](https://docs.snowflake.com/en/sql-reference/parameters#autocommit) + - [BINARY_INPUT_FORMAT](https://docs.snowflake.com/en/sql-reference/parameters#binary-input-format) + - [BINARY_OUTPUT_FORMAT](https://docs.snowflake.com/en/sql-reference/parameters#binary-output-format) + - [CLIENT_MEMORY_LIMIT](https://docs.snowflake.com/en/sql-reference/parameters#client-memory-limit) + - [CLIENT_METADATA_REQUEST_USE_CONNECTION_CTX](https://docs.snowflake.com/en/sql-reference/parameters#client-metadata-request-use-connection-ctx) + - [CLIENT_PREFETCH_THREADS](https://docs.snowflake.com/en/sql-reference/parameters#client-prefetch-threads) + - [CLIENT_RESULT_CHUNK_SIZE](https://docs.snowflake.com/en/sql-reference/parameters#client-result-chunk-size) + - [CLIENT_RESULT_COLUMN_CASE_INSENSITIVE](https://docs.snowflake.com/en/sql-reference/parameters#client-result-column-case-insensitive) + - [CLIENT_SESSION_KEEP_ALIVE](https://docs.snowflake.com/en/sql-reference/parameters#client-session-keep-alive) + - [CLIENT_SESSION_KEEP_ALIVE_HEARTBEAT_FREQUENCY](https://docs.snowflake.com/en/sql-reference/parameters#client-session-keep-alive-heartbeat-frequency) + - [CLIENT_TIMESTAMP_TYPE_MAPPING](https://docs.snowflake.com/en/sql-reference/parameters#client-timestamp-type-mapping) + - [DATE_INPUT_FORMAT](https://docs.snowflake.com/en/sql-reference/parameters#date-input-format) + - [DATE_OUTPUT_FORMAT](https://docs.snowflake.com/en/sql-reference/parameters#date-output-format) + - [ENABLE_UNLOAD_PHYSICAL_TYPE_OPTIMIZATION](https://docs.snowflake.com/en/sql-reference/parameters#enable-unload-physical-type-optimization) + - [ERROR_ON_NONDETERMINISTIC_MERGE](https://docs.snowflake.com/en/sql-reference/parameters#error-on-nondeterministic-merge) + - [ERROR_ON_NONDETERMINISTIC_UPDATE](https://docs.snowflake.com/en/sql-reference/parameters#error-on-nondeterministic-update) + - [GEOGRAPHY_OUTPUT_FORMAT](https://docs.snowflake.com/en/sql-reference/parameters#geography-output-format) + - [GEOMETRY_OUTPUT_FORMAT](https://docs.snowflake.com/en/sql-reference/parameters#geometry-output-format) + - [JDBC_TREAT_DECIMAL_AS_INT](https://docs.snowflake.com/en/sql-reference/parameters#jdbc-treat-decimal-as-int) + - [JDBC_TREAT_TIMESTAMP_NTZ_AS_UTC](https://docs.snowflake.com/en/sql-reference/parameters#jdbc-treat-timestamp-ntz-as-utc) + - [JDBC_USE_SESSION_TIMEZONE](https://docs.snowflake.com/en/sql-reference/parameters#jdbc-use-session-timezone) + - [JSON_INDENT](https://docs.snowflake.com/en/sql-reference/parameters#json-indent) + - [LOCK_TIMEOUT](https://docs.snowflake.com/en/sql-reference/parameters#lock-timeout) + - [LOG_LEVEL](https://docs.snowflake.com/en/sql-reference/parameters#log-level) + - [MULTI_STATEMENT_COUNT](https://docs.snowflake.com/en/sql-reference/parameters#multi-statement-count) + - [NOORDER_SEQUENCE_AS_DEFAULT](https://docs.snowflake.com/en/sql-reference/parameters#noorder-sequence-as-default) + - [ODBC_TREAT_DECIMAL_AS_INT](https://docs.snowflake.com/en/sql-reference/parameters#odbc-treat-decimal-as-int) + - [QUERY_TAG](https://docs.snowflake.com/en/sql-reference/parameters#query-tag) + - [QUOTED_IDENTIFIERS_IGNORE_CASE](https://docs.snowflake.com/en/sql-reference/parameters#quoted-identifiers-ignore-case) + - [ROWS_PER_RESULTSET](https://docs.snowflake.com/en/sql-reference/parameters#rows-per-resultset) + - [S3_STAGE_VPCE_DNS_NAME](https://docs.snowflake.com/en/sql-reference/parameters#s3-stage-vpce-dns-name) + - [SEARCH_PATH](https://docs.snowflake.com/en/sql-reference/parameters#search-path) + - [SIMULATED_DATA_SHARING_CONSUMER](https://docs.snowflake.com/en/sql-reference/parameters#simulated-data-sharing-consumer) + - [STATEMENT_QUEUED_TIMEOUT_IN_SECONDS](https://docs.snowflake.com/en/sql-reference/parameters#statement-queued-timeout-in-seconds) + - [STATEMENT_TIMEOUT_IN_SECONDS](https://docs.snowflake.com/en/sql-reference/parameters#statement-timeout-in-seconds) + - [STRICT_JSON_OUTPUT](https://docs.snowflake.com/en/sql-reference/parameters#strict-json-output) + - [TIMESTAMP_DAY_IS_ALWAYS_24H](https://docs.snowflake.com/en/sql-reference/parameters#timestamp-day-is-always-24h) + - [TIMESTAMP_INPUT_FORMAT](https://docs.snowflake.com/en/sql-reference/parameters#timestamp-input-format) + - [TIMESTAMP_LTZ_OUTPUT_FORMAT](https://docs.snowflake.com/en/sql-reference/parameters#timestamp-ltz-output-format) + - [TIMESTAMP_NTZ_OUTPUT_FORMAT](https://docs.snowflake.com/en/sql-reference/parameters#timestamp-ntz-output-format) + - [TIMESTAMP_OUTPUT_FORMAT](https://docs.snowflake.com/en/sql-reference/parameters#timestamp-output-format) + - [TIMESTAMP_TYPE_MAPPING](https://docs.snowflake.com/en/sql-reference/parameters#timestamp-type-mapping) + - [TIMESTAMP_TZ_OUTPUT_FORMAT](https://docs.snowflake.com/en/sql-reference/parameters#timestamp-tz-output-format) + - [TIMEZONE](https://docs.snowflake.com/en/sql-reference/parameters#timezone) + - [TIME_INPUT_FORMAT](https://docs.snowflake.com/en/sql-reference/parameters#time-input-format) + - [TIME_OUTPUT_FORMAT](https://docs.snowflake.com/en/sql-reference/parameters#time-output-format) + - [TRACE_LEVEL](https://docs.snowflake.com/en/sql-reference/parameters#trace-level) + - [TRANSACTION_ABORT_ON_ERROR](https://docs.snowflake.com/en/sql-reference/parameters#transaction-abort-on-error) + - [TRANSACTION_DEFAULT_ISOLATION_LEVEL](https://docs.snowflake.com/en/sql-reference/parameters#transaction-default-isolation-level) + - [TWO_DIGIT_CENTURY_START](https://docs.snowflake.com/en/sql-reference/parameters#two-digit-century-start) + - [UNSUPPORTED_DDL_ACTION](https://docs.snowflake.com/en/sql-reference/parameters#unsupported-ddl-action) + - [USE_CACHED_RESULT](https://docs.snowflake.com/en/sql-reference/parameters#use-cached-result) + - [WEEK_OF_YEAR_POLICY](https://docs.snowflake.com/en/sql-reference/parameters#week-of-year-policy) + - [WEEK_START](https://docs.snowflake.com/en/sql-reference/parameters#week-start) + - [ENABLE_UNREDACTED_QUERY_SYNTAX_ERROR](https://docs.snowflake.com/en/sql-reference/parameters#enable-unredacted-query-syntax-error) + - [NETWORK_POLICY](https://docs.snowflake.com/en/sql-reference/parameters#network-policy) + - [PREVENT_UNLOAD_TO_INTERNAL_STAGES](https://docs.snowflake.com/en/sql-reference/parameters#prevent-unload-to-internal-stages) + ## v0.94.0 ➞ v0.94.1 ### changes in snowflake_schema diff --git a/docs/resources/schema.md b/docs/resources/schema.md index e3448ff674..704a302ce5 100644 --- a/docs/resources/schema.md +++ b/docs/resources/schema.md @@ -68,7 +68,7 @@ resource "snowflake_schema" "schema" { - `is_transient` (String) Specifies the schema as transient. Transient schemas do not have a Fail-safe period so they do not incur additional storage costs once they leave Time Travel; however, this means they are also not protected by Fail-safe in the event of a data loss. Available options are: "true" or "false". When the value is not set in the configuration the provider will put "default" there which means to use the Snowflake default for this value. - `log_level` (String) 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]. Messages at the specified level (and at more severe levels) are ingested. For more information, see [LOG_LEVEL](https://docs.snowflake.com/en/sql-reference/parameters.html#label-log-level). - `max_data_extension_time_in_days` (Number) 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. For a detailed description of this parameter, see [MAX_DATA_EXTENSION_TIME_IN_DAYS](https://docs.snowflake.com/en/sql-reference/parameters.html#label-max-data-extension-time-in-days). -- `pipe_execution_paused` (Boolean) Specifies whether to pause a running pipe, primarily in preparation for transferring ownership of the pipe to a different role. For more information, see [PIPE_EXECUTION_PAUSED](https://docs.snowflake.com/en/sql-reference/parameters#pipe-execution-paused). +- `pipe_execution_paused` (Boolean) Specifies whether to pause a running pipe, primarily in preparation for transferring ownership of the pipe to a different role. For more information, check [PIPE_EXECUTION_PAUSED docs](https://docs.snowflake.com/en/sql-reference/parameters#pipe-execution-paused). - `quoted_identifiers_ignore_case` (Boolean) If true, the case of quoted identifiers is ignored. For more information, see [QUOTED_IDENTIFIERS_IGNORE_CASE](https://docs.snowflake.com/en/sql-reference/parameters#quoted-identifiers-ignore-case). - `replace_invalid_characters` (Boolean) Specifies whether to replace invalid UTF-8 characters with the Unicode replacement character (�) in query results for an Iceberg table. You can only set this parameter for tables that use an external Iceberg catalog. For more information, see [REPLACE_INVALID_CHARACTERS](https://docs.snowflake.com/en/sql-reference/parameters#replace-invalid-characters). - `storage_serialization_policy` (String) The storage serialization policy for Iceberg tables that use Snowflake as the catalog. Valid options are: [COMPATIBLE OPTIMIZED]. COMPATIBLE: Snowflake performs encoding and compression of data files that ensures interoperability with third-party compute engines. OPTIMIZED: Snowflake performs encoding and compression of data files that ensures the best table performance within Snowflake. For more information, see [STORAGE_SERIALIZATION_POLICY](https://docs.snowflake.com/en/sql-reference/parameters#storage-serialization-policy). diff --git a/docs/resources/user.md b/docs/resources/user.md index 1caa0af951..ff060871c1 100644 --- a/docs/resources/user.md +++ b/docs/resources/user.md @@ -5,6 +5,8 @@ description: |- --- +!> **V1 release candidate** This resource was reworked and is a release candidate for the V1. We do not expect significant changes in it before the V1. We will welcome any feedback and adjust the resource if needed. Any errors reported will be resolved with a higher priority. We encourage checking this resource out before the V1 release. Please follow the [migration guide](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/MIGRATION_GUIDE.md#v094x--v0950) to use it. + # snowflake_user (Resource) @@ -43,7 +45,21 @@ resource "snowflake_user" "user" { ### Optional +- `abort_detached_query` (Boolean) Specifies the action that Snowflake performs for in-progress queries if connectivity is lost due to abrupt termination of a session (e.g. network outage, browser termination, service interruption). For more information, check [ABORT_DETACHED_QUERY docs](https://docs.snowflake.com/en/sql-reference/parameters#abort-detached-query). +- `autocommit` (Boolean) Specifies whether autocommit is enabled for the session. Autocommit determines whether a DML statement, when executed without an active transaction, is automatically committed after the statement successfully completes. For more information, see [Transactions](https://docs.snowflake.com/en/sql-reference/transactions). For more information, check [AUTOCOMMIT docs](https://docs.snowflake.com/en/sql-reference/parameters#autocommit). +- `binary_input_format` (String) The format of VARCHAR values passed as input to VARCHAR-to-BINARY conversion functions. For more information, see [Binary input and output](https://docs.snowflake.com/en/sql-reference/binary-input-output). For more information, check [BINARY_INPUT_FORMAT docs](https://docs.snowflake.com/en/sql-reference/parameters#binary-input-format). +- `binary_output_format` (String) The format for VARCHAR values returned as output by BINARY-to-VARCHAR conversion functions. For more information, see [Binary input and output](https://docs.snowflake.com/en/sql-reference/binary-input-output). For more information, check [BINARY_OUTPUT_FORMAT docs](https://docs.snowflake.com/en/sql-reference/parameters#binary-output-format). +- `client_memory_limit` (Number) Parameter that specifies the maximum amount of memory the JDBC driver or ODBC driver should use for the result set from queries (in MB). For more information, check [CLIENT_MEMORY_LIMIT docs](https://docs.snowflake.com/en/sql-reference/parameters#client-memory-limit). +- `client_metadata_request_use_connection_ctx` (Boolean) For specific ODBC functions and JDBC methods, this parameter can change the default search scope from all databases/schemas to the current database/schema. The narrower search typically returns fewer rows and executes more quickly. For more information, check [CLIENT_METADATA_REQUEST_USE_CONNECTION_CTX docs](https://docs.snowflake.com/en/sql-reference/parameters#client-metadata-request-use-connection-ctx). +- `client_prefetch_threads` (Number) Parameter that specifies the number of threads used by the client to pre-fetch large result sets. The driver will attempt to honor the parameter value, but defines the minimum and maximum values (depending on your system’s resources) to improve performance. For more information, check [CLIENT_PREFETCH_THREADS docs](https://docs.snowflake.com/en/sql-reference/parameters#client-prefetch-threads). +- `client_result_chunk_size` (Number) Parameter that specifies the maximum size of each set (or chunk) of query results to download (in MB). The JDBC driver downloads query results in chunks. For more information, check [CLIENT_RESULT_CHUNK_SIZE docs](https://docs.snowflake.com/en/sql-reference/parameters#client-result-chunk-size). +- `client_result_column_case_insensitive` (Boolean) Parameter that indicates whether to match column name case-insensitively in ResultSet.get* methods in JDBC. For more information, check [CLIENT_RESULT_COLUMN_CASE_INSENSITIVE docs](https://docs.snowflake.com/en/sql-reference/parameters#client-result-column-case-insensitive). +- `client_session_keep_alive` (Boolean) Parameter that indicates whether to force a user to log in again after a period of inactivity in the session. For more information, check [CLIENT_SESSION_KEEP_ALIVE docs](https://docs.snowflake.com/en/sql-reference/parameters#client-session-keep-alive). +- `client_session_keep_alive_heartbeat_frequency` (Number) Number of seconds in-between client attempts to update the token for the session. For more information, check [CLIENT_SESSION_KEEP_ALIVE_HEARTBEAT_FREQUENCY docs](https://docs.snowflake.com/en/sql-reference/parameters#client-session-keep-alive-heartbeat-frequency). +- `client_timestamp_type_mapping` (String) Specifies the [TIMESTAMP_* variation](https://docs.snowflake.com/en/sql-reference/data-types-datetime.html#label-datatypes-timestamp-variations) to use when binding timestamp variables for JDBC or ODBC applications that use the bind API to load data. For more information, check [CLIENT_TIMESTAMP_TYPE_MAPPING docs](https://docs.snowflake.com/en/sql-reference/parameters#client-timestamp-type-mapping). - `comment` (String) +- `date_input_format` (String) Specifies the input format for the DATE data type. For more information, see [Date and time input and output formats](https://docs.snowflake.com/en/sql-reference/date-time-input-output). For more information, check [DATE_INPUT_FORMAT docs](https://docs.snowflake.com/en/sql-reference/parameters#date-input-format). +- `date_output_format` (String) Specifies the display format for the DATE data type. For more information, see [Date and time input and output formats](https://docs.snowflake.com/en/sql-reference/date-time-input-output). For more information, check [DATE_OUTPUT_FORMAT docs](https://docs.snowflake.com/en/sql-reference/parameters#date-output-format). - `default_namespace` (String) Specifies the namespace (database only or database and schema) that is active by default for the user’s session upon login. - `default_role` (String) Specifies the role that is active by default for the user’s session upon login. - `default_secondary_roles` (Set of String) Specifies the set of secondary roles that are active for the user’s session upon login. Currently only ["ALL"] value is supported - more information can be found in [doc](https://docs.snowflake.com/en/sql-reference/sql/create-user#optional-object-properties-objectproperties) @@ -51,18 +67,857 @@ resource "snowflake_user" "user" { - `disabled` (Boolean) - `display_name` (String, Sensitive) Name displayed for the user in the Snowflake web interface. - `email` (String, Sensitive) Email address for the user. +- `enable_unload_physical_type_optimization` (Boolean) Specifies whether to set the schema for unloaded Parquet files based on the logical column data types (i.e. the types in the unload SQL query or source table) or on the unloaded column values (i.e. the smallest data types and precision that support the values in the output columns of the unload SQL statement or source table). For more information, check [ENABLE_UNLOAD_PHYSICAL_TYPE_OPTIMIZATION docs](https://docs.snowflake.com/en/sql-reference/parameters#enable-unload-physical-type-optimization). +- `enable_unredacted_query_syntax_error` (Boolean) Controls whether query text is redacted if a SQL query fails due to a syntax or parsing error. If `FALSE`, the content of a failed query is redacted in the views, pages, and functions that provide a query history. Only users with a role that is granted or inherits the AUDIT privilege can set the ENABLE_UNREDACTED_QUERY_SYNTAX_ERROR parameter. When using the ALTER USER command to set the parameter to `TRUE` for a particular user, modify the user that you want to see the query text, not the user who executed the query (if those are different users). For more information, check [ENABLE_UNREDACTED_QUERY_SYNTAX_ERROR docs](https://docs.snowflake.com/en/sql-reference/parameters#enable-unredacted-query-syntax-error). +- `error_on_nondeterministic_merge` (Boolean) Specifies whether to return an error when the [MERGE](https://docs.snowflake.com/en/sql-reference/sql/merge) command is used to update or delete a target row that joins multiple source rows and the system cannot determine the action to perform on the target row. For more information, check [ERROR_ON_NONDETERMINISTIC_MERGE docs](https://docs.snowflake.com/en/sql-reference/parameters#error-on-nondeterministic-merge). +- `error_on_nondeterministic_update` (Boolean) Specifies whether to return an error when the [UPDATE](https://docs.snowflake.com/en/sql-reference/sql/update) command is used to update a target row that joins multiple source rows and the system cannot determine the action to perform on the target row. For more information, check [ERROR_ON_NONDETERMINISTIC_UPDATE docs](https://docs.snowflake.com/en/sql-reference/parameters#error-on-nondeterministic-update). - `first_name` (String, Sensitive) First name of the user. +- `geography_output_format` (String) Display format for [GEOGRAPHY values](https://docs.snowflake.com/en/sql-reference/data-types-geospatial.html#label-data-types-geography). For more information, check [GEOGRAPHY_OUTPUT_FORMAT docs](https://docs.snowflake.com/en/sql-reference/parameters#geography-output-format). +- `geometry_output_format` (String) Display format for [GEOMETRY values](https://docs.snowflake.com/en/sql-reference/data-types-geospatial.html#label-data-types-geometry). For more information, check [GEOMETRY_OUTPUT_FORMAT docs](https://docs.snowflake.com/en/sql-reference/parameters#geometry-output-format). +- `jdbc_treat_decimal_as_int` (Boolean) Specifies how JDBC processes columns that have a scale of zero (0). For more information, check [JDBC_TREAT_DECIMAL_AS_INT docs](https://docs.snowflake.com/en/sql-reference/parameters#jdbc-treat-decimal-as-int). +- `jdbc_treat_timestamp_ntz_as_utc` (Boolean) Specifies how JDBC processes TIMESTAMP_NTZ values. For more information, check [JDBC_TREAT_TIMESTAMP_NTZ_AS_UTC docs](https://docs.snowflake.com/en/sql-reference/parameters#jdbc-treat-timestamp-ntz-as-utc). +- `jdbc_use_session_timezone` (Boolean) Specifies whether the JDBC Driver uses the time zone of the JVM or the time zone of the session (specified by the [TIMEZONE](https://docs.snowflake.com/en/sql-reference/parameters#label-timezone) parameter) for the getDate(), getTime(), and getTimestamp() methods of the ResultSet class. For more information, check [JDBC_USE_SESSION_TIMEZONE docs](https://docs.snowflake.com/en/sql-reference/parameters#jdbc-use-session-timezone). +- `json_indent` (Number) Specifies the number of blank spaces to indent each new element in JSON output in the session. Also specifies whether to insert newline characters after each element. For more information, check [JSON_INDENT docs](https://docs.snowflake.com/en/sql-reference/parameters#json-indent). - `last_name` (String, Sensitive) Last name of the user. +- `lock_timeout` (Number) Number of seconds to wait while trying to lock a resource, before timing out and aborting the statement. For more information, check [LOCK_TIMEOUT docs](https://docs.snowflake.com/en/sql-reference/parameters#lock-timeout). +- `log_level` (String) Specifies the severity level of messages that should be ingested and made available in the active event table. Messages at the specified level (and at more severe levels) are ingested. For more information about log levels, see [Setting log level](https://docs.snowflake.com/en/developer-guide/logging-tracing/logging-log-level). For more information, check [LOG_LEVEL docs](https://docs.snowflake.com/en/sql-reference/parameters#log-level). - `login_name` (String) The name users use to log in. If not supplied, snowflake will use name instead. +- `multi_statement_count` (Number) Number of statements to execute when using the multi-statement capability. For more information, check [MULTI_STATEMENT_COUNT docs](https://docs.snowflake.com/en/sql-reference/parameters#multi-statement-count). - `must_change_password` (Boolean) Specifies whether the user is forced to change their password on next login (including their first/initial login) into the system. +- `network_policy` (String) Specifies the network policy to enforce for your account. Network policies enable restricting access to your account based on users’ IP address. For more details, see [Controlling network traffic with network policies](https://docs.snowflake.com/en/user-guide/network-policies). Any existing network policy (created using [CREATE NETWORK POLICY](https://docs.snowflake.com/en/sql-reference/sql/create-network-policy)). For more information, check [NETWORK_POLICY docs](https://docs.snowflake.com/en/sql-reference/parameters#network-policy). +- `noorder_sequence_as_default` (Boolean) Specifies whether the ORDER or NOORDER property is set by default when you create a new sequence or add a new table column. The ORDER and NOORDER properties determine whether or not the values are generated for the sequence or auto-incremented column in [increasing or decreasing order](https://docs.snowflake.com/en/user-guide/querying-sequences.html#label-querying-sequences-increasing-values). For more information, check [NOORDER_SEQUENCE_AS_DEFAULT docs](https://docs.snowflake.com/en/sql-reference/parameters#noorder-sequence-as-default). +- `odbc_treat_decimal_as_int` (Boolean) Specifies how ODBC processes columns that have a scale of zero (0). For more information, check [ODBC_TREAT_DECIMAL_AS_INT docs](https://docs.snowflake.com/en/sql-reference/parameters#odbc-treat-decimal-as-int). - `password` (String, Sensitive) **WARNING:** this will put the password in the terraform state file. Use carefully. +- `prevent_unload_to_internal_stages` (Boolean) Specifies whether to prevent data unload operations to internal (Snowflake) stages using [COPY INTO ](https://docs.snowflake.com/en/sql-reference/sql/copy-into-location) statements. For more information, check [PREVENT_UNLOAD_TO_INTERNAL_STAGES docs](https://docs.snowflake.com/en/sql-reference/parameters#prevent-unload-to-internal-stages). +- `query_tag` (String) Optional string that can be used to tag queries and other SQL statements executed within a session. The tags are displayed in the output of the [QUERY_HISTORY, QUERY_HISTORY_BY_*](https://docs.snowflake.com/en/sql-reference/functions/query_history) functions. For more information, check [QUERY_TAG docs](https://docs.snowflake.com/en/sql-reference/parameters#query-tag). +- `quoted_identifiers_ignore_case` (Boolean) Specifies whether letters in double-quoted object identifiers are stored and resolved as uppercase letters. By default, Snowflake preserves the case of alphabetic characters when storing and resolving double-quoted identifiers (see [Identifier resolution](https://docs.snowflake.com/en/sql-reference/identifiers-syntax.html#label-identifier-casing)). You can use this parameter in situations in which [third-party applications always use double quotes around identifiers](https://docs.snowflake.com/en/sql-reference/identifiers-syntax.html#label-identifier-casing-parameter). For more information, check [QUOTED_IDENTIFIERS_IGNORE_CASE docs](https://docs.snowflake.com/en/sql-reference/parameters#quoted-identifiers-ignore-case). +- `rows_per_resultset` (Number) Specifies the maximum number of rows returned in a result set. A value of 0 specifies no maximum. For more information, check [ROWS_PER_RESULTSET docs](https://docs.snowflake.com/en/sql-reference/parameters#rows-per-resultset). - `rsa_public_key` (String) Specifies the user’s RSA public key; used for key-pair authentication. Must be on 1 line without header and trailer. - `rsa_public_key_2` (String) Specifies the user’s second RSA public key; used to rotate the public and private keys for key-pair authentication based on an expiration schedule set by your organization. Must be on 1 line without header and trailer. +- `s3_stage_vpce_dns_name` (String) Specifies the DNS name of an Amazon S3 interface endpoint. Requests sent to the internal stage of an account via [AWS PrivateLink for Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/privatelink-interface-endpoints.html) use this endpoint to connect. For more information, see [Accessing Internal stages with dedicated interface endpoints](https://docs.snowflake.com/en/user-guide/private-internal-stages-aws.html#label-aws-privatelink-internal-stage-network-isolation). For more information, check [S3_STAGE_VPCE_DNS_NAME docs](https://docs.snowflake.com/en/sql-reference/parameters#s3-stage-vpce-dns-name). +- `search_path` (String) Specifies the path to search to resolve unqualified object names in queries. For more information, see [Name resolution in queries](https://docs.snowflake.com/en/sql-reference/name-resolution.html#label-object-name-resolution-search-path). Comma-separated list of identifiers. An identifier can be a fully or partially qualified schema name. For more information, check [SEARCH_PATH docs](https://docs.snowflake.com/en/sql-reference/parameters#search-path). +- `simulated_data_sharing_consumer` (String) Specifies the name of a consumer account to simulate for testing/validating shared data, particularly shared secure views. When this parameter is set in a session, shared views return rows as if executed in the specified consumer account rather than the provider account. For more information, see [Introduction to Secure Data Sharing](https://docs.snowflake.com/en/user-guide/data-sharing-intro) and [Working with shares](https://docs.snowflake.com/en/user-guide/data-sharing-provider). For more information, check [SIMULATED_DATA_SHARING_CONSUMER docs](https://docs.snowflake.com/en/sql-reference/parameters#simulated-data-sharing-consumer). +- `statement_queued_timeout_in_seconds` (Number) Amount of time, in seconds, a SQL statement (query, DDL, DML, etc.) remains queued for a warehouse before it is canceled by the system. This parameter can be used in conjunction with the [MAX_CONCURRENCY_LEVEL](https://docs.snowflake.com/en/sql-reference/parameters#label-max-concurrency-level) parameter to ensure a warehouse is never backlogged. For more information, check [STATEMENT_QUEUED_TIMEOUT_IN_SECONDS docs](https://docs.snowflake.com/en/sql-reference/parameters#statement-queued-timeout-in-seconds). +- `statement_timeout_in_seconds` (Number) Amount of time, in seconds, after which a running SQL statement (query, DDL, DML, etc.) is canceled by the system. For more information, check [STATEMENT_TIMEOUT_IN_SECONDS docs](https://docs.snowflake.com/en/sql-reference/parameters#statement-timeout-in-seconds). +- `strict_json_output` (Boolean) This parameter specifies whether JSON output in a session is compatible with the general standard (as described by [http://json.org](http://json.org)). By design, Snowflake allows JSON input that contains non-standard values; however, these non-standard values might result in Snowflake outputting JSON that is incompatible with other platforms and languages. This parameter, when enabled, ensures that Snowflake outputs valid/compatible JSON. For more information, check [STRICT_JSON_OUTPUT docs](https://docs.snowflake.com/en/sql-reference/parameters#strict-json-output). +- `time_input_format` (String) Specifies the input format for the TIME data type. For more information, see [Date and time input and output formats](https://docs.snowflake.com/en/sql-reference/date-time-input-output). Any valid, supported time format or AUTO (AUTO specifies that Snowflake attempts to automatically detect the format of times stored in the system during the session). For more information, check [TIME_INPUT_FORMAT docs](https://docs.snowflake.com/en/sql-reference/parameters#time-input-format). +- `time_output_format` (String) Specifies the display format for the TIME data type. For more information, see [Date and time input and output formats](https://docs.snowflake.com/en/sql-reference/date-time-input-output). For more information, check [TIME_OUTPUT_FORMAT docs](https://docs.snowflake.com/en/sql-reference/parameters#time-output-format). +- `timestamp_day_is_always_24h` (Boolean) Specifies whether the [DATEADD](https://docs.snowflake.com/en/sql-reference/functions/dateadd) function (and its aliases) always consider a day to be exactly 24 hours for expressions that span multiple days. For more information, check [TIMESTAMP_DAY_IS_ALWAYS_24H docs](https://docs.snowflake.com/en/sql-reference/parameters#timestamp-day-is-always-24h). +- `timestamp_input_format` (String) Specifies the input format for the TIMESTAMP data type alias. For more information, see [Date and time input and output formats](https://docs.snowflake.com/en/sql-reference/date-time-input-output). Any valid, supported timestamp format or AUTO (AUTO specifies that Snowflake attempts to automatically detect the format of timestamps stored in the system during the session). For more information, check [TIMESTAMP_INPUT_FORMAT docs](https://docs.snowflake.com/en/sql-reference/parameters#timestamp-input-format). +- `timestamp_ltz_output_format` (String) Specifies the display format for the TIMESTAMP_LTZ data type. If no format is specified, defaults to [TIMESTAMP_OUTPUT_FORMAT](https://docs.snowflake.com/en/sql-reference/parameters#label-timestamp-output-format). For more information, see [Date and time input and output formats](https://docs.snowflake.com/en/sql-reference/date-time-input-output). For more information, check [TIMESTAMP_LTZ_OUTPUT_FORMAT docs](https://docs.snowflake.com/en/sql-reference/parameters#timestamp-ltz-output-format). +- `timestamp_ntz_output_format` (String) Specifies the display format for the TIMESTAMP_NTZ data type. For more information, check [TIMESTAMP_NTZ_OUTPUT_FORMAT docs](https://docs.snowflake.com/en/sql-reference/parameters#timestamp-ntz-output-format). +- `timestamp_output_format` (String) Specifies the display format for the TIMESTAMP data type alias. For more information, see [Date and time input and output formats](https://docs.snowflake.com/en/sql-reference/date-time-input-output). For more information, check [TIMESTAMP_OUTPUT_FORMAT docs](https://docs.snowflake.com/en/sql-reference/parameters#timestamp-output-format). +- `timestamp_type_mapping` (String) Specifies the TIMESTAMP_* variation that the TIMESTAMP data type alias maps to. For more information, check [TIMESTAMP_TYPE_MAPPING docs](https://docs.snowflake.com/en/sql-reference/parameters#timestamp-type-mapping). +- `timestamp_tz_output_format` (String) Specifies the display format for the TIMESTAMP_TZ data type. If no format is specified, defaults to [TIMESTAMP_OUTPUT_FORMAT](https://docs.snowflake.com/en/sql-reference/parameters#label-timestamp-output-format). For more information, see [Date and time input and output formats](https://docs.snowflake.com/en/sql-reference/date-time-input-output). For more information, check [TIMESTAMP_TZ_OUTPUT_FORMAT docs](https://docs.snowflake.com/en/sql-reference/parameters#timestamp-tz-output-format). +- `timezone` (String) Specifies the time zone for the session. You can specify a [time zone name](https://data.iana.org/time-zones/tzdb-2021a/zone1970.tab) or a [link name](https://data.iana.org/time-zones/tzdb-2021a/backward) from release 2021a of the [IANA Time Zone Database](https://www.iana.org/time-zones) (e.g. America/Los_Angeles, Europe/London, UTC, Etc/GMT, etc.). For more information, check [TIMEZONE docs](https://docs.snowflake.com/en/sql-reference/parameters#timezone). +- `trace_level` (String) Controls how trace events are ingested into the event table. For more information about trace levels, see [Setting trace level](https://docs.snowflake.com/en/developer-guide/logging-tracing/tracing-trace-level). For more information, check [TRACE_LEVEL docs](https://docs.snowflake.com/en/sql-reference/parameters#trace-level). +- `transaction_abort_on_error` (Boolean) Specifies the action to perform when a statement issued within a non-autocommit transaction returns with an error. For more information, check [TRANSACTION_ABORT_ON_ERROR docs](https://docs.snowflake.com/en/sql-reference/parameters#transaction-abort-on-error). +- `transaction_default_isolation_level` (String) Specifies the isolation level for transactions in the user session. For more information, check [TRANSACTION_DEFAULT_ISOLATION_LEVEL docs](https://docs.snowflake.com/en/sql-reference/parameters#transaction-default-isolation-level). +- `two_digit_century_start` (Number) Specifies the “century start” year for 2-digit years (i.e. the earliest year such dates can represent). This parameter prevents ambiguous dates when importing or converting data with the `YY` date format component (i.e. years represented as 2 digits). For more information, check [TWO_DIGIT_CENTURY_START docs](https://docs.snowflake.com/en/sql-reference/parameters#two-digit-century-start). +- `unsupported_ddl_action` (String) Determines if an unsupported (i.e. non-default) value specified for a constraint property returns an error. For more information, check [UNSUPPORTED_DDL_ACTION docs](https://docs.snowflake.com/en/sql-reference/parameters#unsupported-ddl-action). +- `use_cached_result` (Boolean) Specifies whether to reuse persisted query results, if available, when a matching query is submitted. For more information, check [USE_CACHED_RESULT docs](https://docs.snowflake.com/en/sql-reference/parameters#use-cached-result). +- `week_of_year_policy` (Number) Specifies how the weeks in a given year are computed. `0`: The semantics used are equivalent to the ISO semantics, in which a week belongs to a given year if at least 4 days of that week are in that year. `1`: January 1 is included in the first week of the year and December 31 is included in the last week of the year. For more information, check [WEEK_OF_YEAR_POLICY docs](https://docs.snowflake.com/en/sql-reference/parameters#week-of-year-policy). +- `week_start` (Number) Specifies the first day of the week (used by week-related date functions). `0`: Legacy Snowflake behavior is used (i.e. ISO-like semantics). `1` (Monday) to `7` (Sunday): All the week-related functions use weeks that start on the specified day of the week. For more information, check [WEEK_START docs](https://docs.snowflake.com/en/sql-reference/parameters#week-start). ### Read-Only - `has_rsa_public_key` (Boolean) Will be true if user as an RSA key set. - `id` (String) The ID of this resource. +- `parameters` (List of Object) Outputs the result of `SHOW PARAMETERS IN USER` for the given user. (see [below for nested schema](#nestedatt--parameters)) +- `show_output` (List of Object) Outputs the result of `SHOW USER` for the given user. (see [below for nested schema](#nestedatt--show_output)) + + +### Nested Schema for `parameters` + +Read-Only: + +- `abort_detached_query` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--abort_detached_query)) +- `autocommit` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--autocommit)) +- `binary_input_format` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--binary_input_format)) +- `binary_output_format` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--binary_output_format)) +- `client_memory_limit` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--client_memory_limit)) +- `client_metadata_request_use_connection_ctx` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--client_metadata_request_use_connection_ctx)) +- `client_prefetch_threads` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--client_prefetch_threads)) +- `client_result_chunk_size` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--client_result_chunk_size)) +- `client_result_column_case_insensitive` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--client_result_column_case_insensitive)) +- `client_session_keep_alive` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--client_session_keep_alive)) +- `client_session_keep_alive_heartbeat_frequency` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--client_session_keep_alive_heartbeat_frequency)) +- `client_timestamp_type_mapping` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--client_timestamp_type_mapping)) +- `date_input_format` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--date_input_format)) +- `date_output_format` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--date_output_format)) +- `enable_unload_physical_type_optimization` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--enable_unload_physical_type_optimization)) +- `enable_unredacted_query_syntax_error` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--enable_unredacted_query_syntax_error)) +- `error_on_nondeterministic_merge` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--error_on_nondeterministic_merge)) +- `error_on_nondeterministic_update` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--error_on_nondeterministic_update)) +- `geography_output_format` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--geography_output_format)) +- `geometry_output_format` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--geometry_output_format)) +- `jdbc_treat_decimal_as_int` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--jdbc_treat_decimal_as_int)) +- `jdbc_treat_timestamp_ntz_as_utc` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--jdbc_treat_timestamp_ntz_as_utc)) +- `jdbc_use_session_timezone` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--jdbc_use_session_timezone)) +- `json_indent` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--json_indent)) +- `lock_timeout` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--lock_timeout)) +- `log_level` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--log_level)) +- `multi_statement_count` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--multi_statement_count)) +- `network_policy` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--network_policy)) +- `noorder_sequence_as_default` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--noorder_sequence_as_default)) +- `odbc_treat_decimal_as_int` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--odbc_treat_decimal_as_int)) +- `prevent_unload_to_internal_stages` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--prevent_unload_to_internal_stages)) +- `query_tag` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--query_tag)) +- `quoted_identifiers_ignore_case` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--quoted_identifiers_ignore_case)) +- `rows_per_resultset` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--rows_per_resultset)) +- `s3_stage_vpce_dns_name` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--s3_stage_vpce_dns_name)) +- `search_path` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--search_path)) +- `simulated_data_sharing_consumer` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--simulated_data_sharing_consumer)) +- `statement_queued_timeout_in_seconds` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--statement_queued_timeout_in_seconds)) +- `statement_timeout_in_seconds` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--statement_timeout_in_seconds)) +- `strict_json_output` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--strict_json_output)) +- `time_input_format` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--time_input_format)) +- `time_output_format` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--time_output_format)) +- `timestamp_day_is_always_24h` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--timestamp_day_is_always_24h)) +- `timestamp_input_format` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--timestamp_input_format)) +- `timestamp_ltz_output_format` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--timestamp_ltz_output_format)) +- `timestamp_ntz_output_format` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--timestamp_ntz_output_format)) +- `timestamp_output_format` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--timestamp_output_format)) +- `timestamp_type_mapping` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--timestamp_type_mapping)) +- `timestamp_tz_output_format` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--timestamp_tz_output_format)) +- `timezone` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--timezone)) +- `trace_level` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--trace_level)) +- `transaction_abort_on_error` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--transaction_abort_on_error)) +- `transaction_default_isolation_level` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--transaction_default_isolation_level)) +- `two_digit_century_start` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--two_digit_century_start)) +- `unsupported_ddl_action` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--unsupported_ddl_action)) +- `use_cached_result` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--use_cached_result)) +- `week_of_year_policy` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--week_of_year_policy)) +- `week_start` (List of Object) (see [below for nested schema](#nestedobjatt--parameters--week_start)) + + +### Nested Schema for `parameters.abort_detached_query` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.autocommit` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.binary_input_format` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.binary_output_format` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.client_memory_limit` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.client_metadata_request_use_connection_ctx` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.client_prefetch_threads` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.client_result_chunk_size` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.client_result_column_case_insensitive` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.client_session_keep_alive` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.client_session_keep_alive_heartbeat_frequency` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.client_timestamp_type_mapping` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.date_input_format` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.date_output_format` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.enable_unload_physical_type_optimization` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.enable_unredacted_query_syntax_error` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.error_on_nondeterministic_merge` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.error_on_nondeterministic_update` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.geography_output_format` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.geometry_output_format` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.jdbc_treat_decimal_as_int` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.jdbc_treat_timestamp_ntz_as_utc` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.jdbc_use_session_timezone` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.json_indent` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.lock_timeout` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.log_level` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.multi_statement_count` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.network_policy` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.noorder_sequence_as_default` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.odbc_treat_decimal_as_int` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.prevent_unload_to_internal_stages` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.query_tag` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.quoted_identifiers_ignore_case` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.rows_per_resultset` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.s3_stage_vpce_dns_name` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.search_path` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.simulated_data_sharing_consumer` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.statement_queued_timeout_in_seconds` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.statement_timeout_in_seconds` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.strict_json_output` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.time_input_format` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.time_output_format` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.timestamp_day_is_always_24h` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.timestamp_input_format` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.timestamp_ltz_output_format` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.timestamp_ntz_output_format` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.timestamp_output_format` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.timestamp_type_mapping` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.timestamp_tz_output_format` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.timezone` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.trace_level` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.transaction_abort_on_error` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.transaction_default_isolation_level` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.two_digit_century_start` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.unsupported_ddl_action` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.use_cached_result` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.week_of_year_policy` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + +### Nested Schema for `parameters.week_start` + +Read-Only: + +- `default` (String) +- `description` (String) +- `key` (String) +- `level` (String) +- `value` (String) + + + + +### Nested Schema for `show_output` + +Read-Only: + +- `comment` (String) +- `created_on` (String) +- `days_to_expiry` (String) +- `default_namespace` (String) +- `default_role` (String) +- `default_secondary_roles` (String) +- `default_warehouse` (String) +- `disabled` (Boolean) +- `display_name` (String) +- `email` (String) +- `expires_at_time` (String) +- `ext_authn_duo` (Boolean) +- `ext_authn_uid` (String) +- `first_name` (String) +- `has_password` (Boolean) +- `has_rsa_public_key` (Boolean) +- `last_name` (String) +- `last_success_login` (String) +- `locked_until_time` (String) +- `login_name` (String) +- `mins_to_bypass_mfa` (String) +- `mins_to_unlock` (String) +- `must_change_password` (Boolean) +- `name` (String) +- `owner` (String) +- `snowflake_lock` (Boolean) ## Import diff --git a/pkg/acceptance/bettertestspoc/assert/resourceassert/user_resource_gen.go b/pkg/acceptance/bettertestspoc/assert/resourceassert/user_resource_gen.go index 45f5bbd716..2693a8e9d4 100644 --- a/pkg/acceptance/bettertestspoc/assert/resourceassert/user_resource_gen.go +++ b/pkg/acceptance/bettertestspoc/assert/resourceassert/user_resource_gen.go @@ -32,11 +32,81 @@ func ImportedUserResource(t *testing.T, id string) *UserResourceAssert { // Attribute value string checks // /////////////////////////////////// +func (u *UserResourceAssert) HasAbortDetachedQueryString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("abort_detached_query", expected)) + return u +} + +func (u *UserResourceAssert) HasAutocommitString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("autocommit", expected)) + return u +} + +func (u *UserResourceAssert) HasBinaryInputFormatString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("binary_input_format", expected)) + return u +} + +func (u *UserResourceAssert) HasBinaryOutputFormatString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("binary_output_format", expected)) + return u +} + +func (u *UserResourceAssert) HasClientMemoryLimitString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("client_memory_limit", expected)) + return u +} + +func (u *UserResourceAssert) HasClientMetadataRequestUseConnectionCtxString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("client_metadata_request_use_connection_ctx", expected)) + return u +} + +func (u *UserResourceAssert) HasClientPrefetchThreadsString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("client_prefetch_threads", expected)) + return u +} + +func (u *UserResourceAssert) HasClientResultChunkSizeString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("client_result_chunk_size", expected)) + return u +} + +func (u *UserResourceAssert) HasClientResultColumnCaseInsensitiveString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("client_result_column_case_insensitive", expected)) + return u +} + +func (u *UserResourceAssert) HasClientSessionKeepAliveString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("client_session_keep_alive", expected)) + return u +} + +func (u *UserResourceAssert) HasClientSessionKeepAliveHeartbeatFrequencyString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("client_session_keep_alive_heartbeat_frequency", expected)) + return u +} + +func (u *UserResourceAssert) HasClientTimestampTypeMappingString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("client_timestamp_type_mapping", expected)) + return u +} + func (u *UserResourceAssert) HasCommentString(expected string) *UserResourceAssert { u.AddAssertion(assert.ValueSet("comment", expected)) return u } +func (u *UserResourceAssert) HasDateInputFormatString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("date_input_format", expected)) + return u +} + +func (u *UserResourceAssert) HasDateOutputFormatString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("date_output_format", expected)) + return u +} + func (u *UserResourceAssert) HasDefaultNamespaceString(expected string) *UserResourceAssert { u.AddAssertion(assert.ValueSet("default_namespace", expected)) return u @@ -72,26 +142,91 @@ func (u *UserResourceAssert) HasEmailString(expected string) *UserResourceAssert return u } +func (u *UserResourceAssert) HasEnableUnloadPhysicalTypeOptimizationString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("enable_unload_physical_type_optimization", expected)) + return u +} + +func (u *UserResourceAssert) HasEnableUnredactedQuerySyntaxErrorString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("enable_unredacted_query_syntax_error", expected)) + return u +} + +func (u *UserResourceAssert) HasErrorOnNondeterministicMergeString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("error_on_nondeterministic_merge", expected)) + return u +} + +func (u *UserResourceAssert) HasErrorOnNondeterministicUpdateString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("error_on_nondeterministic_update", expected)) + return u +} + func (u *UserResourceAssert) HasFirstNameString(expected string) *UserResourceAssert { u.AddAssertion(assert.ValueSet("first_name", expected)) return u } +func (u *UserResourceAssert) HasGeographyOutputFormatString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("geography_output_format", expected)) + return u +} + +func (u *UserResourceAssert) HasGeometryOutputFormatString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("geometry_output_format", expected)) + return u +} + func (u *UserResourceAssert) HasHasRsaPublicKeyString(expected string) *UserResourceAssert { u.AddAssertion(assert.ValueSet("has_rsa_public_key", expected)) return u } +func (u *UserResourceAssert) HasJdbcTreatDecimalAsIntString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("jdbc_treat_decimal_as_int", expected)) + return u +} + +func (u *UserResourceAssert) HasJdbcTreatTimestampNtzAsUtcString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("jdbc_treat_timestamp_ntz_as_utc", expected)) + return u +} + +func (u *UserResourceAssert) HasJdbcUseSessionTimezoneString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("jdbc_use_session_timezone", expected)) + return u +} + +func (u *UserResourceAssert) HasJsonIndentString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("json_indent", expected)) + return u +} + func (u *UserResourceAssert) HasLastNameString(expected string) *UserResourceAssert { u.AddAssertion(assert.ValueSet("last_name", expected)) return u } +func (u *UserResourceAssert) HasLockTimeoutString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("lock_timeout", expected)) + return u +} + +func (u *UserResourceAssert) HasLogLevelString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("log_level", expected)) + return u +} + func (u *UserResourceAssert) HasLoginNameString(expected string) *UserResourceAssert { u.AddAssertion(assert.ValueSet("login_name", expected)) return u } +func (u *UserResourceAssert) HasMultiStatementCountString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("multi_statement_count", expected)) + return u +} + func (u *UserResourceAssert) HasMustChangePasswordString(expected string) *UserResourceAssert { u.AddAssertion(assert.ValueSet("must_change_password", expected)) return u @@ -102,11 +237,46 @@ func (u *UserResourceAssert) HasNameString(expected string) *UserResourceAssert return u } +func (u *UserResourceAssert) HasNetworkPolicyString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("network_policy", expected)) + return u +} + +func (u *UserResourceAssert) HasNoorderSequenceAsDefaultString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("noorder_sequence_as_default", expected)) + return u +} + +func (u *UserResourceAssert) HasOdbcTreatDecimalAsIntString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("odbc_treat_decimal_as_int", expected)) + return u +} + func (u *UserResourceAssert) HasPasswordString(expected string) *UserResourceAssert { u.AddAssertion(assert.ValueSet("password", expected)) return u } +func (u *UserResourceAssert) HasPreventUnloadToInternalStagesString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("prevent_unload_to_internal_stages", expected)) + return u +} + +func (u *UserResourceAssert) HasQueryTagString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("query_tag", expected)) + return u +} + +func (u *UserResourceAssert) HasQuotedIdentifiersIgnoreCaseString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("quoted_identifiers_ignore_case", expected)) + return u +} + +func (u *UserResourceAssert) HasRowsPerResultsetString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("rows_per_resultset", expected)) + return u +} + func (u *UserResourceAssert) HasRsaPublicKeyString(expected string) *UserResourceAssert { u.AddAssertion(assert.ValueSet("rsa_public_key", expected)) return u @@ -117,15 +287,205 @@ func (u *UserResourceAssert) HasRsaPublicKey2String(expected string) *UserResour return u } +func (u *UserResourceAssert) HasS3StageVpceDnsNameString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("s3_stage_vpce_dns_name", expected)) + return u +} + +func (u *UserResourceAssert) HasSearchPathString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("search_path", expected)) + return u +} + +func (u *UserResourceAssert) HasSimulatedDataSharingConsumerString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("simulated_data_sharing_consumer", expected)) + return u +} + +func (u *UserResourceAssert) HasStatementQueuedTimeoutInSecondsString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("statement_queued_timeout_in_seconds", expected)) + return u +} + +func (u *UserResourceAssert) HasStatementTimeoutInSecondsString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("statement_timeout_in_seconds", expected)) + return u +} + +func (u *UserResourceAssert) HasStrictJsonOutputString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("strict_json_output", expected)) + return u +} + +func (u *UserResourceAssert) HasTimeInputFormatString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("time_input_format", expected)) + return u +} + +func (u *UserResourceAssert) HasTimeOutputFormatString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("time_output_format", expected)) + return u +} + +func (u *UserResourceAssert) HasTimestampDayIsAlways24hString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("timestamp_day_is_always_24h", expected)) + return u +} + +func (u *UserResourceAssert) HasTimestampInputFormatString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("timestamp_input_format", expected)) + return u +} + +func (u *UserResourceAssert) HasTimestampLtzOutputFormatString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("timestamp_ltz_output_format", expected)) + return u +} + +func (u *UserResourceAssert) HasTimestampNtzOutputFormatString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("timestamp_ntz_output_format", expected)) + return u +} + +func (u *UserResourceAssert) HasTimestampOutputFormatString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("timestamp_output_format", expected)) + return u +} + +func (u *UserResourceAssert) HasTimestampTypeMappingString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("timestamp_type_mapping", expected)) + return u +} + +func (u *UserResourceAssert) HasTimestampTzOutputFormatString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("timestamp_tz_output_format", expected)) + return u +} + +func (u *UserResourceAssert) HasTimezoneString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("timezone", expected)) + return u +} + +func (u *UserResourceAssert) HasTraceLevelString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("trace_level", expected)) + return u +} + +func (u *UserResourceAssert) HasTransactionAbortOnErrorString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("transaction_abort_on_error", expected)) + return u +} + +func (u *UserResourceAssert) HasTransactionDefaultIsolationLevelString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("transaction_default_isolation_level", expected)) + return u +} + +func (u *UserResourceAssert) HasTwoDigitCenturyStartString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("two_digit_century_start", expected)) + return u +} + +func (u *UserResourceAssert) HasUnsupportedDdlActionString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("unsupported_ddl_action", expected)) + return u +} + +func (u *UserResourceAssert) HasUseCachedResultString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("use_cached_result", expected)) + return u +} + +func (u *UserResourceAssert) HasWeekOfYearPolicyString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("week_of_year_policy", expected)) + return u +} + +func (u *UserResourceAssert) HasWeekStartString(expected string) *UserResourceAssert { + u.AddAssertion(assert.ValueSet("week_start", expected)) + return u +} + //////////////////////////// // Attribute empty checks // //////////////////////////// +func (u *UserResourceAssert) HasNoAbortDetachedQuery() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("abort_detached_query")) + return u +} + +func (u *UserResourceAssert) HasNoAutocommit() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("autocommit")) + return u +} + +func (u *UserResourceAssert) HasNoBinaryInputFormat() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("binary_input_format")) + return u +} + +func (u *UserResourceAssert) HasNoBinaryOutputFormat() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("binary_output_format")) + return u +} + +func (u *UserResourceAssert) HasNoClientMemoryLimit() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("client_memory_limit")) + return u +} + +func (u *UserResourceAssert) HasNoClientMetadataRequestUseConnectionCtx() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("client_metadata_request_use_connection_ctx")) + return u +} + +func (u *UserResourceAssert) HasNoClientPrefetchThreads() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("client_prefetch_threads")) + return u +} + +func (u *UserResourceAssert) HasNoClientResultChunkSize() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("client_result_chunk_size")) + return u +} + +func (u *UserResourceAssert) HasNoClientResultColumnCaseInsensitive() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("client_result_column_case_insensitive")) + return u +} + +func (u *UserResourceAssert) HasNoClientSessionKeepAlive() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("client_session_keep_alive")) + return u +} + +func (u *UserResourceAssert) HasNoClientSessionKeepAliveHeartbeatFrequency() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("client_session_keep_alive_heartbeat_frequency")) + return u +} + +func (u *UserResourceAssert) HasNoClientTimestampTypeMapping() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("client_timestamp_type_mapping")) + return u +} + func (u *UserResourceAssert) HasNoComment() *UserResourceAssert { u.AddAssertion(assert.ValueNotSet("comment")) return u } +func (u *UserResourceAssert) HasNoDateInputFormat() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("date_input_format")) + return u +} + +func (u *UserResourceAssert) HasNoDateOutputFormat() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("date_output_format")) + return u +} + func (u *UserResourceAssert) HasNoDefaultNamespace() *UserResourceAssert { u.AddAssertion(assert.ValueNotSet("default_namespace")) return u @@ -161,26 +521,91 @@ func (u *UserResourceAssert) HasNoEmail() *UserResourceAssert { return u } +func (u *UserResourceAssert) HasNoEnableUnloadPhysicalTypeOptimization() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("enable_unload_physical_type_optimization")) + return u +} + +func (u *UserResourceAssert) HasNoEnableUnredactedQuerySyntaxError() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("enable_unredacted_query_syntax_error")) + return u +} + +func (u *UserResourceAssert) HasNoErrorOnNondeterministicMerge() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("error_on_nondeterministic_merge")) + return u +} + +func (u *UserResourceAssert) HasNoErrorOnNondeterministicUpdate() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("error_on_nondeterministic_update")) + return u +} + func (u *UserResourceAssert) HasNoFirstName() *UserResourceAssert { u.AddAssertion(assert.ValueNotSet("first_name")) return u } +func (u *UserResourceAssert) HasNoGeographyOutputFormat() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("geography_output_format")) + return u +} + +func (u *UserResourceAssert) HasNoGeometryOutputFormat() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("geometry_output_format")) + return u +} + func (u *UserResourceAssert) HasNoHasRsaPublicKey() *UserResourceAssert { u.AddAssertion(assert.ValueNotSet("has_rsa_public_key")) return u } +func (u *UserResourceAssert) HasNoJdbcTreatDecimalAsInt() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("jdbc_treat_decimal_as_int")) + return u +} + +func (u *UserResourceAssert) HasNoJdbcTreatTimestampNtzAsUtc() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("jdbc_treat_timestamp_ntz_as_utc")) + return u +} + +func (u *UserResourceAssert) HasNoJdbcUseSessionTimezone() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("jdbc_use_session_timezone")) + return u +} + +func (u *UserResourceAssert) HasNoJsonIndent() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("json_indent")) + return u +} + func (u *UserResourceAssert) HasNoLastName() *UserResourceAssert { u.AddAssertion(assert.ValueNotSet("last_name")) return u } +func (u *UserResourceAssert) HasNoLockTimeout() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("lock_timeout")) + return u +} + +func (u *UserResourceAssert) HasNoLogLevel() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("log_level")) + return u +} + func (u *UserResourceAssert) HasNoLoginName() *UserResourceAssert { u.AddAssertion(assert.ValueNotSet("login_name")) return u } +func (u *UserResourceAssert) HasNoMultiStatementCount() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("multi_statement_count")) + return u +} + func (u *UserResourceAssert) HasNoMustChangePassword() *UserResourceAssert { u.AddAssertion(assert.ValueNotSet("must_change_password")) return u @@ -191,11 +616,46 @@ func (u *UserResourceAssert) HasNoName() *UserResourceAssert { return u } +func (u *UserResourceAssert) HasNoNetworkPolicy() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("network_policy")) + return u +} + +func (u *UserResourceAssert) HasNoNoorderSequenceAsDefault() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("noorder_sequence_as_default")) + return u +} + +func (u *UserResourceAssert) HasNoOdbcTreatDecimalAsInt() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("odbc_treat_decimal_as_int")) + return u +} + func (u *UserResourceAssert) HasNoPassword() *UserResourceAssert { u.AddAssertion(assert.ValueNotSet("password")) return u } +func (u *UserResourceAssert) HasNoPreventUnloadToInternalStages() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("prevent_unload_to_internal_stages")) + return u +} + +func (u *UserResourceAssert) HasNoQueryTag() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("query_tag")) + return u +} + +func (u *UserResourceAssert) HasNoQuotedIdentifiersIgnoreCase() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("quoted_identifiers_ignore_case")) + return u +} + +func (u *UserResourceAssert) HasNoRowsPerResultset() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("rows_per_resultset")) + return u +} + func (u *UserResourceAssert) HasNoRsaPublicKey() *UserResourceAssert { u.AddAssertion(assert.ValueNotSet("rsa_public_key")) return u @@ -205,3 +665,123 @@ func (u *UserResourceAssert) HasNoRsaPublicKey2() *UserResourceAssert { u.AddAssertion(assert.ValueNotSet("rsa_public_key_2")) return u } + +func (u *UserResourceAssert) HasNoS3StageVpceDnsName() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("s3_stage_vpce_dns_name")) + return u +} + +func (u *UserResourceAssert) HasNoSearchPath() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("search_path")) + return u +} + +func (u *UserResourceAssert) HasNoSimulatedDataSharingConsumer() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("simulated_data_sharing_consumer")) + return u +} + +func (u *UserResourceAssert) HasNoStatementQueuedTimeoutInSeconds() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("statement_queued_timeout_in_seconds")) + return u +} + +func (u *UserResourceAssert) HasNoStatementTimeoutInSeconds() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("statement_timeout_in_seconds")) + return u +} + +func (u *UserResourceAssert) HasNoStrictJsonOutput() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("strict_json_output")) + return u +} + +func (u *UserResourceAssert) HasNoTimeInputFormat() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("time_input_format")) + return u +} + +func (u *UserResourceAssert) HasNoTimeOutputFormat() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("time_output_format")) + return u +} + +func (u *UserResourceAssert) HasNoTimestampDayIsAlways24h() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("timestamp_day_is_always_24h")) + return u +} + +func (u *UserResourceAssert) HasNoTimestampInputFormat() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("timestamp_input_format")) + return u +} + +func (u *UserResourceAssert) HasNoTimestampLtzOutputFormat() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("timestamp_ltz_output_format")) + return u +} + +func (u *UserResourceAssert) HasNoTimestampNtzOutputFormat() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("timestamp_ntz_output_format")) + return u +} + +func (u *UserResourceAssert) HasNoTimestampOutputFormat() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("timestamp_output_format")) + return u +} + +func (u *UserResourceAssert) HasNoTimestampTypeMapping() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("timestamp_type_mapping")) + return u +} + +func (u *UserResourceAssert) HasNoTimestampTzOutputFormat() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("timestamp_tz_output_format")) + return u +} + +func (u *UserResourceAssert) HasNoTimezone() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("timezone")) + return u +} + +func (u *UserResourceAssert) HasNoTraceLevel() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("trace_level")) + return u +} + +func (u *UserResourceAssert) HasNoTransactionAbortOnError() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("transaction_abort_on_error")) + return u +} + +func (u *UserResourceAssert) HasNoTransactionDefaultIsolationLevel() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("transaction_default_isolation_level")) + return u +} + +func (u *UserResourceAssert) HasNoTwoDigitCenturyStart() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("two_digit_century_start")) + return u +} + +func (u *UserResourceAssert) HasNoUnsupportedDdlAction() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("unsupported_ddl_action")) + return u +} + +func (u *UserResourceAssert) HasNoUseCachedResult() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("use_cached_result")) + return u +} + +func (u *UserResourceAssert) HasNoWeekOfYearPolicy() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("week_of_year_policy")) + return u +} + +func (u *UserResourceAssert) HasNoWeekStart() *UserResourceAssert { + u.AddAssertion(assert.ValueNotSet("week_start")) + return u +} diff --git a/pkg/acceptance/bettertestspoc/config/model/user_model_ext.go b/pkg/acceptance/bettertestspoc/config/model/user_model_ext.go new file mode 100644 index 0000000000..8888b90051 --- /dev/null +++ b/pkg/acceptance/bettertestspoc/config/model/user_model_ext.go @@ -0,0 +1,62 @@ +package model + +import ( + tfconfig "github.com/hashicorp/terraform-plugin-testing/config" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" +) + +func (u *UserModel) WithBinaryInputFormatEnum(binaryInputFormat sdk.BinaryInputFormat) *UserModel { + u.BinaryInputFormat = tfconfig.StringVariable(string(binaryInputFormat)) + return u +} + +func (u *UserModel) WithBinaryOutputFormatEnum(binaryOutputFormat sdk.BinaryOutputFormat) *UserModel { + u.BinaryOutputFormat = tfconfig.StringVariable(string(binaryOutputFormat)) + return u +} + +func (u *UserModel) WithClientTimestampTypeMappingEnum(clientTimestampTypeMapping sdk.ClientTimestampTypeMapping) *UserModel { + u.ClientTimestampTypeMapping = tfconfig.StringVariable(string(clientTimestampTypeMapping)) + return u +} + +func (u *UserModel) WithGeographyOutputFormatEnum(geographyOutputFormat sdk.GeographyOutputFormat) *UserModel { + u.GeographyOutputFormat = tfconfig.StringVariable(string(geographyOutputFormat)) + return u +} + +func (u *UserModel) WithGeometryOutputFormatEnum(geometryOutputFormat sdk.GeometryOutputFormat) *UserModel { + u.GeometryOutputFormat = tfconfig.StringVariable(string(geometryOutputFormat)) + return u +} + +func (u *UserModel) WithLogLevelEnum(logLevel sdk.LogLevel) *UserModel { + u.LogLevel = tfconfig.StringVariable(string(logLevel)) + return u +} + +func (u *UserModel) WithTimestampTypeMappingEnum(timestampTypeMapping sdk.TimestampTypeMapping) *UserModel { + u.TimestampTypeMapping = tfconfig.StringVariable(string(timestampTypeMapping)) + return u +} + +func (u *UserModel) WithTraceLevelEnum(traceLevel sdk.TraceLevel) *UserModel { + u.TraceLevel = tfconfig.StringVariable(string(traceLevel)) + return u +} + +func (u *UserModel) WithTransactionDefaultIsolationLevelEnum(transactionDefaultIsolationLevel sdk.TransactionDefaultIsolationLevel) *UserModel { + u.TransactionDefaultIsolationLevel = tfconfig.StringVariable(string(transactionDefaultIsolationLevel)) + return u +} + +func (u *UserModel) WithUnsupportedDdlActionEnum(unsupportedDdlAction sdk.UnsupportedDDLAction) *UserModel { + u.UnsupportedDdlAction = tfconfig.StringVariable(string(unsupportedDdlAction)) + return u +} + +func (u *UserModel) WithNetworkPolicyId(networkPolicy sdk.AccountObjectIdentifier) *UserModel { + u.NetworkPolicy = tfconfig.StringVariable(networkPolicy.Name()) + return u +} diff --git a/pkg/acceptance/bettertestspoc/config/model/user_model_gen.go b/pkg/acceptance/bettertestspoc/config/model/user_model_gen.go index 230ca3a77c..8002163a6b 100644 --- a/pkg/acceptance/bettertestspoc/config/model/user_model_gen.go +++ b/pkg/acceptance/bettertestspoc/config/model/user_model_gen.go @@ -10,23 +10,81 @@ import ( ) type UserModel struct { - Comment tfconfig.Variable `json:"comment,omitempty"` - DefaultNamespace tfconfig.Variable `json:"default_namespace,omitempty"` - DefaultRole tfconfig.Variable `json:"default_role,omitempty"` - DefaultSecondaryRoles tfconfig.Variable `json:"default_secondary_roles,omitempty"` - DefaultWarehouse tfconfig.Variable `json:"default_warehouse,omitempty"` - Disabled tfconfig.Variable `json:"disabled,omitempty"` - DisplayName tfconfig.Variable `json:"display_name,omitempty"` - Email tfconfig.Variable `json:"email,omitempty"` - FirstName tfconfig.Variable `json:"first_name,omitempty"` - HasRsaPublicKey tfconfig.Variable `json:"has_rsa_public_key,omitempty"` - LastName tfconfig.Variable `json:"last_name,omitempty"` - LoginName tfconfig.Variable `json:"login_name,omitempty"` - MustChangePassword tfconfig.Variable `json:"must_change_password,omitempty"` - Name tfconfig.Variable `json:"name,omitempty"` - Password tfconfig.Variable `json:"password,omitempty"` - RsaPublicKey tfconfig.Variable `json:"rsa_public_key,omitempty"` - RsaPublicKey2 tfconfig.Variable `json:"rsa_public_key_2,omitempty"` + AbortDetachedQuery tfconfig.Variable `json:"abort_detached_query,omitempty"` + Autocommit tfconfig.Variable `json:"autocommit,omitempty"` + BinaryInputFormat tfconfig.Variable `json:"binary_input_format,omitempty"` + BinaryOutputFormat tfconfig.Variable `json:"binary_output_format,omitempty"` + ClientMemoryLimit tfconfig.Variable `json:"client_memory_limit,omitempty"` + ClientMetadataRequestUseConnectionCtx tfconfig.Variable `json:"client_metadata_request_use_connection_ctx,omitempty"` + ClientPrefetchThreads tfconfig.Variable `json:"client_prefetch_threads,omitempty"` + ClientResultChunkSize tfconfig.Variable `json:"client_result_chunk_size,omitempty"` + ClientResultColumnCaseInsensitive tfconfig.Variable `json:"client_result_column_case_insensitive,omitempty"` + ClientSessionKeepAlive tfconfig.Variable `json:"client_session_keep_alive,omitempty"` + ClientSessionKeepAliveHeartbeatFrequency tfconfig.Variable `json:"client_session_keep_alive_heartbeat_frequency,omitempty"` + ClientTimestampTypeMapping tfconfig.Variable `json:"client_timestamp_type_mapping,omitempty"` + Comment tfconfig.Variable `json:"comment,omitempty"` + DateInputFormat tfconfig.Variable `json:"date_input_format,omitempty"` + DateOutputFormat tfconfig.Variable `json:"date_output_format,omitempty"` + DefaultNamespace tfconfig.Variable `json:"default_namespace,omitempty"` + DefaultRole tfconfig.Variable `json:"default_role,omitempty"` + DefaultSecondaryRoles tfconfig.Variable `json:"default_secondary_roles,omitempty"` + DefaultWarehouse tfconfig.Variable `json:"default_warehouse,omitempty"` + Disabled tfconfig.Variable `json:"disabled,omitempty"` + DisplayName tfconfig.Variable `json:"display_name,omitempty"` + Email tfconfig.Variable `json:"email,omitempty"` + EnableUnloadPhysicalTypeOptimization tfconfig.Variable `json:"enable_unload_physical_type_optimization,omitempty"` + EnableUnredactedQuerySyntaxError tfconfig.Variable `json:"enable_unredacted_query_syntax_error,omitempty"` + ErrorOnNondeterministicMerge tfconfig.Variable `json:"error_on_nondeterministic_merge,omitempty"` + ErrorOnNondeterministicUpdate tfconfig.Variable `json:"error_on_nondeterministic_update,omitempty"` + FirstName tfconfig.Variable `json:"first_name,omitempty"` + GeographyOutputFormat tfconfig.Variable `json:"geography_output_format,omitempty"` + GeometryOutputFormat tfconfig.Variable `json:"geometry_output_format,omitempty"` + HasRsaPublicKey tfconfig.Variable `json:"has_rsa_public_key,omitempty"` + JdbcTreatDecimalAsInt tfconfig.Variable `json:"jdbc_treat_decimal_as_int,omitempty"` + JdbcTreatTimestampNtzAsUtc tfconfig.Variable `json:"jdbc_treat_timestamp_ntz_as_utc,omitempty"` + JdbcUseSessionTimezone tfconfig.Variable `json:"jdbc_use_session_timezone,omitempty"` + JsonIndent tfconfig.Variable `json:"json_indent,omitempty"` + LastName tfconfig.Variable `json:"last_name,omitempty"` + LockTimeout tfconfig.Variable `json:"lock_timeout,omitempty"` + LogLevel tfconfig.Variable `json:"log_level,omitempty"` + LoginName tfconfig.Variable `json:"login_name,omitempty"` + MultiStatementCount tfconfig.Variable `json:"multi_statement_count,omitempty"` + MustChangePassword tfconfig.Variable `json:"must_change_password,omitempty"` + Name tfconfig.Variable `json:"name,omitempty"` + NetworkPolicy tfconfig.Variable `json:"network_policy,omitempty"` + NoorderSequenceAsDefault tfconfig.Variable `json:"noorder_sequence_as_default,omitempty"` + OdbcTreatDecimalAsInt tfconfig.Variable `json:"odbc_treat_decimal_as_int,omitempty"` + Password tfconfig.Variable `json:"password,omitempty"` + PreventUnloadToInternalStages tfconfig.Variable `json:"prevent_unload_to_internal_stages,omitempty"` + QueryTag tfconfig.Variable `json:"query_tag,omitempty"` + QuotedIdentifiersIgnoreCase tfconfig.Variable `json:"quoted_identifiers_ignore_case,omitempty"` + RowsPerResultset tfconfig.Variable `json:"rows_per_resultset,omitempty"` + RsaPublicKey tfconfig.Variable `json:"rsa_public_key,omitempty"` + RsaPublicKey2 tfconfig.Variable `json:"rsa_public_key_2,omitempty"` + S3StageVpceDnsName tfconfig.Variable `json:"s3_stage_vpce_dns_name,omitempty"` + SearchPath tfconfig.Variable `json:"search_path,omitempty"` + SimulatedDataSharingConsumer tfconfig.Variable `json:"simulated_data_sharing_consumer,omitempty"` + StatementQueuedTimeoutInSeconds tfconfig.Variable `json:"statement_queued_timeout_in_seconds,omitempty"` + StatementTimeoutInSeconds tfconfig.Variable `json:"statement_timeout_in_seconds,omitempty"` + StrictJsonOutput tfconfig.Variable `json:"strict_json_output,omitempty"` + TimeInputFormat tfconfig.Variable `json:"time_input_format,omitempty"` + TimeOutputFormat tfconfig.Variable `json:"time_output_format,omitempty"` + TimestampDayIsAlways24h tfconfig.Variable `json:"timestamp_day_is_always_24h,omitempty"` + TimestampInputFormat tfconfig.Variable `json:"timestamp_input_format,omitempty"` + TimestampLtzOutputFormat tfconfig.Variable `json:"timestamp_ltz_output_format,omitempty"` + TimestampNtzOutputFormat tfconfig.Variable `json:"timestamp_ntz_output_format,omitempty"` + TimestampOutputFormat tfconfig.Variable `json:"timestamp_output_format,omitempty"` + TimestampTypeMapping tfconfig.Variable `json:"timestamp_type_mapping,omitempty"` + TimestampTzOutputFormat tfconfig.Variable `json:"timestamp_tz_output_format,omitempty"` + Timezone tfconfig.Variable `json:"timezone,omitempty"` + TraceLevel tfconfig.Variable `json:"trace_level,omitempty"` + TransactionAbortOnError tfconfig.Variable `json:"transaction_abort_on_error,omitempty"` + TransactionDefaultIsolationLevel tfconfig.Variable `json:"transaction_default_isolation_level,omitempty"` + TwoDigitCenturyStart tfconfig.Variable `json:"two_digit_century_start,omitempty"` + UnsupportedDdlAction tfconfig.Variable `json:"unsupported_ddl_action,omitempty"` + UseCachedResult tfconfig.Variable `json:"use_cached_result,omitempty"` + WeekOfYearPolicy tfconfig.Variable `json:"week_of_year_policy,omitempty"` + WeekStart tfconfig.Variable `json:"week_start,omitempty"` *config.ResourceModelMeta } @@ -56,11 +114,81 @@ func UserWithDefaultMeta( // below all the proper values // ///////////////////////////////// +func (u *UserModel) WithAbortDetachedQuery(abortDetachedQuery bool) *UserModel { + u.AbortDetachedQuery = tfconfig.BoolVariable(abortDetachedQuery) + return u +} + +func (u *UserModel) WithAutocommit(autocommit bool) *UserModel { + u.Autocommit = tfconfig.BoolVariable(autocommit) + return u +} + +func (u *UserModel) WithBinaryInputFormat(binaryInputFormat string) *UserModel { + u.BinaryInputFormat = tfconfig.StringVariable(binaryInputFormat) + return u +} + +func (u *UserModel) WithBinaryOutputFormat(binaryOutputFormat string) *UserModel { + u.BinaryOutputFormat = tfconfig.StringVariable(binaryOutputFormat) + return u +} + +func (u *UserModel) WithClientMemoryLimit(clientMemoryLimit int) *UserModel { + u.ClientMemoryLimit = tfconfig.IntegerVariable(clientMemoryLimit) + return u +} + +func (u *UserModel) WithClientMetadataRequestUseConnectionCtx(clientMetadataRequestUseConnectionCtx bool) *UserModel { + u.ClientMetadataRequestUseConnectionCtx = tfconfig.BoolVariable(clientMetadataRequestUseConnectionCtx) + return u +} + +func (u *UserModel) WithClientPrefetchThreads(clientPrefetchThreads int) *UserModel { + u.ClientPrefetchThreads = tfconfig.IntegerVariable(clientPrefetchThreads) + return u +} + +func (u *UserModel) WithClientResultChunkSize(clientResultChunkSize int) *UserModel { + u.ClientResultChunkSize = tfconfig.IntegerVariable(clientResultChunkSize) + return u +} + +func (u *UserModel) WithClientResultColumnCaseInsensitive(clientResultColumnCaseInsensitive bool) *UserModel { + u.ClientResultColumnCaseInsensitive = tfconfig.BoolVariable(clientResultColumnCaseInsensitive) + return u +} + +func (u *UserModel) WithClientSessionKeepAlive(clientSessionKeepAlive bool) *UserModel { + u.ClientSessionKeepAlive = tfconfig.BoolVariable(clientSessionKeepAlive) + return u +} + +func (u *UserModel) WithClientSessionKeepAliveHeartbeatFrequency(clientSessionKeepAliveHeartbeatFrequency int) *UserModel { + u.ClientSessionKeepAliveHeartbeatFrequency = tfconfig.IntegerVariable(clientSessionKeepAliveHeartbeatFrequency) + return u +} + +func (u *UserModel) WithClientTimestampTypeMapping(clientTimestampTypeMapping string) *UserModel { + u.ClientTimestampTypeMapping = tfconfig.StringVariable(clientTimestampTypeMapping) + return u +} + func (u *UserModel) WithComment(comment string) *UserModel { u.Comment = tfconfig.StringVariable(comment) return u } +func (u *UserModel) WithDateInputFormat(dateInputFormat string) *UserModel { + u.DateInputFormat = tfconfig.StringVariable(dateInputFormat) + return u +} + +func (u *UserModel) WithDateOutputFormat(dateOutputFormat string) *UserModel { + u.DateOutputFormat = tfconfig.StringVariable(dateOutputFormat) + return u +} + func (u *UserModel) WithDefaultNamespace(defaultNamespace string) *UserModel { u.DefaultNamespace = tfconfig.StringVariable(defaultNamespace) return u @@ -93,26 +221,91 @@ func (u *UserModel) WithEmail(email string) *UserModel { return u } +func (u *UserModel) WithEnableUnloadPhysicalTypeOptimization(enableUnloadPhysicalTypeOptimization bool) *UserModel { + u.EnableUnloadPhysicalTypeOptimization = tfconfig.BoolVariable(enableUnloadPhysicalTypeOptimization) + return u +} + +func (u *UserModel) WithEnableUnredactedQuerySyntaxError(enableUnredactedQuerySyntaxError bool) *UserModel { + u.EnableUnredactedQuerySyntaxError = tfconfig.BoolVariable(enableUnredactedQuerySyntaxError) + return u +} + +func (u *UserModel) WithErrorOnNondeterministicMerge(errorOnNondeterministicMerge bool) *UserModel { + u.ErrorOnNondeterministicMerge = tfconfig.BoolVariable(errorOnNondeterministicMerge) + return u +} + +func (u *UserModel) WithErrorOnNondeterministicUpdate(errorOnNondeterministicUpdate bool) *UserModel { + u.ErrorOnNondeterministicUpdate = tfconfig.BoolVariable(errorOnNondeterministicUpdate) + return u +} + func (u *UserModel) WithFirstName(firstName string) *UserModel { u.FirstName = tfconfig.StringVariable(firstName) return u } +func (u *UserModel) WithGeographyOutputFormat(geographyOutputFormat string) *UserModel { + u.GeographyOutputFormat = tfconfig.StringVariable(geographyOutputFormat) + return u +} + +func (u *UserModel) WithGeometryOutputFormat(geometryOutputFormat string) *UserModel { + u.GeometryOutputFormat = tfconfig.StringVariable(geometryOutputFormat) + return u +} + func (u *UserModel) WithHasRsaPublicKey(hasRsaPublicKey bool) *UserModel { u.HasRsaPublicKey = tfconfig.BoolVariable(hasRsaPublicKey) return u } +func (u *UserModel) WithJdbcTreatDecimalAsInt(jdbcTreatDecimalAsInt bool) *UserModel { + u.JdbcTreatDecimalAsInt = tfconfig.BoolVariable(jdbcTreatDecimalAsInt) + return u +} + +func (u *UserModel) WithJdbcTreatTimestampNtzAsUtc(jdbcTreatTimestampNtzAsUtc bool) *UserModel { + u.JdbcTreatTimestampNtzAsUtc = tfconfig.BoolVariable(jdbcTreatTimestampNtzAsUtc) + return u +} + +func (u *UserModel) WithJdbcUseSessionTimezone(jdbcUseSessionTimezone bool) *UserModel { + u.JdbcUseSessionTimezone = tfconfig.BoolVariable(jdbcUseSessionTimezone) + return u +} + +func (u *UserModel) WithJsonIndent(jsonIndent int) *UserModel { + u.JsonIndent = tfconfig.IntegerVariable(jsonIndent) + return u +} + func (u *UserModel) WithLastName(lastName string) *UserModel { u.LastName = tfconfig.StringVariable(lastName) return u } +func (u *UserModel) WithLockTimeout(lockTimeout int) *UserModel { + u.LockTimeout = tfconfig.IntegerVariable(lockTimeout) + return u +} + +func (u *UserModel) WithLogLevel(logLevel string) *UserModel { + u.LogLevel = tfconfig.StringVariable(logLevel) + return u +} + func (u *UserModel) WithLoginName(loginName string) *UserModel { u.LoginName = tfconfig.StringVariable(loginName) return u } +func (u *UserModel) WithMultiStatementCount(multiStatementCount int) *UserModel { + u.MultiStatementCount = tfconfig.IntegerVariable(multiStatementCount) + return u +} + func (u *UserModel) WithMustChangePassword(mustChangePassword bool) *UserModel { u.MustChangePassword = tfconfig.BoolVariable(mustChangePassword) return u @@ -123,11 +316,46 @@ func (u *UserModel) WithName(name string) *UserModel { return u } +func (u *UserModel) WithNetworkPolicy(networkPolicy string) *UserModel { + u.NetworkPolicy = tfconfig.StringVariable(networkPolicy) + return u +} + +func (u *UserModel) WithNoorderSequenceAsDefault(noorderSequenceAsDefault bool) *UserModel { + u.NoorderSequenceAsDefault = tfconfig.BoolVariable(noorderSequenceAsDefault) + return u +} + +func (u *UserModel) WithOdbcTreatDecimalAsInt(odbcTreatDecimalAsInt bool) *UserModel { + u.OdbcTreatDecimalAsInt = tfconfig.BoolVariable(odbcTreatDecimalAsInt) + return u +} + func (u *UserModel) WithPassword(password string) *UserModel { u.Password = tfconfig.StringVariable(password) return u } +func (u *UserModel) WithPreventUnloadToInternalStages(preventUnloadToInternalStages bool) *UserModel { + u.PreventUnloadToInternalStages = tfconfig.BoolVariable(preventUnloadToInternalStages) + return u +} + +func (u *UserModel) WithQueryTag(queryTag string) *UserModel { + u.QueryTag = tfconfig.StringVariable(queryTag) + return u +} + +func (u *UserModel) WithQuotedIdentifiersIgnoreCase(quotedIdentifiersIgnoreCase bool) *UserModel { + u.QuotedIdentifiersIgnoreCase = tfconfig.BoolVariable(quotedIdentifiersIgnoreCase) + return u +} + +func (u *UserModel) WithRowsPerResultset(rowsPerResultset int) *UserModel { + u.RowsPerResultset = tfconfig.IntegerVariable(rowsPerResultset) + return u +} + func (u *UserModel) WithRsaPublicKey(rsaPublicKey string) *UserModel { u.RsaPublicKey = tfconfig.StringVariable(rsaPublicKey) return u @@ -138,15 +366,205 @@ func (u *UserModel) WithRsaPublicKey2(rsaPublicKey2 string) *UserModel { return u } +func (u *UserModel) WithS3StageVpceDnsName(s3StageVpceDnsName string) *UserModel { + u.S3StageVpceDnsName = tfconfig.StringVariable(s3StageVpceDnsName) + return u +} + +func (u *UserModel) WithSearchPath(searchPath string) *UserModel { + u.SearchPath = tfconfig.StringVariable(searchPath) + return u +} + +func (u *UserModel) WithSimulatedDataSharingConsumer(simulatedDataSharingConsumer string) *UserModel { + u.SimulatedDataSharingConsumer = tfconfig.StringVariable(simulatedDataSharingConsumer) + return u +} + +func (u *UserModel) WithStatementQueuedTimeoutInSeconds(statementQueuedTimeoutInSeconds int) *UserModel { + u.StatementQueuedTimeoutInSeconds = tfconfig.IntegerVariable(statementQueuedTimeoutInSeconds) + return u +} + +func (u *UserModel) WithStatementTimeoutInSeconds(statementTimeoutInSeconds int) *UserModel { + u.StatementTimeoutInSeconds = tfconfig.IntegerVariable(statementTimeoutInSeconds) + return u +} + +func (u *UserModel) WithStrictJsonOutput(strictJsonOutput bool) *UserModel { + u.StrictJsonOutput = tfconfig.BoolVariable(strictJsonOutput) + return u +} + +func (u *UserModel) WithTimeInputFormat(timeInputFormat string) *UserModel { + u.TimeInputFormat = tfconfig.StringVariable(timeInputFormat) + return u +} + +func (u *UserModel) WithTimeOutputFormat(timeOutputFormat string) *UserModel { + u.TimeOutputFormat = tfconfig.StringVariable(timeOutputFormat) + return u +} + +func (u *UserModel) WithTimestampDayIsAlways24h(timestampDayIsAlways24h bool) *UserModel { + u.TimestampDayIsAlways24h = tfconfig.BoolVariable(timestampDayIsAlways24h) + return u +} + +func (u *UserModel) WithTimestampInputFormat(timestampInputFormat string) *UserModel { + u.TimestampInputFormat = tfconfig.StringVariable(timestampInputFormat) + return u +} + +func (u *UserModel) WithTimestampLtzOutputFormat(timestampLtzOutputFormat string) *UserModel { + u.TimestampLtzOutputFormat = tfconfig.StringVariable(timestampLtzOutputFormat) + return u +} + +func (u *UserModel) WithTimestampNtzOutputFormat(timestampNtzOutputFormat string) *UserModel { + u.TimestampNtzOutputFormat = tfconfig.StringVariable(timestampNtzOutputFormat) + return u +} + +func (u *UserModel) WithTimestampOutputFormat(timestampOutputFormat string) *UserModel { + u.TimestampOutputFormat = tfconfig.StringVariable(timestampOutputFormat) + return u +} + +func (u *UserModel) WithTimestampTypeMapping(timestampTypeMapping string) *UserModel { + u.TimestampTypeMapping = tfconfig.StringVariable(timestampTypeMapping) + return u +} + +func (u *UserModel) WithTimestampTzOutputFormat(timestampTzOutputFormat string) *UserModel { + u.TimestampTzOutputFormat = tfconfig.StringVariable(timestampTzOutputFormat) + return u +} + +func (u *UserModel) WithTimezone(timezone string) *UserModel { + u.Timezone = tfconfig.StringVariable(timezone) + return u +} + +func (u *UserModel) WithTraceLevel(traceLevel string) *UserModel { + u.TraceLevel = tfconfig.StringVariable(traceLevel) + return u +} + +func (u *UserModel) WithTransactionAbortOnError(transactionAbortOnError bool) *UserModel { + u.TransactionAbortOnError = tfconfig.BoolVariable(transactionAbortOnError) + return u +} + +func (u *UserModel) WithTransactionDefaultIsolationLevel(transactionDefaultIsolationLevel string) *UserModel { + u.TransactionDefaultIsolationLevel = tfconfig.StringVariable(transactionDefaultIsolationLevel) + return u +} + +func (u *UserModel) WithTwoDigitCenturyStart(twoDigitCenturyStart int) *UserModel { + u.TwoDigitCenturyStart = tfconfig.IntegerVariable(twoDigitCenturyStart) + return u +} + +func (u *UserModel) WithUnsupportedDdlAction(unsupportedDdlAction string) *UserModel { + u.UnsupportedDdlAction = tfconfig.StringVariable(unsupportedDdlAction) + return u +} + +func (u *UserModel) WithUseCachedResult(useCachedResult bool) *UserModel { + u.UseCachedResult = tfconfig.BoolVariable(useCachedResult) + return u +} + +func (u *UserModel) WithWeekOfYearPolicy(weekOfYearPolicy int) *UserModel { + u.WeekOfYearPolicy = tfconfig.IntegerVariable(weekOfYearPolicy) + return u +} + +func (u *UserModel) WithWeekStart(weekStart int) *UserModel { + u.WeekStart = tfconfig.IntegerVariable(weekStart) + return u +} + ////////////////////////////////////////// // below it's possible to set any value // ////////////////////////////////////////// +func (u *UserModel) WithAbortDetachedQueryValue(value tfconfig.Variable) *UserModel { + u.AbortDetachedQuery = value + return u +} + +func (u *UserModel) WithAutocommitValue(value tfconfig.Variable) *UserModel { + u.Autocommit = value + return u +} + +func (u *UserModel) WithBinaryInputFormatValue(value tfconfig.Variable) *UserModel { + u.BinaryInputFormat = value + return u +} + +func (u *UserModel) WithBinaryOutputFormatValue(value tfconfig.Variable) *UserModel { + u.BinaryOutputFormat = value + return u +} + +func (u *UserModel) WithClientMemoryLimitValue(value tfconfig.Variable) *UserModel { + u.ClientMemoryLimit = value + return u +} + +func (u *UserModel) WithClientMetadataRequestUseConnectionCtxValue(value tfconfig.Variable) *UserModel { + u.ClientMetadataRequestUseConnectionCtx = value + return u +} + +func (u *UserModel) WithClientPrefetchThreadsValue(value tfconfig.Variable) *UserModel { + u.ClientPrefetchThreads = value + return u +} + +func (u *UserModel) WithClientResultChunkSizeValue(value tfconfig.Variable) *UserModel { + u.ClientResultChunkSize = value + return u +} + +func (u *UserModel) WithClientResultColumnCaseInsensitiveValue(value tfconfig.Variable) *UserModel { + u.ClientResultColumnCaseInsensitive = value + return u +} + +func (u *UserModel) WithClientSessionKeepAliveValue(value tfconfig.Variable) *UserModel { + u.ClientSessionKeepAlive = value + return u +} + +func (u *UserModel) WithClientSessionKeepAliveHeartbeatFrequencyValue(value tfconfig.Variable) *UserModel { + u.ClientSessionKeepAliveHeartbeatFrequency = value + return u +} + +func (u *UserModel) WithClientTimestampTypeMappingValue(value tfconfig.Variable) *UserModel { + u.ClientTimestampTypeMapping = value + return u +} + func (u *UserModel) WithCommentValue(value tfconfig.Variable) *UserModel { u.Comment = value return u } +func (u *UserModel) WithDateInputFormatValue(value tfconfig.Variable) *UserModel { + u.DateInputFormat = value + return u +} + +func (u *UserModel) WithDateOutputFormatValue(value tfconfig.Variable) *UserModel { + u.DateOutputFormat = value + return u +} + func (u *UserModel) WithDefaultNamespaceValue(value tfconfig.Variable) *UserModel { u.DefaultNamespace = value return u @@ -182,26 +600,91 @@ func (u *UserModel) WithEmailValue(value tfconfig.Variable) *UserModel { return u } +func (u *UserModel) WithEnableUnloadPhysicalTypeOptimizationValue(value tfconfig.Variable) *UserModel { + u.EnableUnloadPhysicalTypeOptimization = value + return u +} + +func (u *UserModel) WithEnableUnredactedQuerySyntaxErrorValue(value tfconfig.Variable) *UserModel { + u.EnableUnredactedQuerySyntaxError = value + return u +} + +func (u *UserModel) WithErrorOnNondeterministicMergeValue(value tfconfig.Variable) *UserModel { + u.ErrorOnNondeterministicMerge = value + return u +} + +func (u *UserModel) WithErrorOnNondeterministicUpdateValue(value tfconfig.Variable) *UserModel { + u.ErrorOnNondeterministicUpdate = value + return u +} + func (u *UserModel) WithFirstNameValue(value tfconfig.Variable) *UserModel { u.FirstName = value return u } +func (u *UserModel) WithGeographyOutputFormatValue(value tfconfig.Variable) *UserModel { + u.GeographyOutputFormat = value + return u +} + +func (u *UserModel) WithGeometryOutputFormatValue(value tfconfig.Variable) *UserModel { + u.GeometryOutputFormat = value + return u +} + func (u *UserModel) WithHasRsaPublicKeyValue(value tfconfig.Variable) *UserModel { u.HasRsaPublicKey = value return u } +func (u *UserModel) WithJdbcTreatDecimalAsIntValue(value tfconfig.Variable) *UserModel { + u.JdbcTreatDecimalAsInt = value + return u +} + +func (u *UserModel) WithJdbcTreatTimestampNtzAsUtcValue(value tfconfig.Variable) *UserModel { + u.JdbcTreatTimestampNtzAsUtc = value + return u +} + +func (u *UserModel) WithJdbcUseSessionTimezoneValue(value tfconfig.Variable) *UserModel { + u.JdbcUseSessionTimezone = value + return u +} + +func (u *UserModel) WithJsonIndentValue(value tfconfig.Variable) *UserModel { + u.JsonIndent = value + return u +} + func (u *UserModel) WithLastNameValue(value tfconfig.Variable) *UserModel { u.LastName = value return u } +func (u *UserModel) WithLockTimeoutValue(value tfconfig.Variable) *UserModel { + u.LockTimeout = value + return u +} + +func (u *UserModel) WithLogLevelValue(value tfconfig.Variable) *UserModel { + u.LogLevel = value + return u +} + func (u *UserModel) WithLoginNameValue(value tfconfig.Variable) *UserModel { u.LoginName = value return u } +func (u *UserModel) WithMultiStatementCountValue(value tfconfig.Variable) *UserModel { + u.MultiStatementCount = value + return u +} + func (u *UserModel) WithMustChangePasswordValue(value tfconfig.Variable) *UserModel { u.MustChangePassword = value return u @@ -212,11 +695,46 @@ func (u *UserModel) WithNameValue(value tfconfig.Variable) *UserModel { return u } +func (u *UserModel) WithNetworkPolicyValue(value tfconfig.Variable) *UserModel { + u.NetworkPolicy = value + return u +} + +func (u *UserModel) WithNoorderSequenceAsDefaultValue(value tfconfig.Variable) *UserModel { + u.NoorderSequenceAsDefault = value + return u +} + +func (u *UserModel) WithOdbcTreatDecimalAsIntValue(value tfconfig.Variable) *UserModel { + u.OdbcTreatDecimalAsInt = value + return u +} + func (u *UserModel) WithPasswordValue(value tfconfig.Variable) *UserModel { u.Password = value return u } +func (u *UserModel) WithPreventUnloadToInternalStagesValue(value tfconfig.Variable) *UserModel { + u.PreventUnloadToInternalStages = value + return u +} + +func (u *UserModel) WithQueryTagValue(value tfconfig.Variable) *UserModel { + u.QueryTag = value + return u +} + +func (u *UserModel) WithQuotedIdentifiersIgnoreCaseValue(value tfconfig.Variable) *UserModel { + u.QuotedIdentifiersIgnoreCase = value + return u +} + +func (u *UserModel) WithRowsPerResultsetValue(value tfconfig.Variable) *UserModel { + u.RowsPerResultset = value + return u +} + func (u *UserModel) WithRsaPublicKeyValue(value tfconfig.Variable) *UserModel { u.RsaPublicKey = value return u @@ -226,3 +744,123 @@ func (u *UserModel) WithRsaPublicKey2Value(value tfconfig.Variable) *UserModel { u.RsaPublicKey2 = value return u } + +func (u *UserModel) WithS3StageVpceDnsNameValue(value tfconfig.Variable) *UserModel { + u.S3StageVpceDnsName = value + return u +} + +func (u *UserModel) WithSearchPathValue(value tfconfig.Variable) *UserModel { + u.SearchPath = value + return u +} + +func (u *UserModel) WithSimulatedDataSharingConsumerValue(value tfconfig.Variable) *UserModel { + u.SimulatedDataSharingConsumer = value + return u +} + +func (u *UserModel) WithStatementQueuedTimeoutInSecondsValue(value tfconfig.Variable) *UserModel { + u.StatementQueuedTimeoutInSeconds = value + return u +} + +func (u *UserModel) WithStatementTimeoutInSecondsValue(value tfconfig.Variable) *UserModel { + u.StatementTimeoutInSeconds = value + return u +} + +func (u *UserModel) WithStrictJsonOutputValue(value tfconfig.Variable) *UserModel { + u.StrictJsonOutput = value + return u +} + +func (u *UserModel) WithTimeInputFormatValue(value tfconfig.Variable) *UserModel { + u.TimeInputFormat = value + return u +} + +func (u *UserModel) WithTimeOutputFormatValue(value tfconfig.Variable) *UserModel { + u.TimeOutputFormat = value + return u +} + +func (u *UserModel) WithTimestampDayIsAlways24hValue(value tfconfig.Variable) *UserModel { + u.TimestampDayIsAlways24h = value + return u +} + +func (u *UserModel) WithTimestampInputFormatValue(value tfconfig.Variable) *UserModel { + u.TimestampInputFormat = value + return u +} + +func (u *UserModel) WithTimestampLtzOutputFormatValue(value tfconfig.Variable) *UserModel { + u.TimestampLtzOutputFormat = value + return u +} + +func (u *UserModel) WithTimestampNtzOutputFormatValue(value tfconfig.Variable) *UserModel { + u.TimestampNtzOutputFormat = value + return u +} + +func (u *UserModel) WithTimestampOutputFormatValue(value tfconfig.Variable) *UserModel { + u.TimestampOutputFormat = value + return u +} + +func (u *UserModel) WithTimestampTypeMappingValue(value tfconfig.Variable) *UserModel { + u.TimestampTypeMapping = value + return u +} + +func (u *UserModel) WithTimestampTzOutputFormatValue(value tfconfig.Variable) *UserModel { + u.TimestampTzOutputFormat = value + return u +} + +func (u *UserModel) WithTimezoneValue(value tfconfig.Variable) *UserModel { + u.Timezone = value + return u +} + +func (u *UserModel) WithTraceLevelValue(value tfconfig.Variable) *UserModel { + u.TraceLevel = value + return u +} + +func (u *UserModel) WithTransactionAbortOnErrorValue(value tfconfig.Variable) *UserModel { + u.TransactionAbortOnError = value + return u +} + +func (u *UserModel) WithTransactionDefaultIsolationLevelValue(value tfconfig.Variable) *UserModel { + u.TransactionDefaultIsolationLevel = value + return u +} + +func (u *UserModel) WithTwoDigitCenturyStartValue(value tfconfig.Variable) *UserModel { + u.TwoDigitCenturyStart = value + return u +} + +func (u *UserModel) WithUnsupportedDdlActionValue(value tfconfig.Variable) *UserModel { + u.UnsupportedDdlAction = value + return u +} + +func (u *UserModel) WithUseCachedResultValue(value tfconfig.Variable) *UserModel { + u.UseCachedResult = value + return u +} + +func (u *UserModel) WithWeekOfYearPolicyValue(value tfconfig.Variable) *UserModel { + u.WeekOfYearPolicy = value + return u +} + +func (u *UserModel) WithWeekStartValue(value tfconfig.Variable) *UserModel { + u.WeekStart = value + return u +} diff --git a/pkg/datasources/databases.go b/pkg/datasources/databases.go index fa0acd83e8..a9a0f6d2d1 100644 --- a/pkg/datasources/databases.go +++ b/pkg/datasources/databases.go @@ -146,11 +146,7 @@ func ReadDatabases(ctx context.Context, d *schema.ResourceData, meta any) diag.D var databaseParameters []map[string]any if d.Get("with_parameters").(bool) { - parameters, err := client.Parameters.ShowParameters(ctx, &sdk.ShowParametersOptions{ - In: &sdk.ParametersIn{ - Database: database.ID(), - }, - }) + parameters, err := client.Databases.ShowParameters(ctx, database.ID()) if err != nil { return diag.FromErr(err) } diff --git a/pkg/datasources/parameters_acceptance_test.go b/pkg/datasources/parameters_acceptance_test.go index e510fdda8f..bd28718372 100644 --- a/pkg/datasources/parameters_acceptance_test.go +++ b/pkg/datasources/parameters_acceptance_test.go @@ -6,6 +6,8 @@ import ( acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/testenvs" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/tfversion" ) @@ -97,7 +99,10 @@ func TestAcc_Parameters_TransactionAbortOnErrorCanBeSet(t *testing.T) { // proves https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2353 is fixed // done on user, to not interfere with other parallel tests on the same account func TestAcc_Parameters_QuotedIdentifiersIgnoreCaseCanBeSet(t *testing.T) { - userId := acc.TestClient().Ids.RandomAccountObjectIdentifier() + _ = testenvs.GetOrSkipTest(t, testenvs.EnableAcceptance) + + user, userCleanup := acc.TestClient().User.CreateUser(t) + t.Cleanup(userCleanup) resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, @@ -107,23 +112,20 @@ func TestAcc_Parameters_QuotedIdentifiersIgnoreCaseCanBeSet(t *testing.T) { }, Steps: []resource.TestStep{ { - Config: sessionParameterOnUser(userId.Name()), + Config: sessionParameterOnUser(user.ID()), }, }, }) } -func sessionParameterOnUser(userName string) string { +func sessionParameterOnUser(userId sdk.AccountObjectIdentifier) string { return fmt.Sprintf( ` - resource "snowflake_user" "u" { - name = "%s" - } resource "snowflake_session_parameter" "test" { key = "QUOTED_IDENTIFIERS_IGNORE_CASE" value = "true" - user = snowflake_user.u.name - }`, userName) + user = %[1]s + }`, userId.FullyQualifiedName()) } func parametersConfigOnAccount() string { diff --git a/pkg/datasources/schemas.go b/pkg/datasources/schemas.go index 371e42adf4..07c5be6d67 100644 --- a/pkg/datasources/schemas.go +++ b/pkg/datasources/schemas.go @@ -205,11 +205,7 @@ func ReadSchemas(ctx context.Context, d *schema.ResourceData, meta any) diag.Dia var schemaParameters []map[string]any if d.Get("with_parameters").(bool) { - parameters, err := client.Parameters.ShowParameters(ctx, &sdk.ShowParametersOptions{ - In: &sdk.ParametersIn{ - Schema: schema.ID(), - }, - }) + parameters, err := client.Schemas.ShowParameters(ctx, schema.ID()) if err != nil { return diag.FromErr(err) } diff --git a/pkg/datasources/warehouses.go b/pkg/datasources/warehouses.go index 8c153989bd..e52c09e9aa 100644 --- a/pkg/datasources/warehouses.go +++ b/pkg/datasources/warehouses.go @@ -103,11 +103,7 @@ func ReadWarehouses(ctx context.Context, d *schema.ResourceData, meta any) diag. var warehouseParameters []map[string]any if d.Get("with_parameters").(bool) { - parameters, err := client.Parameters.ShowParameters(ctx, &sdk.ShowParametersOptions{ - In: &sdk.ParametersIn{ - Warehouse: warehouse.ID(), - }, - }) + parameters, err := client.Warehouses.ShowParameters(ctx, warehouse.ID()) if err != nil { return diag.FromErr(err) } diff --git a/pkg/resources/account_parameter_acceptance_test.go b/pkg/resources/account_parameter_acceptance_test.go index 5b50b2517b..95d9322d65 100644 --- a/pkg/resources/account_parameter_acceptance_test.go +++ b/pkg/resources/account_parameter_acceptance_test.go @@ -80,7 +80,9 @@ func TestAcc_AccountParameter_REQUIRE_STORAGE_INTEGRATION_FOR_STAGE_CREATION(t * }) } +// TODO [SNOW-1528546]: unskip func TestAcc_AccountParameter_Issue2573(t *testing.T) { + t.Skipf("The cleanup for parameter is currently incorrect and this test messes with other ones. Skipping until SNOW-1528546 is resolved.") resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, PreCheck: func() { acc.TestAccPreCheck(t) }, diff --git a/pkg/resources/custom_diffs.go b/pkg/resources/custom_diffs.go index 6bcfa55c8a..05a9b04ac0 100644 --- a/pkg/resources/custom_diffs.go +++ b/pkg/resources/custom_diffs.go @@ -13,23 +13,23 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func StringParameterValueComputedIf(key string, params []*sdk.Parameter, parameterLevel sdk.ParameterType, parameter sdk.AccountParameter) schema.CustomizeDiffFunc { +func StringParameterValueComputedIf[T ~string](key string, params []*sdk.Parameter, parameterLevel sdk.ParameterType, parameter T) schema.CustomizeDiffFunc { return ParameterValueComputedIf(key, params, parameterLevel, parameter, func(value any) string { return value.(string) }) } -func IntParameterValueComputedIf(key string, params []*sdk.Parameter, parameterLevel sdk.ParameterType, parameter sdk.AccountParameter) schema.CustomizeDiffFunc { +func IntParameterValueComputedIf[T ~string](key string, params []*sdk.Parameter, parameterLevel sdk.ParameterType, parameter T) schema.CustomizeDiffFunc { return ParameterValueComputedIf(key, params, parameterLevel, parameter, func(value any) string { return strconv.Itoa(value.(int)) }) } -func BoolParameterValueComputedIf(key string, params []*sdk.Parameter, parameterLevel sdk.ParameterType, parameter sdk.AccountParameter) schema.CustomizeDiffFunc { +func BoolParameterValueComputedIf[T ~string](key string, params []*sdk.Parameter, parameterLevel sdk.ParameterType, parameter T) schema.CustomizeDiffFunc { return ParameterValueComputedIf(key, params, parameterLevel, parameter, func(value any) string { return strconv.FormatBool(value.(bool)) }) } -func ParameterValueComputedIf(key string, parameters []*sdk.Parameter, objectParameterLevel sdk.ParameterType, accountParameter sdk.AccountParameter, valueToString func(v any) string) schema.CustomizeDiffFunc { +func ParameterValueComputedIf[T ~string](key string, parameters []*sdk.Parameter, objectParameterLevel sdk.ParameterType, param T, valueToString func(v any) string) schema.CustomizeDiffFunc { return func(ctx context.Context, d *schema.ResourceDiff, meta any) error { - foundParameter, err := collections.FindOne(parameters, func(parameter *sdk.Parameter) bool { return parameter.Key == string(accountParameter) }) + foundParameter, err := collections.FindOne(parameters, func(parameter *sdk.Parameter) bool { return parameter.Key == string(param) }) if err != nil { - log.Printf("[WARN] failed to find account parameter: %s", accountParameter) + log.Printf("[WARN] failed to find parameter: %s", param) return nil } parameter := *foundParameter @@ -98,8 +98,8 @@ func ComputedIfAnyAttributeChanged(key string, changedAttributeKeys ...string) s }) } -type parameter struct { - parameterName sdk.AccountParameter +type parameter[T ~string] struct { + parameterName T valueType valueType parameterType sdk.ParameterType } @@ -116,7 +116,7 @@ type ResourceIdProvider interface { Id() string } -func ParametersCustomDiff(parametersProvider func(context.Context, ResourceIdProvider, any) ([]*sdk.Parameter, error), parameters ...parameter) schema.CustomizeDiffFunc { +func ParametersCustomDiff[T ~string](parametersProvider func(context.Context, ResourceIdProvider, any) ([]*sdk.Parameter, error), parameters ...parameter[T]) schema.CustomizeDiffFunc { return func(ctx context.Context, d *schema.ResourceDiff, meta any) error { if d.Id() == "" { return nil diff --git a/pkg/resources/database.go b/pkg/resources/database.go index d6c1085cf1..5044cb563d 100644 --- a/pkg/resources/database.go +++ b/pkg/resources/database.go @@ -84,12 +84,12 @@ func Database() *schema.Resource { DeleteContext: DeleteDatabase, Description: "Represents a standard database. If replication configuration is specified, the database is promoted to serve as a primary database for replication.", - Schema: helpers.MergeMaps(databaseSchema, DatabaseParametersSchema), + Schema: helpers.MergeMaps(databaseSchema, databaseParametersSchema), Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, - CustomizeDiff: DatabaseParametersCustomDiff, + CustomizeDiff: databaseParametersCustomDiff, StateUpgraders: []schema.StateUpgrader{ { @@ -107,47 +107,15 @@ func CreateDatabase(ctx context.Context, d *schema.ResourceData, meta any) diag. id := sdk.NewAccountObjectIdentifier(d.Get("name").(string)) - dataRetentionTimeInDays, - maxDataExtensionTimeInDays, - externalVolume, - catalog, - replaceInvalidCharacters, - defaultDDLCollation, - storageSerializationPolicy, - logLevel, - traceLevel, - suspendTaskAfterNumFailures, - taskAutoRetryAttempts, - userTaskManagedInitialWarehouseSize, - userTaskTimeoutMs, - userTaskMinimumTriggerIntervalInSeconds, - quotedIdentifiersIgnoreCase, - enableConsoleOutput, - err := GetAllDatabaseParameters(d) - if err != nil { - return diag.FromErr(err) + opts := &sdk.CreateDatabaseOptions{ + Transient: GetConfigPropertyAsPointerAllowingZeroValue[bool](d, "is_transient"), + Comment: GetConfigPropertyAsPointerAllowingZeroValue[string](d, "comment"), + } + if parametersCreateDiags := handleDatabaseParametersCreate(d, opts); len(parametersCreateDiags) > 0 { + return parametersCreateDiags } - err = client.Databases.Create(ctx, id, &sdk.CreateDatabaseOptions{ - Transient: GetConfigPropertyAsPointerAllowingZeroValue[bool](d, "is_transient"), - DataRetentionTimeInDays: dataRetentionTimeInDays, - MaxDataExtensionTimeInDays: maxDataExtensionTimeInDays, - ExternalVolume: externalVolume, - Catalog: catalog, - ReplaceInvalidCharacters: replaceInvalidCharacters, - DefaultDDLCollation: defaultDDLCollation, - StorageSerializationPolicy: storageSerializationPolicy, - LogLevel: logLevel, - TraceLevel: traceLevel, - SuspendTaskAfterNumFailures: suspendTaskAfterNumFailures, - TaskAutoRetryAttempts: taskAutoRetryAttempts, - UserTaskManagedInitialWarehouseSize: userTaskManagedInitialWarehouseSize, - UserTaskTimeoutMs: userTaskTimeoutMs, - UserTaskMinimumTriggerIntervalInSeconds: userTaskMinimumTriggerIntervalInSeconds, - QuotedIdentifiersIgnoreCase: quotedIdentifiersIgnoreCase, - EnableConsoleOutput: enableConsoleOutput, - Comment: GetConfigPropertyAsPointerAllowingZeroValue[string](d, "comment"), - }) + err := client.Databases.Create(ctx, id, opts) if err != nil { return diag.FromErr(err) } @@ -235,7 +203,7 @@ func UpdateDatabase(ctx context.Context, d *schema.ResourceData, meta any) diag. databaseSetRequest := new(sdk.DatabaseSet) databaseUnsetRequest := new(sdk.DatabaseUnset) - if updateParamDiags := HandleDatabaseParametersChanges(d, databaseSetRequest, databaseUnsetRequest); len(updateParamDiags) > 0 { + if updateParamDiags := handleDatabaseParametersChanges(d, databaseSetRequest, databaseUnsetRequest); len(updateParamDiags) > 0 { return updateParamDiags } @@ -440,16 +408,12 @@ func ReadDatabase(ctx context.Context, d *schema.ResourceData, meta any) diag.Di } } - databaseParameters, err := client.Parameters.ShowParameters(ctx, &sdk.ShowParametersOptions{ - In: &sdk.ParametersIn{ - Database: id, - }, - }) + databaseParameters, err := client.Databases.ShowParameters(ctx, id) if err != nil { return diag.FromErr(err) } - if diags := HandleDatabaseParameterRead(d, databaseParameters); diags != nil { + if diags := handleDatabaseParameterRead(d, databaseParameters); diags != nil { return diags } diff --git a/pkg/resources/database_commons.go b/pkg/resources/database_commons.go index 61e0d9638d..7a285f475f 100644 --- a/pkg/resources/database_commons.go +++ b/pkg/resources/database_commons.go @@ -7,7 +7,6 @@ import ( "strconv" "strings" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -16,45 +15,39 @@ import ( ) var ( - DatabaseParametersSchema = make(map[string]*schema.Schema) - SharedDatabaseParametersSchema = make(map[string]*schema.Schema) + databaseParametersSchema = make(map[string]*schema.Schema) + sharedDatabaseParametersSchema = make(map[string]*schema.Schema) sharedDatabaseNotApplicableParameters = []sdk.ObjectParameter{ sdk.ObjectParameterDataRetentionTimeInDays, sdk.ObjectParameterMaxDataExtensionTimeInDays, } - DatabaseParametersCustomDiff = ParametersCustomDiff( + databaseParametersCustomDiff = ParametersCustomDiff( databaseParametersProvider, - parameter{sdk.AccountParameterDataRetentionTimeInDays, valueTypeInt, sdk.ParameterTypeDatabase}, - parameter{sdk.AccountParameterMaxDataExtensionTimeInDays, valueTypeInt, sdk.ParameterTypeDatabase}, - parameter{sdk.AccountParameterExternalVolume, valueTypeString, sdk.ParameterTypeDatabase}, - parameter{sdk.AccountParameterCatalog, valueTypeString, sdk.ParameterTypeDatabase}, - parameter{sdk.AccountParameterReplaceInvalidCharacters, valueTypeBool, sdk.ParameterTypeDatabase}, - parameter{sdk.AccountParameterDefaultDDLCollation, valueTypeString, sdk.ParameterTypeDatabase}, - parameter{sdk.AccountParameterStorageSerializationPolicy, valueTypeString, sdk.ParameterTypeDatabase}, - parameter{sdk.AccountParameterLogLevel, valueTypeString, sdk.ParameterTypeDatabase}, - parameter{sdk.AccountParameterTraceLevel, valueTypeString, sdk.ParameterTypeDatabase}, - parameter{sdk.AccountParameterSuspendTaskAfterNumFailures, valueTypeInt, sdk.ParameterTypeDatabase}, - parameter{sdk.AccountParameterTaskAutoRetryAttempts, valueTypeInt, sdk.ParameterTypeDatabase}, - parameter{sdk.AccountParameterUserTaskManagedInitialWarehouseSize, valueTypeString, sdk.ParameterTypeDatabase}, - parameter{sdk.AccountParameterUserTaskTimeoutMs, valueTypeInt, sdk.ParameterTypeDatabase}, - parameter{sdk.AccountParameterUserTaskMinimumTriggerIntervalInSeconds, valueTypeInt, sdk.ParameterTypeDatabase}, - parameter{sdk.AccountParameterQuotedIdentifiersIgnoreCase, valueTypeBool, sdk.ParameterTypeDatabase}, - parameter{sdk.AccountParameterEnableConsoleOutput, valueTypeBool, sdk.ParameterTypeDatabase}, + parameter[sdk.AccountParameter]{sdk.AccountParameterDataRetentionTimeInDays, valueTypeInt, sdk.ParameterTypeDatabase}, + parameter[sdk.AccountParameter]{sdk.AccountParameterMaxDataExtensionTimeInDays, valueTypeInt, sdk.ParameterTypeDatabase}, + parameter[sdk.AccountParameter]{sdk.AccountParameterExternalVolume, valueTypeString, sdk.ParameterTypeDatabase}, + parameter[sdk.AccountParameter]{sdk.AccountParameterCatalog, valueTypeString, sdk.ParameterTypeDatabase}, + parameter[sdk.AccountParameter]{sdk.AccountParameterReplaceInvalidCharacters, valueTypeBool, sdk.ParameterTypeDatabase}, + parameter[sdk.AccountParameter]{sdk.AccountParameterDefaultDDLCollation, valueTypeString, sdk.ParameterTypeDatabase}, + parameter[sdk.AccountParameter]{sdk.AccountParameterStorageSerializationPolicy, valueTypeString, sdk.ParameterTypeDatabase}, + parameter[sdk.AccountParameter]{sdk.AccountParameterLogLevel, valueTypeString, sdk.ParameterTypeDatabase}, + parameter[sdk.AccountParameter]{sdk.AccountParameterTraceLevel, valueTypeString, sdk.ParameterTypeDatabase}, + parameter[sdk.AccountParameter]{sdk.AccountParameterSuspendTaskAfterNumFailures, valueTypeInt, sdk.ParameterTypeDatabase}, + parameter[sdk.AccountParameter]{sdk.AccountParameterTaskAutoRetryAttempts, valueTypeInt, sdk.ParameterTypeDatabase}, + parameter[sdk.AccountParameter]{sdk.AccountParameterUserTaskManagedInitialWarehouseSize, valueTypeString, sdk.ParameterTypeDatabase}, + parameter[sdk.AccountParameter]{sdk.AccountParameterUserTaskTimeoutMs, valueTypeInt, sdk.ParameterTypeDatabase}, + parameter[sdk.AccountParameter]{sdk.AccountParameterUserTaskMinimumTriggerIntervalInSeconds, valueTypeInt, sdk.ParameterTypeDatabase}, + parameter[sdk.AccountParameter]{sdk.AccountParameterQuotedIdentifiersIgnoreCase, valueTypeBool, sdk.ParameterTypeDatabase}, + parameter[sdk.AccountParameter]{sdk.AccountParameterEnableConsoleOutput, valueTypeBool, sdk.ParameterTypeDatabase}, ) ) func databaseParametersProvider(ctx context.Context, d ResourceIdProvider, meta any) ([]*sdk.Parameter, error) { - client := meta.(*provider.Context).Client - id := helpers.DecodeSnowflakeID(d.Id()).(sdk.AccountObjectIdentifier) - databaseParameters, err := client.Parameters.ShowParameters(ctx, &sdk.ShowParametersOptions{ - In: &sdk.ParametersIn{ - Database: id, - }, - }) - if err != nil { - return nil, err - } - return databaseParameters, nil + return parametersProvider(ctx, d, meta.(*provider.Context), databaseParametersProviderFunc) +} + +func databaseParametersProviderFunc(c *sdk.Client) showParametersFunc[sdk.AccountObjectIdentifier] { + return c.Databases.ShowParameters } func init() { @@ -173,7 +166,7 @@ func init() { for _, field := range databaseParameterFields { fieldName := strings.ToLower(string(field.Name)) - DatabaseParametersSchema[fieldName] = &schema.Schema{ + databaseParametersSchema[fieldName] = &schema.Schema{ Type: field.Type, Description: field.Description, Computed: true, @@ -183,7 +176,7 @@ func init() { } if !slices.Contains(sharedDatabaseNotApplicableParameters, field.Name) { - SharedDatabaseParametersSchema[fieldName] = &schema.Schema{ + sharedDatabaseParametersSchema[fieldName] = &schema.Schema{ Type: field.Type, Description: field.Description, ForceNew: true, @@ -196,111 +189,89 @@ func init() { } } -// TODO(SNOW-1480106): Change to smaller and safer return type -func GetAllDatabaseParameters(d *schema.ResourceData) ( - dataRetentionTimeInDays *int, - maxDataExtensionTimeInDays *int, - externalVolume *sdk.AccountObjectIdentifier, - catalog *sdk.AccountObjectIdentifier, - replaceInvalidCharacters *bool, - defaultDDLCollation *string, - storageSerializationPolicy *sdk.StorageSerializationPolicy, - logLevel *sdk.LogLevel, - traceLevel *sdk.TraceLevel, - suspendTaskAfterNumFailures *int, - taskAutoRetryAttempts *int, - userTaskManagedInitialWarehouseSize *sdk.WarehouseSize, - userTaskTimeoutMs *int, - userTaskMinimumTriggerIntervalInSeconds *int, - quotedIdentifiersIgnoreCase *bool, - enableConsoleOutput *bool, - err error, -) { - dataRetentionTimeInDays = GetConfigPropertyAsPointerAllowingZeroValue[int](d, "data_retention_time_in_days") - maxDataExtensionTimeInDays = GetConfigPropertyAsPointerAllowingZeroValue[int](d, "max_data_extension_time_in_days") - if externalVolumeRaw := GetConfigPropertyAsPointerAllowingZeroValue[string](d, "external_volume"); externalVolumeRaw != nil { - externalVolume = sdk.Pointer(sdk.NewAccountObjectIdentifier(*externalVolumeRaw)) - } - if catalogRaw := GetConfigPropertyAsPointerAllowingZeroValue[string](d, "catalog"); catalogRaw != nil { - catalog = sdk.Pointer(sdk.NewAccountObjectIdentifier(*catalogRaw)) - } - replaceInvalidCharacters = GetConfigPropertyAsPointerAllowingZeroValue[bool](d, "replace_invalid_characters") - defaultDDLCollation = GetConfigPropertyAsPointerAllowingZeroValue[string](d, "default_ddl_collation") - if storageSerializationPolicyRaw := GetConfigPropertyAsPointerAllowingZeroValue[string](d, "storage_serialization_policy"); storageSerializationPolicyRaw != nil { - storageSerializationPolicy = sdk.Pointer(sdk.StorageSerializationPolicy(*storageSerializationPolicyRaw)) - } - if logLevelRaw := GetConfigPropertyAsPointerAllowingZeroValue[string](d, "log_level"); logLevelRaw != nil { - logLevel = sdk.Pointer(sdk.LogLevel(*logLevelRaw)) - } - if traceLevelRaw := GetConfigPropertyAsPointerAllowingZeroValue[string](d, "trace_level"); traceLevelRaw != nil { - traceLevel = sdk.Pointer(sdk.TraceLevel(*traceLevelRaw)) - } - suspendTaskAfterNumFailures = GetConfigPropertyAsPointerAllowingZeroValue[int](d, "suspend_task_after_num_failures") - taskAutoRetryAttempts = GetConfigPropertyAsPointerAllowingZeroValue[int](d, "task_auto_retry_attempts") - if userTaskManagedInitialWarehouseSizeRaw := GetConfigPropertyAsPointerAllowingZeroValue[string](d, "user_task_managed_initial_warehouse_size"); userTaskManagedInitialWarehouseSizeRaw != nil { - var warehouseSize sdk.WarehouseSize - if warehouseSize, err = sdk.ToWarehouseSize(*userTaskManagedInitialWarehouseSizeRaw); err != nil { - return - } - userTaskManagedInitialWarehouseSize = sdk.Pointer(warehouseSize) - } - userTaskTimeoutMs = GetConfigPropertyAsPointerAllowingZeroValue[int](d, "user_task_timeout_ms") - userTaskMinimumTriggerIntervalInSeconds = GetConfigPropertyAsPointerAllowingZeroValue[int](d, "user_task_minimum_trigger_interval_in_seconds") - quotedIdentifiersIgnoreCase = GetConfigPropertyAsPointerAllowingZeroValue[bool](d, "quoted_identifiers_ignore_case") - enableConsoleOutput = GetConfigPropertyAsPointerAllowingZeroValue[bool](d, "enable_console_output") - return +func handleDatabaseParametersCreate(d *schema.ResourceData, createOpts *sdk.CreateDatabaseOptions) diag.Diagnostics { + return JoinDiags( + handleParameterCreate(d, sdk.ObjectParameterDataRetentionTimeInDays, &createOpts.DataRetentionTimeInDays), + handleParameterCreate(d, sdk.ObjectParameterMaxDataExtensionTimeInDays, &createOpts.MaxDataExtensionTimeInDays), + handleParameterCreateWithMapping(d, sdk.ObjectParameterExternalVolume, &createOpts.ExternalVolume, stringToAccountObjectIdentifier), + handleParameterCreateWithMapping(d, sdk.ObjectParameterCatalog, &createOpts.Catalog, stringToAccountObjectIdentifier), + handleParameterCreate(d, sdk.ObjectParameterReplaceInvalidCharacters, &createOpts.ReplaceInvalidCharacters), + handleParameterCreate(d, sdk.ObjectParameterDefaultDDLCollation, &createOpts.DefaultDDLCollation), + handleParameterCreateWithMapping(d, sdk.ObjectParameterStorageSerializationPolicy, &createOpts.StorageSerializationPolicy, sdk.ToStorageSerializationPolicy), + handleParameterCreateWithMapping(d, sdk.ObjectParameterLogLevel, &createOpts.LogLevel, sdk.ToLogLevel), + handleParameterCreateWithMapping(d, sdk.ObjectParameterTraceLevel, &createOpts.TraceLevel, sdk.ToTraceLevel), + handleParameterCreate(d, sdk.ObjectParameterSuspendTaskAfterNumFailures, &createOpts.SuspendTaskAfterNumFailures), + handleParameterCreate(d, sdk.ObjectParameterTaskAutoRetryAttempts, &createOpts.TaskAutoRetryAttempts), + handleParameterCreateWithMapping(d, sdk.ObjectParameterUserTaskManagedInitialWarehouseSize, &createOpts.UserTaskManagedInitialWarehouseSize, sdk.ToWarehouseSize), + handleParameterCreate(d, sdk.ObjectParameterUserTaskTimeoutMs, &createOpts.UserTaskTimeoutMs), + handleParameterCreate(d, sdk.ObjectParameterUserTaskMinimumTriggerIntervalInSeconds, &createOpts.UserTaskMinimumTriggerIntervalInSeconds), + handleParameterCreate(d, sdk.ObjectParameterQuotedIdentifiersIgnoreCase, &createOpts.QuotedIdentifiersIgnoreCase), + handleParameterCreate(d, sdk.ObjectParameterEnableConsoleOutput, &createOpts.EnableConsoleOutput), + ) } -func HandleDatabaseParametersChanges(d *schema.ResourceData, set *sdk.DatabaseSet, unset *sdk.DatabaseUnset) diag.Diagnostics { +func handleSecondaryDatabaseParametersCreate(d *schema.ResourceData, createOpts *sdk.CreateSecondaryDatabaseOptions) diag.Diagnostics { return JoinDiags( - handleValuePropertyChange[int](d, "data_retention_time_in_days", &set.DataRetentionTimeInDays, &unset.DataRetentionTimeInDays), - handleValuePropertyChange[int](d, "max_data_extension_time_in_days", &set.MaxDataExtensionTimeInDays, &unset.MaxDataExtensionTimeInDays), - handleValuePropertyChangeWithMapping[string](d, "external_volume", &set.ExternalVolume, &unset.ExternalVolume, func(value string) (sdk.AccountObjectIdentifier, error) { - return sdk.NewAccountObjectIdentifier(value), nil - }), - handleValuePropertyChangeWithMapping[string](d, "catalog", &set.Catalog, &unset.Catalog, func(value string) (sdk.AccountObjectIdentifier, error) { - return sdk.NewAccountObjectIdentifier(value), nil - }), - handleValuePropertyChange[bool](d, "replace_invalid_characters", &set.ReplaceInvalidCharacters, &unset.ReplaceInvalidCharacters), - handleValuePropertyChange[string](d, "default_ddl_collation", &set.DefaultDDLCollation, &unset.DefaultDDLCollation), - handleValuePropertyChangeWithMapping[string](d, "storage_serialization_policy", &set.StorageSerializationPolicy, &unset.StorageSerializationPolicy, sdk.ToStorageSerializationPolicy), - handleValuePropertyChangeWithMapping[string](d, "log_level", &set.LogLevel, &unset.LogLevel, sdk.ToLogLevel), - handleValuePropertyChangeWithMapping[string](d, "trace_level", &set.TraceLevel, &unset.TraceLevel, sdk.ToTraceLevel), - handleValuePropertyChange[int](d, "suspend_task_after_num_failures", &set.SuspendTaskAfterNumFailures, &unset.SuspendTaskAfterNumFailures), - handleValuePropertyChange[int](d, "task_auto_retry_attempts", &set.TaskAutoRetryAttempts, &unset.TaskAutoRetryAttempts), - handleValuePropertyChangeWithMapping[string](d, "user_task_managed_initial_warehouse_size", &set.UserTaskManagedInitialWarehouseSize, &unset.UserTaskManagedInitialWarehouseSize, sdk.ToWarehouseSize), - handleValuePropertyChange[int](d, "user_task_timeout_ms", &set.UserTaskTimeoutMs, &unset.UserTaskTimeoutMs), - handleValuePropertyChange[int](d, "user_task_minimum_trigger_interval_in_seconds", &set.UserTaskMinimumTriggerIntervalInSeconds, &unset.UserTaskMinimumTriggerIntervalInSeconds), - handleValuePropertyChange[bool](d, "quoted_identifiers_ignore_case", &set.QuotedIdentifiersIgnoreCase, &unset.QuotedIdentifiersIgnoreCase), - handleValuePropertyChange[bool](d, "enable_console_output", &set.EnableConsoleOutput, &unset.EnableConsoleOutput), + handleParameterCreate(d, sdk.ObjectParameterDataRetentionTimeInDays, &createOpts.DataRetentionTimeInDays), + handleParameterCreate(d, sdk.ObjectParameterMaxDataExtensionTimeInDays, &createOpts.MaxDataExtensionTimeInDays), + handleParameterCreateWithMapping(d, sdk.ObjectParameterExternalVolume, &createOpts.ExternalVolume, stringToAccountObjectIdentifier), + handleParameterCreateWithMapping(d, sdk.ObjectParameterCatalog, &createOpts.Catalog, stringToAccountObjectIdentifier), + handleParameterCreate(d, sdk.ObjectParameterReplaceInvalidCharacters, &createOpts.ReplaceInvalidCharacters), + handleParameterCreate(d, sdk.ObjectParameterDefaultDDLCollation, &createOpts.DefaultDDLCollation), + handleParameterCreateWithMapping(d, sdk.ObjectParameterStorageSerializationPolicy, &createOpts.StorageSerializationPolicy, sdk.ToStorageSerializationPolicy), + handleParameterCreateWithMapping(d, sdk.ObjectParameterLogLevel, &createOpts.LogLevel, sdk.ToLogLevel), + handleParameterCreateWithMapping(d, sdk.ObjectParameterTraceLevel, &createOpts.TraceLevel, sdk.ToTraceLevel), + handleParameterCreate(d, sdk.ObjectParameterSuspendTaskAfterNumFailures, &createOpts.SuspendTaskAfterNumFailures), + handleParameterCreate(d, sdk.ObjectParameterTaskAutoRetryAttempts, &createOpts.TaskAutoRetryAttempts), + handleParameterCreateWithMapping(d, sdk.ObjectParameterUserTaskManagedInitialWarehouseSize, &createOpts.UserTaskManagedInitialWarehouseSize, sdk.ToWarehouseSize), + handleParameterCreate(d, sdk.ObjectParameterUserTaskTimeoutMs, &createOpts.UserTaskTimeoutMs), + handleParameterCreate(d, sdk.ObjectParameterUserTaskMinimumTriggerIntervalInSeconds, &createOpts.UserTaskMinimumTriggerIntervalInSeconds), + handleParameterCreate(d, sdk.ObjectParameterQuotedIdentifiersIgnoreCase, &createOpts.QuotedIdentifiersIgnoreCase), + handleParameterCreate(d, sdk.ObjectParameterEnableConsoleOutput, &createOpts.EnableConsoleOutput), ) } -// handleValuePropertyChange calls internally handleValuePropertyChangeWithMapping with identity mapping -func handleValuePropertyChange[T any](d *schema.ResourceData, key string, setField **T, unsetField **bool) diag.Diagnostics { - return handleValuePropertyChangeWithMapping[T, T](d, key, setField, unsetField, func(value T) (T, error) { return value, nil }) +func handleSharedDatabaseParametersCreate(d *schema.ResourceData, createOpts *sdk.CreateSharedDatabaseOptions) diag.Diagnostics { + return JoinDiags( + handleParameterCreateWithMapping(d, sdk.ObjectParameterExternalVolume, &createOpts.ExternalVolume, stringToAccountObjectIdentifier), + handleParameterCreateWithMapping(d, sdk.ObjectParameterCatalog, &createOpts.Catalog, stringToAccountObjectIdentifier), + handleParameterCreate(d, sdk.ObjectParameterReplaceInvalidCharacters, &createOpts.ReplaceInvalidCharacters), + handleParameterCreate(d, sdk.ObjectParameterDefaultDDLCollation, &createOpts.DefaultDDLCollation), + handleParameterCreateWithMapping(d, sdk.ObjectParameterStorageSerializationPolicy, &createOpts.StorageSerializationPolicy, sdk.ToStorageSerializationPolicy), + handleParameterCreateWithMapping(d, sdk.ObjectParameterLogLevel, &createOpts.LogLevel, sdk.ToLogLevel), + handleParameterCreateWithMapping(d, sdk.ObjectParameterTraceLevel, &createOpts.TraceLevel, sdk.ToTraceLevel), + handleParameterCreate(d, sdk.ObjectParameterSuspendTaskAfterNumFailures, &createOpts.SuspendTaskAfterNumFailures), + handleParameterCreate(d, sdk.ObjectParameterTaskAutoRetryAttempts, &createOpts.TaskAutoRetryAttempts), + handleParameterCreateWithMapping(d, sdk.ObjectParameterUserTaskManagedInitialWarehouseSize, &createOpts.UserTaskManagedInitialWarehouseSize, sdk.ToWarehouseSize), + handleParameterCreate(d, sdk.ObjectParameterUserTaskTimeoutMs, &createOpts.UserTaskTimeoutMs), + handleParameterCreate(d, sdk.ObjectParameterUserTaskMinimumTriggerIntervalInSeconds, &createOpts.UserTaskMinimumTriggerIntervalInSeconds), + handleParameterCreate(d, sdk.ObjectParameterQuotedIdentifiersIgnoreCase, &createOpts.QuotedIdentifiersIgnoreCase), + handleParameterCreate(d, sdk.ObjectParameterEnableConsoleOutput, &createOpts.EnableConsoleOutput), + ) } -// handleValuePropertyChangeWithMapping checks schema.ResourceData for change in key's value. If there's a change detected -// (or unknown value that basically indicates diff.SetNewComputed was called on the key), it checks if the value is set in the configuration. -// If the value is set, setField (representing setter for a value) is set to the new planned value applying mapping beforehand in cases where enum values, -// identifiers, etc. have to be set. Otherwise, unsetField is populated. -func handleValuePropertyChangeWithMapping[T, R any](d *schema.ResourceData, key string, setField **R, unsetField **bool, mapping func(value T) (R, error)) diag.Diagnostics { - if d.HasChange(key) || !d.GetRawPlan().AsValueMap()[key].IsKnown() { - if !d.GetRawConfig().AsValueMap()[key].IsNull() { - mappedValue, err := mapping(d.Get(key).(T)) - if err != nil { - return diag.FromErr(err) - } - *setField = sdk.Pointer(mappedValue) - } else { - *unsetField = sdk.Bool(true) - } - } - return nil +func handleDatabaseParametersChanges(d *schema.ResourceData, set *sdk.DatabaseSet, unset *sdk.DatabaseUnset) diag.Diagnostics { + return JoinDiags( + handleParameterUpdate(d, sdk.ObjectParameterDataRetentionTimeInDays, &set.DataRetentionTimeInDays, &unset.DataRetentionTimeInDays), + handleParameterUpdate(d, sdk.ObjectParameterMaxDataExtensionTimeInDays, &set.MaxDataExtensionTimeInDays, &unset.MaxDataExtensionTimeInDays), + handleParameterUpdateWithMapping(d, sdk.ObjectParameterExternalVolume, &set.ExternalVolume, &unset.ExternalVolume, stringToAccountObjectIdentifier), + handleParameterUpdateWithMapping(d, sdk.ObjectParameterCatalog, &set.Catalog, &unset.Catalog, stringToAccountObjectIdentifier), + handleParameterUpdate(d, sdk.ObjectParameterReplaceInvalidCharacters, &set.ReplaceInvalidCharacters, &unset.ReplaceInvalidCharacters), + handleParameterUpdate(d, sdk.ObjectParameterDefaultDDLCollation, &set.DefaultDDLCollation, &unset.DefaultDDLCollation), + handleParameterUpdateWithMapping(d, sdk.ObjectParameterStorageSerializationPolicy, &set.StorageSerializationPolicy, &unset.StorageSerializationPolicy, sdk.ToStorageSerializationPolicy), + handleParameterUpdateWithMapping(d, sdk.ObjectParameterLogLevel, &set.LogLevel, &unset.LogLevel, sdk.ToLogLevel), + handleParameterUpdateWithMapping(d, sdk.ObjectParameterTraceLevel, &set.TraceLevel, &unset.TraceLevel, sdk.ToTraceLevel), + handleParameterUpdate(d, sdk.ObjectParameterSuspendTaskAfterNumFailures, &set.SuspendTaskAfterNumFailures, &unset.SuspendTaskAfterNumFailures), + handleParameterUpdate(d, sdk.ObjectParameterTaskAutoRetryAttempts, &set.TaskAutoRetryAttempts, &unset.TaskAutoRetryAttempts), + handleParameterUpdateWithMapping(d, sdk.ObjectParameterUserTaskManagedInitialWarehouseSize, &set.UserTaskManagedInitialWarehouseSize, &unset.UserTaskManagedInitialWarehouseSize, sdk.ToWarehouseSize), + handleParameterUpdate(d, sdk.ObjectParameterUserTaskTimeoutMs, &set.UserTaskTimeoutMs, &unset.UserTaskTimeoutMs), + handleParameterUpdate(d, sdk.ObjectParameterUserTaskMinimumTriggerIntervalInSeconds, &set.UserTaskMinimumTriggerIntervalInSeconds, &unset.UserTaskMinimumTriggerIntervalInSeconds), + handleParameterUpdate(d, sdk.ObjectParameterQuotedIdentifiersIgnoreCase, &set.QuotedIdentifiersIgnoreCase, &unset.QuotedIdentifiersIgnoreCase), + handleParameterUpdate(d, sdk.ObjectParameterEnableConsoleOutput, &set.EnableConsoleOutput, &unset.EnableConsoleOutput), + ) } -func HandleDatabaseParameterRead(d *schema.ResourceData, databaseParameters []*sdk.Parameter) diag.Diagnostics { +func handleDatabaseParameterRead(d *schema.ResourceData, databaseParameters []*sdk.Parameter) diag.Diagnostics { for _, parameter := range databaseParameters { switch parameter.Key { case diff --git a/pkg/resources/network_policy_attachment_acceptance_test.go b/pkg/resources/network_policy_attachment_acceptance_test.go index e64514549b..f9866cc905 100644 --- a/pkg/resources/network_policy_attachment_acceptance_test.go +++ b/pkg/resources/network_policy_attachment_acceptance_test.go @@ -6,10 +6,10 @@ import ( "strings" "testing" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" - acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/testenvs" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -18,9 +18,13 @@ import ( ) func TestAcc_NetworkPolicyAttachmentUser(t *testing.T) { - user1 := acc.TestClient().Ids.Alpha() - user2 := acc.TestClient().Ids.Alpha() - policyNameUser := acc.TestClient().Ids.Alpha() + _ = testenvs.GetOrSkipTest(t, testenvs.EnableAcceptance) + + user1, user1Cleanup := acc.TestClient().User.CreateUser(t) + t.Cleanup(user1Cleanup) + user2, user2Cleanup := acc.TestClient().User.CreateUser(t) + t.Cleanup(user2Cleanup) + policyId := acc.TestClient().Ids.RandomAccountObjectIdentifier() resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, @@ -31,17 +35,17 @@ func TestAcc_NetworkPolicyAttachmentUser(t *testing.T) { CheckDestroy: nil, Steps: []resource.TestStep{ { - Config: networkPolicyAttachmentConfigSingle(user1, policyNameUser), + Config: networkPolicyAttachmentConfigSingle(user1.ID(), policyId), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_network_policy_attachment.test", "network_policy_name", policyNameUser), + resource.TestCheckResourceAttr("snowflake_network_policy_attachment.test", "network_policy_name", policyId.Name()), resource.TestCheckResourceAttr("snowflake_network_policy_attachment.test", "set_for_account", "false"), resource.TestCheckResourceAttr("snowflake_network_policy_attachment.test", "users.#", "1"), ), }, { - Config: networkPolicyAttachmentConfig(user1, user2, policyNameUser), + Config: networkPolicyAttachmentConfig(user1.ID(), user2.ID(), policyId), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_network_policy_attachment.test", "network_policy_name", policyNameUser), + resource.TestCheckResourceAttr("snowflake_network_policy_attachment.test", "network_policy_name", policyId.Name()), resource.TestCheckResourceAttr("snowflake_network_policy_attachment.test", "set_for_account", "false"), resource.TestCheckResourceAttr("snowflake_network_policy_attachment.test", "users.#", "2"), ), @@ -98,46 +102,34 @@ func testAccCheckNetworkPolicyAttachmentDestroy(s *terraform.State) error { return nil } -func networkPolicyAttachmentConfigSingle(user1, policyName string) string { +func networkPolicyAttachmentConfigSingle(user1Id sdk.AccountObjectIdentifier, policyId sdk.AccountObjectIdentifier) string { return fmt.Sprintf(` -resource "snowflake_user" "test-user1" { - name = "%s" -} - resource "snowflake_network_policy" "test" { - name = "%v" + name = %[2]s allowed_ip_list = ["192.168.0.100/24", "29.254.123.20"] } resource "snowflake_network_policy_attachment" "test" { network_policy_name = snowflake_network_policy.test.name set_for_account = false - users = [snowflake_user.test-user1.name] + users = [%[1]s] } -`, user1, policyName) +`, user1Id.FullyQualifiedName(), policyId.FullyQualifiedName()) } -func networkPolicyAttachmentConfig(user1, user2, policyName string) string { +func networkPolicyAttachmentConfig(user1Id sdk.AccountObjectIdentifier, user2Id sdk.AccountObjectIdentifier, policyId sdk.AccountObjectIdentifier) string { return fmt.Sprintf(` -resource "snowflake_user" "test-user1" { - name = "%s" -} - -resource "snowflake_user" "test-user2" { - name = "%s" -} - resource "snowflake_network_policy" "test" { - name = "%v" + name = %[3]s allowed_ip_list = ["192.168.0.100/24", "29.254.123.20"] } resource "snowflake_network_policy_attachment" "test" { network_policy_name = snowflake_network_policy.test.name set_for_account = false - users = [snowflake_user.test-user1.name, snowflake_user.test-user2.name] + users = [%[1]s, %[2]s] } -`, user1, user2, policyName) +`, user1Id.FullyQualifiedName(), user2Id.FullyQualifiedName(), policyId.FullyQualifiedName()) } func networkPolicyAttachmentConfigAccount(policyName string) string { diff --git a/pkg/resources/object_parameter_acceptance_test.go b/pkg/resources/object_parameter_acceptance_test.go index 96d4498d04..a1f3021ba4 100644 --- a/pkg/resources/object_parameter_acceptance_test.go +++ b/pkg/resources/object_parameter_acceptance_test.go @@ -4,10 +4,10 @@ import ( "fmt" "testing" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" - acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/testenvs" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/tfversion" ) @@ -59,7 +59,11 @@ func TestAcc_ObjectParameterAccount(t *testing.T) { } func TestAcc_UserParameter(t *testing.T) { - userName := acc.TestClient().Ids.Alpha() + _ = testenvs.GetOrSkipTest(t, testenvs.EnableAcceptance) + + user, userCleanup := acc.TestClient().User.CreateUser(t) + t.Cleanup(userCleanup) + resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, TerraformVersionChecks: []tfversion.TerraformVersionCheck{ @@ -69,7 +73,7 @@ func TestAcc_UserParameter(t *testing.T) { CheckDestroy: nil, Steps: []resource.TestStep{ { - Config: userParameterConfigBasic(userName, "ENABLE_UNREDACTED_QUERY_SYNTAX_ERROR", "true"), + Config: userParameterConfigBasic(user.ID(), "ENABLE_UNREDACTED_QUERY_SYNTAX_ERROR", "true"), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_object_parameter.p", "key", "ENABLE_UNREDACTED_QUERY_SYNTAX_ERROR"), resource.TestCheckResourceAttr("snowflake_object_parameter.p", "value", "true"), @@ -105,19 +109,15 @@ resource "snowflake_object_parameter" "p" { return fmt.Sprintf(s, key, value, databaseName) } -func userParameterConfigBasic(userName string, key string, value string) string { - s := ` -resource "snowflake_user" "user" { - name = "%s" -} +func userParameterConfigBasic(userId sdk.AccountObjectIdentifier, key string, value string) string { + return fmt.Sprintf(` resource "snowflake_object_parameter" "p" { - key = "%s" - value = "%s" + key = "%[2]s" + value = "%[3]s" object_type = "USER" object_identifier { - name = snowflake_user.user.name + name = %[1]s } } -` - return fmt.Sprintf(s, userName, key, value) +`, userId.FullyQualifiedName(), key, value) } diff --git a/pkg/resources/resource_parameters_commons.go b/pkg/resources/resource_parameters_commons.go new file mode 100644 index 0000000000..af196760f2 --- /dev/null +++ b/pkg/resources/resource_parameters_commons.go @@ -0,0 +1,95 @@ +package resources + +import ( + "context" + "fmt" + "strings" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +// handleParameterCreate calls internally handleParameterCreateWithMapping with identity mapping +func handleParameterCreate[T any, P ~string](d *schema.ResourceData, parameterName P, createField **T) diag.Diagnostics { + return handleParameterCreateWithMapping[T, T](d, parameterName, createField, identityMapping[T]) +} + +// handleParameterCreateWithMapping gets the property pointer from raw config. +// If the value is set, createField is set to the new planned value applying mapping beforehand. +// Otherwise, there is no change to the createField and nil is returned. +func handleParameterCreateWithMapping[T, R any, P ~string](d *schema.ResourceData, parameterName P, createField **R, mapping func(value T) (R, error)) diag.Diagnostics { + key := strings.ToLower(string(parameterName)) + if v := GetConfigPropertyAsPointerAllowingZeroValue[T](d, key); v != nil { + mappedValue, err := mapping(*v) + if err != nil { + return diag.FromErr(err) + } + *createField = sdk.Pointer(mappedValue) + } + return nil +} + +// handleParameterUpdate calls internally handleParameterUpdateWithMapping with identity mapping +func handleParameterUpdate[T any, P ~string](d *schema.ResourceData, parameterName P, setField **T, unsetField **bool) diag.Diagnostics { + return handleParameterUpdateWithMapping[T, T](d, parameterName, setField, unsetField, identityMapping[T]) +} + +// handleParameterUpdateWithMapping checks schema.ResourceData for change in key's value. If there's a change detected +// (or unknown value that basically indicates diff.SetNewComputed was called on the key), it checks if the value is set in the configuration. +// If the value is set, setField (representing setter for a value) is set to the new planned value applying mapping beforehand in cases where enum values, +// identifiers, etc. have to be set. Otherwise, unsetField is populated. +func handleParameterUpdateWithMapping[T, R any, P ~string](d *schema.ResourceData, parameterName P, setField **R, unsetField **bool, mapping func(value T) (R, error)) diag.Diagnostics { + key := strings.ToLower(string(parameterName)) + if d.HasChange(key) || !d.GetRawPlan().AsValueMap()[key].IsKnown() { + if !d.GetRawConfig().AsValueMap()[key].IsNull() { + mappedValue, err := mapping(d.Get(key).(T)) + if err != nil { + return diag.FromErr(err) + } + *setField = sdk.Pointer(mappedValue) + } else { + *unsetField = sdk.Bool(true) + } + } + return nil +} + +func identityMapping[T any](value T) (T, error) { + return value, nil +} + +func stringToAccountObjectIdentifier(value string) (sdk.AccountObjectIdentifier, error) { + return sdk.NewAccountObjectIdentifier(value), nil +} + +func stringToStringEnumProvider[T ~string](mapper func(string) (T, error)) func(value string) (T, error) { + return func(value string) (T, error) { + return mapper(value) + } +} + +// enrichWithReferenceToParameterDocs adds the reference to the Snowflake Parameter docs at the end of the provided description. +func enrichWithReferenceToParameterDocs[T ~string](parameter T, description string) string { + link := fmt.Sprintf("https://docs.snowflake.com/en/sql-reference/parameters#%s", strings.ReplaceAll(strings.ToLower(string(parameter)), "_", "-")) + return fmt.Sprintf("%s For more information, check [%s docs](%s).", description, parameter, link) +} + +type ( + showParametersFunc[T sdk.ObjectIdentifier] func(ctx context.Context, id T) ([]*sdk.Parameter, error) + showParametersFuncProvider[T sdk.ObjectIdentifier] func(client *sdk.Client) showParametersFunc[T] +) + +// parametersProvider is a generic function that can be used with ParametersCustomDiff +func parametersProvider[T sdk.ObjectIdentifier]( + ctx context.Context, + d ResourceIdProvider, + meta *provider.Context, + showParametersFuncProvider showParametersFuncProvider[T], +) ([]*sdk.Parameter, error) { + client := meta.Client + id := helpers.DecodeSnowflakeID(d.Id()).(T) + return showParametersFuncProvider(client)(ctx, id) +} diff --git a/pkg/resources/resource_parameters_commons_test.go b/pkg/resources/resource_parameters_commons_test.go new file mode 100644 index 0000000000..1e6ed32dc5 --- /dev/null +++ b/pkg/resources/resource_parameters_commons_test.go @@ -0,0 +1,19 @@ +package resources + +import ( + "testing" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers/random" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + "github.com/stretchr/testify/require" +) + +func Test_enrichWithReferenceToParameterDocs(t *testing.T) { + t.Run("formats the docs reference correctly", func(t *testing.T) { + description := random.Comment() + + enrichedDescription := enrichWithReferenceToParameterDocs(sdk.UserParameterAbortDetachedQuery, description) + + require.Equal(t, description+" "+"For more information, check [ABORT_DETACHED_QUERY docs](https://docs.snowflake.com/en/sql-reference/parameters#abort-detached-query).", enrichedDescription) + }) +} diff --git a/pkg/resources/schema.go b/pkg/resources/schema.go index 272e279752..57c2baf88b 100644 --- a/pkg/resources/schema.go +++ b/pkg/resources/schema.go @@ -6,21 +6,16 @@ import ( "fmt" "log" "slices" - "strconv" "strings" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/collections" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" - - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" - + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" ) var schemaSchema = map[string]*schema.Schema{ @@ -58,12 +53,6 @@ var schemaSchema = map[string]*schema.Schema{ return slices.Contains(sdk.ParseCommaSeparatedStringArray(x.(string), false), "TRANSIENT") }), }, - strings.ToLower(string(sdk.ObjectParameterPipeExecutionPaused)): { - Type: schema.TypeBool, - Optional: true, - Computed: true, - Description: "Specifies whether to pause a running pipe, primarily in preparation for transferring ownership of the pipe to a different role. For more information, see [PIPE_EXECUTION_PAUSED](https://docs.snowflake.com/en/sql-reference/parameters#pipe-execution-paused).", - }, "comment": { Type: schema.TypeString, Optional: true, @@ -109,6 +98,7 @@ func Schema() *schema.Resource { CustomizeDiff: customdiff.All( ComputedIfAnyAttributeChanged(ShowOutputAttributeName, "name", "comment", "with_managed_access", "is_transient"), ComputedIfAnyAttributeChanged(DescribeOutputAttributeName, "name"), + // TODO [SNOW-1348101]: use list from schema parameters definition instead listing all here (after moving to the SDK) ComputedIfAnyAttributeChanged(ParametersAttributeName, strings.ToLower(string(sdk.ObjectParameterDataRetentionTimeInDays)), strings.ToLower(string(sdk.ObjectParameterMaxDataExtensionTimeInDays)), @@ -128,29 +118,10 @@ func Schema() *schema.Resource { strings.ToLower(string(sdk.ObjectParameterEnableConsoleOutput)), strings.ToLower(string(sdk.ObjectParameterPipeExecutionPaused)), ), - ParametersCustomDiff( - schemaParametersProvider, - parameter{sdk.AccountParameterDataRetentionTimeInDays, valueTypeInt, sdk.ParameterTypeSchema}, - parameter{sdk.AccountParameterMaxDataExtensionTimeInDays, valueTypeInt, sdk.ParameterTypeSchema}, - parameter{sdk.AccountParameterExternalVolume, valueTypeString, sdk.ParameterTypeSchema}, - parameter{sdk.AccountParameterCatalog, valueTypeString, sdk.ParameterTypeSchema}, - parameter{sdk.AccountParameterReplaceInvalidCharacters, valueTypeBool, sdk.ParameterTypeSchema}, - parameter{sdk.AccountParameterDefaultDDLCollation, valueTypeString, sdk.ParameterTypeSchema}, - parameter{sdk.AccountParameterStorageSerializationPolicy, valueTypeString, sdk.ParameterTypeSchema}, - parameter{sdk.AccountParameterLogLevel, valueTypeString, sdk.ParameterTypeSchema}, - parameter{sdk.AccountParameterTraceLevel, valueTypeString, sdk.ParameterTypeSchema}, - parameter{sdk.AccountParameterSuspendTaskAfterNumFailures, valueTypeInt, sdk.ParameterTypeSchema}, - parameter{sdk.AccountParameterTaskAutoRetryAttempts, valueTypeInt, sdk.ParameterTypeSchema}, - parameter{sdk.AccountParameterUserTaskManagedInitialWarehouseSize, valueTypeString, sdk.ParameterTypeSchema}, - parameter{sdk.AccountParameterUserTaskTimeoutMs, valueTypeInt, sdk.ParameterTypeSchema}, - parameter{sdk.AccountParameterUserTaskMinimumTriggerIntervalInSeconds, valueTypeInt, sdk.ParameterTypeSchema}, - parameter{sdk.AccountParameterQuotedIdentifiersIgnoreCase, valueTypeBool, sdk.ParameterTypeSchema}, - parameter{sdk.AccountParameterEnableConsoleOutput, valueTypeBool, sdk.ParameterTypeSchema}, - parameter{sdk.AccountParameterPipeExecutionPaused, valueTypeBool, sdk.ParameterTypeSchema}, - ), + schemaParametersCustomDiff, ), - Schema: helpers.MergeMaps(schemaSchema, DatabaseParametersSchema), + Schema: helpers.MergeMaps(schemaSchema, schemaParametersSchema), Importer: &schema.ResourceImporter{ StateContext: ImportSchema, }, @@ -197,16 +168,6 @@ func ImportSchema(ctx context.Context, d *schema.ResourceData, meta any) ([]*sch return []*schema.ResourceData{d}, nil } -func schemaParametersProvider(ctx context.Context, d ResourceIdProvider, meta any) ([]*sdk.Parameter, error) { - client := meta.(*provider.Context).Client - id := helpers.DecodeSnowflakeID(d.Id()).(sdk.DatabaseObjectIdentifier) - return client.Parameters.ShowParameters(ctx, &sdk.ShowParametersOptions{ - In: &sdk.ParametersIn{ - Schema: id, - }, - }) -} - func CreateContextSchema(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { client := meta.(*provider.Context).Client name := d.Get("name").(string) @@ -224,48 +185,14 @@ func CreateContextSchema(ctx context.Context, d *schema.ResourceData, meta any) return UpdateContextSchema(ctx, d, meta) } } - // there is no PUBLIC schema, so we continue with creating - dataRetentionTimeInDays, - maxDataExtensionTimeInDays, - externalVolume, - catalog, - replaceInvalidCharacters, - defaultDDLCollation, - storageSerializationPolicy, - logLevel, - traceLevel, - suspendTaskAfterNumFailures, - taskAutoRetryAttempts, - userTaskManagedInitialWarehouseSize, - userTaskTimeoutMs, - userTaskMinimumTriggerIntervalInSeconds, - quotedIdentifiersIgnoreCase, - enableConsoleOutput, - err := GetAllDatabaseParameters(d) - if err != nil { - return diag.FromErr(err) - } opts := &sdk.CreateSchemaOptions{ - DataRetentionTimeInDays: dataRetentionTimeInDays, - MaxDataExtensionTimeInDays: maxDataExtensionTimeInDays, - ExternalVolume: externalVolume, - Catalog: catalog, - ReplaceInvalidCharacters: replaceInvalidCharacters, - DefaultDDLCollation: defaultDDLCollation, - StorageSerializationPolicy: storageSerializationPolicy, - LogLevel: logLevel, - TraceLevel: traceLevel, - SuspendTaskAfterNumFailures: suspendTaskAfterNumFailures, - TaskAutoRetryAttempts: taskAutoRetryAttempts, - UserTaskManagedInitialWarehouseSize: userTaskManagedInitialWarehouseSize, - UserTaskTimeoutMs: userTaskTimeoutMs, - UserTaskMinimumTriggerIntervalInSeconds: userTaskMinimumTriggerIntervalInSeconds, - QuotedIdentifiersIgnoreCase: quotedIdentifiersIgnoreCase, - EnableConsoleOutput: enableConsoleOutput, - PipeExecutionPaused: GetConfigPropertyAsPointerAllowingZeroValue[bool](d, "pipe_execution_paused"), - Comment: GetConfigPropertyAsPointerAllowingZeroValue[string](d, "comment"), + Comment: GetConfigPropertyAsPointerAllowingZeroValue[string](d, "comment"), + } + if parametersCreateDiags := handleSchemaParametersCreate(d, opts); len(parametersCreateDiags) > 0 { + return parametersCreateDiags } + if v := d.Get("is_transient").(string); v != BooleanDefault { parsed, err := booleanStringToBool(v) if err != nil { @@ -339,31 +266,14 @@ func ReadContextSchema(withExternalChangesMarking bool) schema.ReadContextFunc { return diag.FromErr(err) } - schemaParameters, err := client.Parameters.ShowParameters(ctx, &sdk.ShowParametersOptions{ - In: &sdk.ParametersIn{ - Schema: id, - }, - }) + schemaParameters, err := client.Schemas.ShowParameters(ctx, id) if err != nil { return diag.FromErr(err) } - if diags := HandleDatabaseParameterRead(d, schemaParameters); diags != nil { + if diags := handleSchemaParameterRead(d, schemaParameters); diags != nil { return diags } - pipeExecutionPaused, err := collections.FindOne(schemaParameters, func(property *sdk.Parameter) bool { - return property.Key == "PIPE_EXECUTION_PAUSED" - }) - if err != nil { - return diag.FromErr(fmt.Errorf("failed to find schema PIPE_EXECUTION_PAUSED parameter, err = %w", err)) - } - value, err := strconv.ParseBool((*pipeExecutionPaused).Value) - if err != nil { - return diag.FromErr(err) - } - if err := d.Set(strings.ToLower(string(sdk.ObjectParameterPipeExecutionPaused)), value); err != nil { - return diag.FromErr(err) - } if withExternalChangesMarking { if err = handleExternalChangesToObjectInShow(d, @@ -462,7 +372,7 @@ func UpdateContextSchema(ctx context.Context, d *schema.ResourceData, meta any) } } - if updateParamDiags := HandleSchemaParametersChanges(d, set, unset); len(updateParamDiags) > 0 { + if updateParamDiags := handleSchemaParametersChanges(d, set, unset); len(updateParamDiags) > 0 { return updateParamDiags } if (*set != sdk.SchemaSet{}) { @@ -486,32 +396,6 @@ func UpdateContextSchema(ctx context.Context, d *schema.ResourceData, meta any) return ReadContextSchema(false)(ctx, d, meta) } -func HandleSchemaParametersChanges(d *schema.ResourceData, set *sdk.SchemaSet, unset *sdk.SchemaUnset) diag.Diagnostics { - return JoinDiags( - handleValuePropertyChange[int](d, "data_retention_time_in_days", &set.DataRetentionTimeInDays, &unset.DataRetentionTimeInDays), - handleValuePropertyChange[int](d, "max_data_extension_time_in_days", &set.MaxDataExtensionTimeInDays, &unset.MaxDataExtensionTimeInDays), - handleValuePropertyChangeWithMapping[string](d, "external_volume", &set.ExternalVolume, &unset.ExternalVolume, func(value string) (sdk.AccountObjectIdentifier, error) { - return sdk.NewAccountObjectIdentifier(value), nil - }), - handleValuePropertyChangeWithMapping[string](d, "catalog", &set.Catalog, &unset.Catalog, func(value string) (sdk.AccountObjectIdentifier, error) { - return sdk.NewAccountObjectIdentifier(value), nil - }), - handleValuePropertyChange[bool](d, "pipe_execution_paused", &set.PipeExecutionPaused, &unset.PipeExecutionPaused), - handleValuePropertyChange[bool](d, "replace_invalid_characters", &set.ReplaceInvalidCharacters, &unset.ReplaceInvalidCharacters), - handleValuePropertyChange[string](d, "default_ddl_collation", &set.DefaultDDLCollation, &unset.DefaultDDLCollation), - handleValuePropertyChangeWithMapping[string](d, "storage_serialization_policy", &set.StorageSerializationPolicy, &unset.StorageSerializationPolicy, sdk.ToStorageSerializationPolicy), - handleValuePropertyChangeWithMapping[string](d, "log_level", &set.LogLevel, &unset.LogLevel, sdk.ToLogLevel), - handleValuePropertyChangeWithMapping[string](d, "trace_level", &set.TraceLevel, &unset.TraceLevel, sdk.ToTraceLevel), - handleValuePropertyChange[int](d, "suspend_task_after_num_failures", &set.SuspendTaskAfterNumFailures, &unset.SuspendTaskAfterNumFailures), - handleValuePropertyChange[int](d, "task_auto_retry_attempts", &set.TaskAutoRetryAttempts, &unset.TaskAutoRetryAttempts), - handleValuePropertyChangeWithMapping[string](d, "user_task_managed_initial_warehouse_size", &set.UserTaskManagedInitialWarehouseSize, &unset.UserTaskManagedInitialWarehouseSize, sdk.ToWarehouseSize), - handleValuePropertyChange[int](d, "user_task_timeout_ms", &set.UserTaskTimeoutMs, &unset.UserTaskTimeoutMs), - handleValuePropertyChange[int](d, "user_task_minimum_trigger_interval_in_seconds", &set.UserTaskMinimumTriggerIntervalInSeconds, &unset.UserTaskMinimumTriggerIntervalInSeconds), - handleValuePropertyChange[bool](d, "quoted_identifiers_ignore_case", &set.QuotedIdentifiersIgnoreCase, &unset.QuotedIdentifiersIgnoreCase), - handleValuePropertyChange[bool](d, "enable_console_output", &set.EnableConsoleOutput, &unset.EnableConsoleOutput), - ) -} - func DeleteContextSchema(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { id := helpers.DecodeSnowflakeID(d.Id()).(sdk.DatabaseObjectIdentifier) client := meta.(*provider.Context).Client diff --git a/pkg/resources/schema_parameters.go b/pkg/resources/schema_parameters.go new file mode 100644 index 0000000000..4bd53f7de4 --- /dev/null +++ b/pkg/resources/schema_parameters.go @@ -0,0 +1,160 @@ +package resources + +import ( + "context" + "strconv" + "strings" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +var ( + schemaParametersSchema = make(map[string]*schema.Schema) + schemaParametersCustomDiff = ParametersCustomDiff( + schemaParametersProvider, + parameter[sdk.ObjectParameter]{sdk.ObjectParameterDataRetentionTimeInDays, valueTypeInt, sdk.ParameterTypeSchema}, + parameter[sdk.ObjectParameter]{sdk.ObjectParameterMaxDataExtensionTimeInDays, valueTypeInt, sdk.ParameterTypeSchema}, + parameter[sdk.ObjectParameter]{sdk.ObjectParameterExternalVolume, valueTypeString, sdk.ParameterTypeSchema}, + parameter[sdk.ObjectParameter]{sdk.ObjectParameterCatalog, valueTypeString, sdk.ParameterTypeSchema}, + parameter[sdk.ObjectParameter]{sdk.ObjectParameterReplaceInvalidCharacters, valueTypeBool, sdk.ParameterTypeSchema}, + parameter[sdk.ObjectParameter]{sdk.ObjectParameterDefaultDDLCollation, valueTypeString, sdk.ParameterTypeSchema}, + parameter[sdk.ObjectParameter]{sdk.ObjectParameterStorageSerializationPolicy, valueTypeString, sdk.ParameterTypeSchema}, + parameter[sdk.ObjectParameter]{sdk.ObjectParameterLogLevel, valueTypeString, sdk.ParameterTypeSchema}, + parameter[sdk.ObjectParameter]{sdk.ObjectParameterTraceLevel, valueTypeString, sdk.ParameterTypeSchema}, + parameter[sdk.ObjectParameter]{sdk.ObjectParameterSuspendTaskAfterNumFailures, valueTypeInt, sdk.ParameterTypeSchema}, + parameter[sdk.ObjectParameter]{sdk.ObjectParameterTaskAutoRetryAttempts, valueTypeInt, sdk.ParameterTypeSchema}, + parameter[sdk.ObjectParameter]{sdk.ObjectParameterUserTaskManagedInitialWarehouseSize, valueTypeString, sdk.ParameterTypeSchema}, + parameter[sdk.ObjectParameter]{sdk.ObjectParameterUserTaskTimeoutMs, valueTypeInt, sdk.ParameterTypeSchema}, + parameter[sdk.ObjectParameter]{sdk.ObjectParameterUserTaskMinimumTriggerIntervalInSeconds, valueTypeInt, sdk.ParameterTypeSchema}, + parameter[sdk.ObjectParameter]{sdk.ObjectParameterQuotedIdentifiersIgnoreCase, valueTypeBool, sdk.ParameterTypeSchema}, + parameter[sdk.ObjectParameter]{sdk.ObjectParameterEnableConsoleOutput, valueTypeBool, sdk.ParameterTypeSchema}, + parameter[sdk.ObjectParameter]{sdk.ObjectParameterPipeExecutionPaused, valueTypeBool, sdk.ParameterTypeSchema}, + ) +) + +func init() { + // TODO [SNOW-1348101][next PR]: merge this struct with the one in user parameters + type parameterDef struct { + Name sdk.ObjectParameter + Type schema.ValueType + Description string + } + additionalSchemaParameterFields := []parameterDef{ + {Name: sdk.ObjectParameterPipeExecutionPaused, Type: schema.TypeBool, Description: "Specifies whether to pause a running pipe, primarily in preparation for transferring ownership of the pipe to a different role."}, + } + + additionalSchemaParameters := make(map[string]*schema.Schema) + for _, field := range additionalSchemaParameterFields { + fieldName := strings.ToLower(string(field.Name)) + + additionalSchemaParameters[fieldName] = &schema.Schema{ + Type: field.Type, + Description: enrichWithReferenceToParameterDocs(field.Name, field.Description), + Computed: true, + Optional: true, + } + } + schemaParametersSchema = helpers.MergeMaps(databaseParametersSchema, additionalSchemaParameters) +} + +func schemaParametersProvider(ctx context.Context, d ResourceIdProvider, meta any) ([]*sdk.Parameter, error) { + return parametersProvider(ctx, d, meta.(*provider.Context), schemaParametersProviderFunc) +} + +func schemaParametersProviderFunc(c *sdk.Client) showParametersFunc[sdk.DatabaseObjectIdentifier] { + return c.Schemas.ShowParameters +} + +func handleSchemaParameterRead(d *schema.ResourceData, databaseParameters []*sdk.Parameter) diag.Diagnostics { + for _, parameter := range databaseParameters { + switch parameter.Key { + case + string(sdk.ObjectParameterDataRetentionTimeInDays), + string(sdk.ObjectParameterMaxDataExtensionTimeInDays), + string(sdk.ObjectParameterSuspendTaskAfterNumFailures), + string(sdk.ObjectParameterTaskAutoRetryAttempts), + string(sdk.ObjectParameterUserTaskTimeoutMs), + string(sdk.ObjectParameterUserTaskMinimumTriggerIntervalInSeconds): + value, err := strconv.Atoi(parameter.Value) + if err != nil { + return diag.FromErr(err) + } + if err := d.Set(strings.ToLower(parameter.Key), value); err != nil { + return diag.FromErr(err) + } + case + string(sdk.ObjectParameterExternalVolume), + string(sdk.ObjectParameterCatalog), + string(sdk.ObjectParameterDefaultDDLCollation), + string(sdk.ObjectParameterStorageSerializationPolicy), + string(sdk.ObjectParameterLogLevel), + string(sdk.ObjectParameterTraceLevel), + string(sdk.ObjectParameterUserTaskManagedInitialWarehouseSize): + if err := d.Set(strings.ToLower(parameter.Key), parameter.Value); err != nil { + return diag.FromErr(err) + } + case + string(sdk.ObjectParameterPipeExecutionPaused), + string(sdk.ObjectParameterReplaceInvalidCharacters), + string(sdk.ObjectParameterQuotedIdentifiersIgnoreCase), + string(sdk.ObjectParameterEnableConsoleOutput): + value, err := strconv.ParseBool(parameter.Value) + if err != nil { + return diag.FromErr(err) + } + if err := d.Set(strings.ToLower(parameter.Key), value); err != nil { + return diag.FromErr(err) + } + } + } + + return nil +} + +func handleSchemaParametersCreate(d *schema.ResourceData, createOpts *sdk.CreateSchemaOptions) diag.Diagnostics { + return JoinDiags( + handleParameterCreate(d, sdk.ObjectParameterDataRetentionTimeInDays, &createOpts.DataRetentionTimeInDays), + handleParameterCreate(d, sdk.ObjectParameterMaxDataExtensionTimeInDays, &createOpts.MaxDataExtensionTimeInDays), + handleParameterCreateWithMapping(d, sdk.ObjectParameterExternalVolume, &createOpts.ExternalVolume, stringToAccountObjectIdentifier), + handleParameterCreateWithMapping(d, sdk.ObjectParameterCatalog, &createOpts.Catalog, stringToAccountObjectIdentifier), + handleParameterCreate(d, sdk.ObjectParameterPipeExecutionPaused, &createOpts.PipeExecutionPaused), + handleParameterCreate(d, sdk.ObjectParameterReplaceInvalidCharacters, &createOpts.ReplaceInvalidCharacters), + handleParameterCreate(d, sdk.ObjectParameterDefaultDDLCollation, &createOpts.DefaultDDLCollation), + handleParameterCreateWithMapping(d, sdk.ObjectParameterStorageSerializationPolicy, &createOpts.StorageSerializationPolicy, sdk.ToStorageSerializationPolicy), + handleParameterCreateWithMapping(d, sdk.ObjectParameterLogLevel, &createOpts.LogLevel, sdk.ToLogLevel), + handleParameterCreateWithMapping(d, sdk.ObjectParameterTraceLevel, &createOpts.TraceLevel, sdk.ToTraceLevel), + handleParameterCreate(d, sdk.ObjectParameterSuspendTaskAfterNumFailures, &createOpts.SuspendTaskAfterNumFailures), + handleParameterCreate(d, sdk.ObjectParameterTaskAutoRetryAttempts, &createOpts.TaskAutoRetryAttempts), + handleParameterCreateWithMapping(d, sdk.ObjectParameterUserTaskManagedInitialWarehouseSize, &createOpts.UserTaskManagedInitialWarehouseSize, sdk.ToWarehouseSize), + handleParameterCreate(d, sdk.ObjectParameterUserTaskTimeoutMs, &createOpts.UserTaskTimeoutMs), + handleParameterCreate(d, sdk.ObjectParameterUserTaskMinimumTriggerIntervalInSeconds, &createOpts.UserTaskMinimumTriggerIntervalInSeconds), + handleParameterCreate(d, sdk.ObjectParameterQuotedIdentifiersIgnoreCase, &createOpts.QuotedIdentifiersIgnoreCase), + handleParameterCreate(d, sdk.ObjectParameterEnableConsoleOutput, &createOpts.EnableConsoleOutput), + ) +} + +func handleSchemaParametersChanges(d *schema.ResourceData, set *sdk.SchemaSet, unset *sdk.SchemaUnset) diag.Diagnostics { + return JoinDiags( + handleParameterUpdate(d, sdk.ObjectParameterDataRetentionTimeInDays, &set.DataRetentionTimeInDays, &unset.DataRetentionTimeInDays), + handleParameterUpdate(d, sdk.ObjectParameterMaxDataExtensionTimeInDays, &set.MaxDataExtensionTimeInDays, &unset.MaxDataExtensionTimeInDays), + handleParameterUpdateWithMapping(d, sdk.ObjectParameterExternalVolume, &set.ExternalVolume, &unset.ExternalVolume, stringToAccountObjectIdentifier), + handleParameterUpdateWithMapping(d, sdk.ObjectParameterCatalog, &set.Catalog, &unset.Catalog, stringToAccountObjectIdentifier), + handleParameterUpdate(d, sdk.ObjectParameterPipeExecutionPaused, &set.PipeExecutionPaused, &unset.PipeExecutionPaused), + handleParameterUpdate(d, sdk.ObjectParameterReplaceInvalidCharacters, &set.ReplaceInvalidCharacters, &unset.ReplaceInvalidCharacters), + handleParameterUpdate(d, sdk.ObjectParameterDefaultDDLCollation, &set.DefaultDDLCollation, &unset.DefaultDDLCollation), + handleParameterUpdateWithMapping(d, sdk.ObjectParameterStorageSerializationPolicy, &set.StorageSerializationPolicy, &unset.StorageSerializationPolicy, sdk.ToStorageSerializationPolicy), + handleParameterUpdateWithMapping(d, sdk.ObjectParameterLogLevel, &set.LogLevel, &unset.LogLevel, sdk.ToLogLevel), + handleParameterUpdateWithMapping(d, sdk.ObjectParameterTraceLevel, &set.TraceLevel, &unset.TraceLevel, sdk.ToTraceLevel), + handleParameterUpdate(d, sdk.ObjectParameterSuspendTaskAfterNumFailures, &set.SuspendTaskAfterNumFailures, &unset.SuspendTaskAfterNumFailures), + handleParameterUpdate(d, sdk.ObjectParameterTaskAutoRetryAttempts, &set.TaskAutoRetryAttempts, &unset.TaskAutoRetryAttempts), + handleParameterUpdateWithMapping(d, sdk.ObjectParameterUserTaskManagedInitialWarehouseSize, &set.UserTaskManagedInitialWarehouseSize, &unset.UserTaskManagedInitialWarehouseSize, sdk.ToWarehouseSize), + handleParameterUpdate(d, sdk.ObjectParameterUserTaskTimeoutMs, &set.UserTaskTimeoutMs, &unset.UserTaskTimeoutMs), + handleParameterUpdate(d, sdk.ObjectParameterUserTaskMinimumTriggerIntervalInSeconds, &set.UserTaskMinimumTriggerIntervalInSeconds, &unset.UserTaskMinimumTriggerIntervalInSeconds), + handleParameterUpdate(d, sdk.ObjectParameterQuotedIdentifiersIgnoreCase, &set.QuotedIdentifiersIgnoreCase, &unset.QuotedIdentifiersIgnoreCase), + handleParameterUpdate(d, sdk.ObjectParameterEnableConsoleOutput, &set.EnableConsoleOutput, &unset.EnableConsoleOutput), + ) +} diff --git a/pkg/resources/secondary_database.go b/pkg/resources/secondary_database.go index cae95c5ccd..111947a39e 100644 --- a/pkg/resources/secondary_database.go +++ b/pkg/resources/secondary_database.go @@ -45,8 +45,8 @@ func SecondaryDatabase() *schema.Resource { DeleteContext: DeleteSecondaryDatabase, Description: "A secondary database creates a replica of an existing primary database (i.e. a secondary database). For more information about database replication, see [Introduction to database replication across multiple accounts](https://docs.snowflake.com/en/user-guide/db-replication-intro).", - CustomizeDiff: DatabaseParametersCustomDiff, - Schema: helpers.MergeMaps(secondaryDatabaseSchema, DatabaseParametersSchema), + CustomizeDiff: databaseParametersCustomDiff, + Schema: helpers.MergeMaps(secondaryDatabaseSchema, databaseParametersSchema), Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, @@ -59,47 +59,15 @@ func CreateSecondaryDatabase(ctx context.Context, d *schema.ResourceData, meta a secondaryDatabaseId := sdk.NewAccountObjectIdentifier(d.Get("name").(string)) primaryDatabaseId := sdk.NewExternalObjectIdentifierFromFullyQualifiedName(d.Get("as_replica_of").(string)) - dataRetentionTimeInDays, - maxDataExtensionTimeInDays, - externalVolume, - catalog, - replaceInvalidCharacters, - defaultDDLCollation, - storageSerializationPolicy, - logLevel, - traceLevel, - suspendTaskAfterNumFailures, - taskAutoRetryAttempts, - userTaskManagedInitialWarehouseSize, - userTaskTimeoutMs, - userTaskMinimumTriggerIntervalInSeconds, - quotedIdentifiersIgnoreCase, - enableConsoleOutput, - err := GetAllDatabaseParameters(d) - if err != nil { - return diag.FromErr(err) + opts := &sdk.CreateSecondaryDatabaseOptions{ + Transient: GetConfigPropertyAsPointerAllowingZeroValue[bool](d, "is_transient"), + Comment: GetConfigPropertyAsPointerAllowingZeroValue[string](d, "comment"), + } + if parametersCreateDiags := handleSecondaryDatabaseParametersCreate(d, opts); len(parametersCreateDiags) > 0 { + return parametersCreateDiags } - err = client.Databases.CreateSecondary(ctx, secondaryDatabaseId, primaryDatabaseId, &sdk.CreateSecondaryDatabaseOptions{ - Transient: GetConfigPropertyAsPointerAllowingZeroValue[bool](d, "is_transient"), - DataRetentionTimeInDays: dataRetentionTimeInDays, - MaxDataExtensionTimeInDays: maxDataExtensionTimeInDays, - ExternalVolume: externalVolume, - Catalog: catalog, - ReplaceInvalidCharacters: replaceInvalidCharacters, - DefaultDDLCollation: defaultDDLCollation, - StorageSerializationPolicy: storageSerializationPolicy, - LogLevel: logLevel, - TraceLevel: traceLevel, - SuspendTaskAfterNumFailures: suspendTaskAfterNumFailures, - TaskAutoRetryAttempts: taskAutoRetryAttempts, - UserTaskManagedInitialWarehouseSize: userTaskManagedInitialWarehouseSize, - UserTaskTimeoutMs: userTaskTimeoutMs, - UserTaskMinimumTriggerIntervalInSeconds: userTaskMinimumTriggerIntervalInSeconds, - QuotedIdentifiersIgnoreCase: quotedIdentifiersIgnoreCase, - EnableConsoleOutput: enableConsoleOutput, - Comment: GetConfigPropertyAsPointerAllowingZeroValue[string](d, "comment"), - }) + err := client.Databases.CreateSecondary(ctx, secondaryDatabaseId, primaryDatabaseId, opts) if err != nil { return diag.FromErr(err) } @@ -128,7 +96,7 @@ func UpdateSecondaryDatabase(ctx context.Context, d *schema.ResourceData, meta a databaseSetRequest := new(sdk.DatabaseSet) databaseUnsetRequest := new(sdk.DatabaseUnset) - if updateParamDiags := HandleDatabaseParametersChanges(d, databaseSetRequest, databaseUnsetRequest); len(updateParamDiags) > 0 { + if updateParamDiags := handleDatabaseParametersChanges(d, databaseSetRequest, databaseUnsetRequest); len(updateParamDiags) > 0 { return updateParamDiags } @@ -221,16 +189,12 @@ func ReadSecondaryDatabase(ctx context.Context, d *schema.ResourceData, meta any return diag.FromErr(err) } - secondaryDatabaseParameters, err := client.Parameters.ShowParameters(ctx, &sdk.ShowParametersOptions{ - In: &sdk.ParametersIn{ - Database: secondaryDatabaseId, - }, - }) + secondaryDatabaseParameters, err := client.Databases.ShowParameters(ctx, secondaryDatabaseId) if err != nil { return diag.FromErr(err) } - if diags := HandleDatabaseParameterRead(d, secondaryDatabaseParameters); diags != nil { + if diags := handleDatabaseParameterRead(d, secondaryDatabaseParameters); diags != nil { return diags } diff --git a/pkg/resources/session_parameter_acceptance_test.go b/pkg/resources/session_parameter_acceptance_test.go index 1408297186..884fe6a95f 100644 --- a/pkg/resources/session_parameter_acceptance_test.go +++ b/pkg/resources/session_parameter_acceptance_test.go @@ -6,12 +6,17 @@ import ( acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/testenvs" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/tfversion" ) func TestAcc_SessionParameterWithUser(t *testing.T) { - prefix := acc.TestClient().Ids.Alpha() + _ = testenvs.GetOrSkipTest(t, testenvs.EnableAcceptance) + + user, userCleanup := acc.TestClient().User.CreateUser(t) + t.Cleanup(userCleanup) resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, @@ -22,11 +27,11 @@ func TestAcc_SessionParameterWithUser(t *testing.T) { CheckDestroy: nil, Steps: []resource.TestStep{ { - Config: sessionParameterWithUser(prefix, "BINARY_OUTPUT_FORMAT", "BASE64"), + Config: sessionParameterWithUser(user.ID(), "BINARY_OUTPUT_FORMAT", "BASE64"), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_session_parameter.p", "key", "BINARY_OUTPUT_FORMAT"), resource.TestCheckResourceAttr("snowflake_session_parameter.p", "value", "BASE64"), - resource.TestCheckResourceAttr("snowflake_session_parameter.p", "user", prefix), + resource.TestCheckResourceAttr("snowflake_session_parameter.p", "user", user.ID().Name()), resource.TestCheckResourceAttr("snowflake_session_parameter.p", "on_account", "false"), ), }, @@ -55,19 +60,14 @@ func TestAcc_SessionParameterOnAccount(t *testing.T) { }) } -func sessionParameterWithUser(user, key, value string) string { - s := ` -resource "snowflake_user" "u" { - name = "%s" -} - +func sessionParameterWithUser(userId sdk.AccountObjectIdentifier, key, value string) string { + return fmt.Sprintf(` resource "snowflake_session_parameter" "p" { - key = "%s" - value = "%s" - user = snowflake_user.u.name + key = "%[2]s" + value = "%[3]s" + user = %[1]s } -` - return fmt.Sprintf(s, user, key, value) +`, userId.FullyQualifiedName(), key, value) } func sessionParameterOnAccount(key, value string) string { diff --git a/pkg/resources/shared_database.go b/pkg/resources/shared_database.go index 73ee42be03..5f290b05c5 100644 --- a/pkg/resources/shared_database.go +++ b/pkg/resources/shared_database.go @@ -46,7 +46,7 @@ func SharedDatabase() *schema.Resource { DeleteContext: DeleteSharedDatabase, Description: "A shared database creates a database from a share provided by another Snowflake account. For more information about shares, see [Introduction to Secure Data Sharing](https://docs.snowflake.com/en/user-guide/data-sharing-intro).", - Schema: helpers.MergeMaps(sharedDatabaseSchema, SharedDatabaseParametersSchema), + Schema: helpers.MergeMaps(sharedDatabaseSchema, sharedDatabaseParametersSchema), Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, @@ -59,44 +59,16 @@ func CreateSharedDatabase(ctx context.Context, d *schema.ResourceData, meta any) id := sdk.NewAccountObjectIdentifier(d.Get("name").(string)) externalShareId := sdk.NewExternalObjectIdentifierFromFullyQualifiedName(d.Get("from_share").(string)) - _, _, externalVolume, - catalog, - replaceInvalidCharacters, - defaultDDLCollation, - storageSerializationPolicy, - logLevel, - traceLevel, - suspendTaskAfterNumFailures, - taskAutoRetryAttempts, - userTaskManagedInitialWarehouseSize, - userTaskTimeoutMs, - userTaskMinimumTriggerIntervalInSeconds, - quotedIdentifiersIgnoreCase, - enableConsoleOutput, - err := GetAllDatabaseParameters(d) - if err != nil { - return diag.FromErr(err) - } - - err = client.Databases.CreateShared(ctx, id, externalShareId, &sdk.CreateSharedDatabaseOptions{ + opts := &sdk.CreateSharedDatabaseOptions{ // TODO(SNOW-1325381) // Transient: GetPropertyAsPointer[bool](d, "is_transient"), - ExternalVolume: externalVolume, - Catalog: catalog, - ReplaceInvalidCharacters: replaceInvalidCharacters, - DefaultDDLCollation: defaultDDLCollation, - StorageSerializationPolicy: storageSerializationPolicy, - LogLevel: logLevel, - TraceLevel: traceLevel, - SuspendTaskAfterNumFailures: suspendTaskAfterNumFailures, - TaskAutoRetryAttempts: taskAutoRetryAttempts, - UserTaskManagedInitialWarehouseSize: userTaskManagedInitialWarehouseSize, - UserTaskTimeoutMs: userTaskTimeoutMs, - UserTaskMinimumTriggerIntervalInSeconds: userTaskMinimumTriggerIntervalInSeconds, - QuotedIdentifiersIgnoreCase: quotedIdentifiersIgnoreCase, - EnableConsoleOutput: enableConsoleOutput, - Comment: GetConfigPropertyAsPointerAllowingZeroValue[string](d, "comment"), - }) + Comment: GetConfigPropertyAsPointerAllowingZeroValue[string](d, "comment"), + } + if parametersCreateDiags := handleSharedDatabaseParametersCreate(d, opts); len(parametersCreateDiags) > 0 { + return parametersCreateDiags + } + + err := client.Databases.CreateShared(ctx, id, externalShareId, opts) if err != nil { return diag.FromErr(err) } @@ -186,16 +158,12 @@ func ReadSharedDatabase(ctx context.Context, d *schema.ResourceData, meta any) d return diag.FromErr(err) } - databaseParameters, err := client.Parameters.ShowParameters(ctx, &sdk.ShowParametersOptions{ - In: &sdk.ParametersIn{ - Database: id, - }, - }) + databaseParameters, err := client.Databases.ShowParameters(ctx, id) if err != nil { return diag.FromErr(err) } - if diags := HandleDatabaseParameterRead(d, databaseParameters); diags != nil { + if diags := handleDatabaseParameterRead(d, databaseParameters); diags != nil { return diags } diff --git a/pkg/resources/user.go b/pkg/resources/user.go index be02013c98..6eb8009266 100644 --- a/pkg/resources/user.go +++ b/pkg/resources/user.go @@ -3,15 +3,17 @@ package resources import ( "context" "errors" + "fmt" "log" "strings" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) var userSchema = map[string]*schema.Schema{ @@ -126,23 +128,47 @@ var userSchema = map[string]*schema.Schema{ // MINS_TO_BYPASS_MFA = // DISABLE_MFA = TRUE | FALSE // MINS_TO_BYPASS_NETWORK POLICY = + ShowOutputAttributeName: { + Type: schema.TypeList, + Computed: true, + Description: "Outputs the result of `SHOW USER` for the given user.", + Elem: &schema.Resource{ + Schema: schemas.ShowUserSchema, + }, + }, + ParametersAttributeName: { + Type: schema.TypeList, + Computed: true, + Description: "Outputs the result of `SHOW PARAMETERS IN USER` for the given user.", + Elem: &schema.Resource{ + Schema: schemas.ShowUserParametersSchema, + }, + }, } func User() *schema.Resource { return &schema.Resource{ - Create: CreateUser, - Read: ReadUser, - Update: UpdateUser, - Delete: DeleteUser, + CreateContext: CreateUser, + UpdateContext: UpdateUser, + ReadContext: GetReadUserFunc(true), + DeleteContext: DeleteUser, - Schema: userSchema, + Schema: helpers.MergeMaps(userSchema, userParametersSchema), Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, + + CustomizeDiff: customdiff.All( + // TODO [SNOW-1348101]: fill after adding all the attributes + // ComputedIfAnyAttributeChanged(ShowOutputAttributeName), + // TODO [SNOW-1348101]: use list from user parameters definition instead listing all here + ComputedIfAnyAttributeChanged(ParametersAttributeName, strings.ToLower(string(sdk.UserParameterAbortDetachedQuery)), strings.ToLower(string(sdk.UserParameterAutocommit)), strings.ToLower(string(sdk.UserParameterBinaryInputFormat)), strings.ToLower(string(sdk.UserParameterBinaryOutputFormat)), strings.ToLower(string(sdk.UserParameterClientMemoryLimit)), strings.ToLower(string(sdk.UserParameterClientMetadataRequestUseConnectionCtx)), strings.ToLower(string(sdk.UserParameterClientPrefetchThreads)), strings.ToLower(string(sdk.UserParameterClientResultChunkSize)), strings.ToLower(string(sdk.UserParameterClientResultColumnCaseInsensitive)), strings.ToLower(string(sdk.UserParameterClientSessionKeepAlive)), strings.ToLower(string(sdk.UserParameterClientSessionKeepAliveHeartbeatFrequency)), strings.ToLower(string(sdk.UserParameterClientTimestampTypeMapping)), strings.ToLower(string(sdk.UserParameterDateInputFormat)), strings.ToLower(string(sdk.UserParameterDateOutputFormat)), strings.ToLower(string(sdk.UserParameterEnableUnloadPhysicalTypeOptimization)), strings.ToLower(string(sdk.UserParameterErrorOnNondeterministicMerge)), strings.ToLower(string(sdk.UserParameterErrorOnNondeterministicUpdate)), strings.ToLower(string(sdk.UserParameterGeographyOutputFormat)), strings.ToLower(string(sdk.UserParameterGeometryOutputFormat)), strings.ToLower(string(sdk.UserParameterJdbcTreatDecimalAsInt)), strings.ToLower(string(sdk.UserParameterJdbcTreatTimestampNtzAsUtc)), strings.ToLower(string(sdk.UserParameterJdbcUseSessionTimezone)), strings.ToLower(string(sdk.UserParameterJsonIndent)), strings.ToLower(string(sdk.UserParameterLockTimeout)), strings.ToLower(string(sdk.UserParameterLogLevel)), strings.ToLower(string(sdk.UserParameterMultiStatementCount)), strings.ToLower(string(sdk.UserParameterNoorderSequenceAsDefault)), strings.ToLower(string(sdk.UserParameterOdbcTreatDecimalAsInt)), strings.ToLower(string(sdk.UserParameterQueryTag)), strings.ToLower(string(sdk.UserParameterQuotedIdentifiersIgnoreCase)), strings.ToLower(string(sdk.UserParameterRowsPerResultset)), strings.ToLower(string(sdk.UserParameterS3StageVpceDnsName)), strings.ToLower(string(sdk.UserParameterSearchPath)), strings.ToLower(string(sdk.UserParameterSimulatedDataSharingConsumer)), strings.ToLower(string(sdk.UserParameterStatementQueuedTimeoutInSeconds)), strings.ToLower(string(sdk.UserParameterStatementTimeoutInSeconds)), strings.ToLower(string(sdk.UserParameterStrictJsonOutput)), strings.ToLower(string(sdk.UserParameterTimestampDayIsAlways24h)), strings.ToLower(string(sdk.UserParameterTimestampInputFormat)), strings.ToLower(string(sdk.UserParameterTimestampLtzOutputFormat)), strings.ToLower(string(sdk.UserParameterTimestampNtzOutputFormat)), strings.ToLower(string(sdk.UserParameterTimestampOutputFormat)), strings.ToLower(string(sdk.UserParameterTimestampTypeMapping)), strings.ToLower(string(sdk.UserParameterTimestampTzOutputFormat)), strings.ToLower(string(sdk.UserParameterTimezone)), strings.ToLower(string(sdk.UserParameterTimeInputFormat)), strings.ToLower(string(sdk.UserParameterTimeOutputFormat)), strings.ToLower(string(sdk.UserParameterTraceLevel)), strings.ToLower(string(sdk.UserParameterTransactionAbortOnError)), strings.ToLower(string(sdk.UserParameterTransactionDefaultIsolationLevel)), strings.ToLower(string(sdk.UserParameterTwoDigitCenturyStart)), strings.ToLower(string(sdk.UserParameterUnsupportedDdlAction)), strings.ToLower(string(sdk.UserParameterUseCachedResult)), strings.ToLower(string(sdk.UserParameterWeekOfYearPolicy)), strings.ToLower(string(sdk.UserParameterWeekStart)), strings.ToLower(string(sdk.UserParameterEnableUnredactedQuerySyntaxError)), strings.ToLower(string(sdk.UserParameterNetworkPolicy)), strings.ToLower(string(sdk.UserParameterPreventUnloadToInternalStages))), + userParametersCustomDiff, + ), } } -func CreateUser(d *schema.ResourceData, meta interface{}) error { +func CreateUser(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { client := meta.(*provider.Context).Client opts := &sdk.CreateUserOptions{ @@ -151,9 +177,12 @@ func CreateUser(d *schema.ResourceData, meta interface{}) error { SessionParameters: &sdk.SessionParameters{}, } name := d.Get("name").(string) - ctx := context.Background() objectIdentifier := sdk.NewAccountObjectIdentifier(name) + if parametersCreateDiags := handleUserParametersCreate(d, opts); len(parametersCreateDiags) > 0 { + return parametersCreateDiags + } + if loginName, ok := d.GetOk("login_name"); ok { opts.ObjectProperties.LoginName = sdk.String(loginName.(string)) } @@ -174,7 +203,7 @@ func CreateUser(d *schema.ResourceData, meta interface{}) error { if defaultNamespace, ok := d.GetOk("default_namespace"); ok { defaultNamespaceId, err := helpers.DecodeSnowflakeParameterID(defaultNamespace.(string)) if err != nil { - return err + return diag.FromErr(err) } opts.ObjectProperties.DefaultNamespace = sdk.Pointer(defaultNamespaceId) } @@ -213,83 +242,119 @@ func CreateUser(d *schema.ResourceData, meta interface{}) error { } err := client.Users.Create(ctx, objectIdentifier, opts) if err != nil { - return err + return diag.FromErr(err) } d.SetId(helpers.EncodeSnowflakeID(objectIdentifier)) - return ReadUser(d, meta) + return GetReadUserFunc(false)(ctx, d, meta) } -func ReadUser(d *schema.ResourceData, meta interface{}) error { - client := meta.(*provider.Context).Client - // We use User.Describe instead of User.Show because the "SHOW USERS ..." command - // requires the "MANAGE GRANTS" global privilege - objectIdentifier := helpers.DecodeSnowflakeID(d.Id()).(sdk.AccountObjectIdentifier) - ctx := context.Background() - user, err := client.Users.Describe(ctx, objectIdentifier) - if err != nil { - if errors.Is(err, sdk.ErrObjectNotExistOrAuthorized) { - log.Printf("[DEBUG] user (%s) not found or we are not authorized. Err: %s", d.Id(), err) - d.SetId("") - return nil +func GetReadUserFunc(withExternalChangesMarking bool) schema.ReadContextFunc { + return func(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + client := meta.(*provider.Context).Client + // We use User.Describe instead of User.Show because the "SHOW USERS ..." command + // requires the "MANAGE GRANTS" global privilege + id := helpers.DecodeSnowflakeID(d.Id()).(sdk.AccountObjectIdentifier) + user, err := client.Users.Describe(ctx, id) + if err != nil { + if errors.Is(err, sdk.ErrObjectNotExistOrAuthorized) { + log.Printf("[DEBUG] user (%s) not found or we are not authorized. Err: %s", d.Id(), err) + d.SetId("") + return diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Warning, + Summary: "Failed to query user. Marking the resource as removed.", + Detail: fmt.Sprintf("User: %s, Err: %s", id.FullyQualifiedName(), err), + }, + } + } + return diag.FromErr(err) } - return err - } - if err := setStringProperty(d, "name", user.Name); err != nil { - return err - } - if err := setStringProperty(d, "comment", user.Comment); err != nil { - return err - } - if err := setStringProperty(d, "login_name", user.LoginName); err != nil { - return err - } - if err := setBoolProperty(d, "disabled", user.Disabled); err != nil { - return err - } - if err := setStringProperty(d, "default_role", user.DefaultRole); err != nil { - return err - } + u, err := client.Users.ShowByID(ctx, id) + if err != nil { + if errors.Is(err, sdk.ErrObjectNotFound) { + d.SetId("") + return diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Warning, + Summary: "Failed to query user. Marking the resource as removed.", + Detail: fmt.Sprintf("User: %s, Err: %s", id.FullyQualifiedName(), err), + }, + } + } + return diag.FromErr(err) + } - var defaultSecondaryRoles []string - if user.DefaultSecondaryRoles != nil && len(user.DefaultSecondaryRoles.Value) > 0 { - defaultRoles, _ := strings.CutPrefix(user.DefaultSecondaryRoles.Value, "[\"") - defaultRoles, _ = strings.CutSuffix(defaultRoles, "\"]") - defaultSecondaryRoles = strings.Split(defaultRoles, ",") - } - if err = d.Set("default_secondary_roles", defaultSecondaryRoles); err != nil { - return err - } - if err := setStringProperty(d, "default_namespace", user.DefaultNamespace); err != nil { - return err - } - if err := setStringProperty(d, "default_warehouse", user.DefaultWarehouse); err != nil { - return err - } - if user.RsaPublicKeyFp != nil { - if err = d.Set("has_rsa_public_key", user.RsaPublicKeyFp.Value != ""); err != nil { - return err + userParameters, err := client.Users.ShowParameters(ctx, id) + if err != nil { + return diag.FromErr(err) } + + if err := setStringProperty(d, "name", user.Name); err != nil { + return diag.FromErr(err) + } + if err := setStringProperty(d, "comment", user.Comment); err != nil { + return diag.FromErr(err) + } + if err := setStringProperty(d, "login_name", user.LoginName); err != nil { + return diag.FromErr(err) + } + if err := setBoolProperty(d, "disabled", user.Disabled); err != nil { + return diag.FromErr(err) + } + if err := setStringProperty(d, "default_role", user.DefaultRole); err != nil { + return diag.FromErr(err) + } + + var defaultSecondaryRoles []string + if user.DefaultSecondaryRoles != nil && len(user.DefaultSecondaryRoles.Value) > 0 { + defaultSecondaryRoles = sdk.ParseCommaSeparatedStringArray(user.DefaultSecondaryRoles.Value, true) + } + if err = d.Set("default_secondary_roles", defaultSecondaryRoles); err != nil { + return diag.FromErr(err) + } + if err := setStringProperty(d, "default_namespace", user.DefaultNamespace); err != nil { + return diag.FromErr(err) + } + if err := setStringProperty(d, "default_warehouse", user.DefaultWarehouse); err != nil { + return diag.FromErr(err) + } + if user.RsaPublicKeyFp != nil { + if err = d.Set("has_rsa_public_key", user.RsaPublicKeyFp.Value != ""); err != nil { + return diag.FromErr(err) + } + } + if err := setStringProperty(d, "email", user.Email); err != nil { + return diag.FromErr(err) + } + if err := setStringProperty(d, "display_name", user.DisplayName); err != nil { + return diag.FromErr(err) + } + if err := setStringProperty(d, "first_name", user.FirstName); err != nil { + return diag.FromErr(err) + } + if err := setStringProperty(d, "last_name", user.LastName); err != nil { + return diag.FromErr(err) + } + + if diags := handleUserParameterRead(d, userParameters); diags != nil { + return diags + } + + if err = d.Set(ShowOutputAttributeName, []map[string]any{schemas.UserToSchema(u)}); err != nil { + return diag.FromErr(err) + } + + if err = d.Set(ParametersAttributeName, []map[string]any{schemas.UserParametersToSchema(userParameters)}); err != nil { + return diag.FromErr(err) + } + + return nil } - if err := setStringProperty(d, "email", user.Email); err != nil { - return err - } - if err := setStringProperty(d, "display_name", user.DisplayName); err != nil { - return err - } - if err := setStringProperty(d, "first_name", user.FirstName); err != nil { - return err - } - if err := setStringProperty(d, "last_name", user.LastName); err != nil { - return err - } - return nil } -func UpdateUser(d *schema.ResourceData, meta interface{}) error { +func UpdateUser(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { client := meta.(*provider.Context).Client - - ctx := context.Background() id := helpers.DecodeSnowflakeID(d.Id()).(sdk.AccountObjectIdentifier) if d.HasChange("name") { @@ -299,7 +364,7 @@ func UpdateUser(d *schema.ResourceData, meta interface{}) error { NewName: newID, }) if err != nil { - return err + return diag.FromErr(err) } d.SetId(helpers.EncodeSnowflakeID(newID)) @@ -344,7 +409,7 @@ func UpdateUser(d *schema.ResourceData, meta interface{}) error { _, n := d.GetChange("default_namespace") defaultNamespaceId, err := helpers.DecodeSnowflakeParameterID(n.(string)) if err != nil { - return err + return diag.FromErr(err) } alterOptions.Set.ObjectProperties.DefaultNamespace = sdk.Pointer(defaultNamespaceId) } @@ -399,26 +464,71 @@ func UpdateUser(d *schema.ResourceData, meta interface{}) error { _, n := d.GetChange("last_name") alterOptions.Set.ObjectProperties.LastName = sdk.String(n.(string)) } + if runSet { err := client.Users.Alter(ctx, id, alterOptions) if err != nil { - return err + return diag.FromErr(err) + } + } + + set := &sdk.UserSet{ + SessionParameters: &sdk.SessionParameters{}, + ObjectParameters: &sdk.UserObjectParameters{}, + } + unset := &sdk.UserUnset{ + SessionParameters: &sdk.SessionParametersUnset{}, + ObjectParameters: &sdk.UserObjectParametersUnset{}, + } + if updateParamDiags := handleUserParametersUpdate(d, set, unset); len(updateParamDiags) > 0 { + return updateParamDiags + } + + if (*set.SessionParameters != sdk.SessionParameters{} || *set.ObjectParameters != sdk.UserObjectParameters{}) { + err := client.Users.Alter(ctx, id, &sdk.AlterUserOptions{ + Set: set, + }) + if err != nil { + return diag.FromErr(err) + } + } + // unset is split into two because: + // 1. this is how it's written in the docs https://docs.snowflake.com/en/sql-reference/sql/alter-user#syntax + // 2. current implementation of sdk.UserUnset makes distinction between user and session parameters, + // so adding a comma between them is not trivial in the current SQL builder implementation + if (*unset.SessionParameters != sdk.SessionParametersUnset{}) { + err := client.Users.Alter(ctx, id, &sdk.AlterUserOptions{ + Unset: &sdk.UserUnset{ + SessionParameters: unset.SessionParameters, + }, + }) + if err != nil { + return diag.FromErr(err) + } + } + if (*unset.ObjectParameters != sdk.UserObjectParametersUnset{}) { + err := client.Users.Alter(ctx, id, &sdk.AlterUserOptions{ + Unset: &sdk.UserUnset{ + ObjectParameters: unset.ObjectParameters, + }, + }) + if err != nil { + return diag.FromErr(err) } } - return ReadUser(d, meta) + return GetReadUserFunc(false)(ctx, d, meta) } -func DeleteUser(d *schema.ResourceData, meta interface{}) error { +func DeleteUser(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { client := meta.(*provider.Context).Client - ctx := context.Background() - objectIdentifier := helpers.DecodeSnowflakeID(d.Id()).(sdk.AccountObjectIdentifier) + id := helpers.DecodeSnowflakeID(d.Id()).(sdk.AccountObjectIdentifier) - err := client.Users.Drop(ctx, objectIdentifier, &sdk.DropUserOptions{ + err := client.Users.Drop(ctx, id, &sdk.DropUserOptions{ IfExists: sdk.Bool(true), }) if err != nil { - return err + return diag.FromErr(err) } d.SetId("") diff --git a/pkg/resources/user_acceptance_test.go b/pkg/resources/user_acceptance_test.go index 6d25f80609..00e0de720a 100644 --- a/pkg/resources/user_acceptance_test.go +++ b/pkg/resources/user_acceptance_test.go @@ -10,8 +10,15 @@ import ( acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert/objectparametersassert" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert/resourceparametersassert" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/config" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/config/model" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers/random" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/testenvs" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/provider/resources" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/testhelpers" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/plancheck" @@ -258,3 +265,304 @@ func TestAcc_User_issue2058(t *testing.T) { }, }) } + +func TestAcc_User_AllParameters(t *testing.T) { + _ = testenvs.GetOrSkipTest(t, testenvs.EnableAcceptance) + networkPolicy, networkPolicyCleanup := acc.TestClient().NetworkPolicy.CreateNetworkPolicy(t) + t.Cleanup(networkPolicyCleanup) + + userId := acc.TestClient().Ids.RandomAccountObjectIdentifier() + + userModel := model.User("u", userId.Name()) + userModelWithAllParametersSet := model.User("u", userId.Name()). + WithAbortDetachedQuery(true). + WithAutocommit(false). + WithBinaryInputFormatEnum(sdk.BinaryInputFormatUTF8). + WithBinaryOutputFormatEnum(sdk.BinaryOutputFormatBase64). + WithClientMemoryLimit(1024). + WithClientMetadataRequestUseConnectionCtx(true). + WithClientPrefetchThreads(2). + WithClientResultChunkSize(48). + WithClientResultColumnCaseInsensitive(true). + WithClientSessionKeepAlive(true). + WithClientSessionKeepAliveHeartbeatFrequency(2400). + WithClientTimestampTypeMappingEnum(sdk.ClientTimestampTypeMappingNtz). + WithDateInputFormat("YYYY-MM-DD"). + WithDateOutputFormat("YY-MM-DD"). + WithEnableUnloadPhysicalTypeOptimization(false). + WithErrorOnNondeterministicMerge(false). + WithErrorOnNondeterministicUpdate(true). + WithGeographyOutputFormatEnum(sdk.GeographyOutputFormatWKB). + WithGeometryOutputFormatEnum(sdk.GeometryOutputFormatWKB). + WithJdbcTreatDecimalAsInt(false). + WithJdbcTreatTimestampNtzAsUtc(true). + WithJdbcUseSessionTimezone(false). + WithJsonIndent(4). + WithLockTimeout(21222). + WithLogLevelEnum(sdk.LogLevelError). + WithMultiStatementCount(0). + WithNoorderSequenceAsDefault(false). + WithOdbcTreatDecimalAsInt(true). + WithQueryTag("some_tag"). + WithQuotedIdentifiersIgnoreCase(true). + WithRowsPerResultset(2). + WithS3StageVpceDnsName("vpce-id.s3.region.vpce.amazonaws.com"). + WithSearchPath("$public, $current"). + WithSimulatedDataSharingConsumer("some_consumer"). + WithStatementQueuedTimeoutInSeconds(10). + WithStatementTimeoutInSeconds(10). + WithStrictJsonOutput(true). + WithTimestampDayIsAlways24h(true). + WithTimestampInputFormat("YYYY-MM-DD"). + WithTimestampLtzOutputFormat("YYYY-MM-DD HH24:MI:SS"). + WithTimestampNtzOutputFormat("YYYY-MM-DD HH24:MI:SS"). + WithTimestampOutputFormat("YYYY-MM-DD HH24:MI:SS"). + WithTimestampTypeMappingEnum(sdk.TimestampTypeMappingLtz). + WithTimestampTzOutputFormat("YYYY-MM-DD HH24:MI:SS"). + WithTimezone("Europe/Warsaw"). + WithTimeInputFormat("HH24:MI"). + WithTimeOutputFormat("HH24:MI"). + WithTraceLevelEnum(sdk.TraceLevelOnEvent). + WithTransactionAbortOnError(true). + WithTransactionDefaultIsolationLevelEnum(sdk.TransactionDefaultIsolationLevelReadCommitted). + WithTwoDigitCenturyStart(1980). + WithUnsupportedDdlActionEnum(sdk.UnsupportedDDLActionFail). + WithUseCachedResult(false). + WithWeekOfYearPolicy(1). + WithWeekStart(1). + WithEnableUnredactedQuerySyntaxError(true). + WithNetworkPolicyId(networkPolicy.ID()). + WithPreventUnloadToInternalStages(true) + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + PreCheck: func() { acc.TestAccPreCheck(t) }, + CheckDestroy: acc.CheckDestroy(t, resources.User), + Steps: []resource.TestStep{ + // create with default values for all the parameters + { + Config: config.FromModel(t, userModel), + Check: assert.AssertThat(t, + objectparametersassert.UserParameters(t, userId). + HasAllDefaults(). + HasAllDefaultsExplicit(), + // TODO [SNOW-1348101][next PR]: check setting parameters on resource level (such assertions not generated yet) + // resourceparametersassert.UserResourceParameters(t, "u").Has(), + ), + }, + // import when no parameter set + { + ResourceName: "snowflake_user.u", + ImportState: true, + ImportStateVerify: true, + // TODO [SNOW-1348101][next PR]: check setting parameters on resource level (such assertions not generated yet) + // ImportStateCheck: assert.AssertThatImport(t), + }, + // set all parameters + { + Config: config.FromModel(t, userModelWithAllParametersSet), + Check: assert.AssertThat(t, + objectparametersassert.UserParameters(t, userId). + HasAbortDetachedQuery(true). + HasAutocommit(false). + HasBinaryInputFormat(sdk.BinaryInputFormatUTF8). + HasBinaryOutputFormat(sdk.BinaryOutputFormatBase64). + HasClientMemoryLimit(1024). + HasClientMetadataRequestUseConnectionCtx(true). + HasClientPrefetchThreads(2). + HasClientResultChunkSize(48). + HasClientResultColumnCaseInsensitive(true). + HasClientSessionKeepAlive(true). + HasClientSessionKeepAliveHeartbeatFrequency(2400). + HasClientTimestampTypeMapping(sdk.ClientTimestampTypeMappingNtz). + HasDateInputFormat("YYYY-MM-DD"). + HasDateOutputFormat("YY-MM-DD"). + HasEnableUnloadPhysicalTypeOptimization(false). + HasErrorOnNondeterministicMerge(false). + HasErrorOnNondeterministicUpdate(true). + HasGeographyOutputFormat(sdk.GeographyOutputFormatWKB). + HasGeometryOutputFormat(sdk.GeometryOutputFormatWKB). + HasJdbcTreatDecimalAsInt(false). + HasJdbcTreatTimestampNtzAsUtc(true). + HasJdbcUseSessionTimezone(false). + HasJsonIndent(4). + HasLockTimeout(21222). + HasLogLevel(sdk.LogLevelError). + HasMultiStatementCount(0). + HasNoorderSequenceAsDefault(false). + HasOdbcTreatDecimalAsInt(true). + HasQueryTag("some_tag"). + HasQuotedIdentifiersIgnoreCase(true). + HasRowsPerResultset(2). + HasS3StageVpceDnsName("vpce-id.s3.region.vpce.amazonaws.com"). + HasSearchPath("$public, $current"). + HasSimulatedDataSharingConsumer("some_consumer"). + HasStatementQueuedTimeoutInSeconds(10). + HasStatementTimeoutInSeconds(10). + HasStrictJsonOutput(true). + HasTimestampDayIsAlways24h(true). + HasTimestampInputFormat("YYYY-MM-DD"). + HasTimestampLtzOutputFormat("YYYY-MM-DD HH24:MI:SS"). + HasTimestampNtzOutputFormat("YYYY-MM-DD HH24:MI:SS"). + HasTimestampOutputFormat("YYYY-MM-DD HH24:MI:SS"). + HasTimestampTypeMapping(sdk.TimestampTypeMappingLtz). + HasTimestampTzOutputFormat("YYYY-MM-DD HH24:MI:SS"). + HasTimezone("Europe/Warsaw"). + HasTimeInputFormat("HH24:MI"). + HasTimeOutputFormat("HH24:MI"). + HasTraceLevel(sdk.TraceLevelOnEvent). + HasTransactionAbortOnError(true). + HasTransactionDefaultIsolationLevel(sdk.TransactionDefaultIsolationLevelReadCommitted). + HasTwoDigitCenturyStart(1980). + HasUnsupportedDdlAction(sdk.UnsupportedDDLActionFail). + HasUseCachedResult(false). + HasWeekOfYearPolicy(1). + HasWeekStart(1). + HasEnableUnredactedQuerySyntaxError(true). + HasNetworkPolicy(networkPolicy.ID().Name()). + HasPreventUnloadToInternalStages(true), + resourceparametersassert.UserResourceParameters(t, "snowflake_user.u"). + HasAbortDetachedQuery(true). + HasAutocommit(false). + HasBinaryInputFormat(sdk.BinaryInputFormatUTF8). + HasBinaryOutputFormat(sdk.BinaryOutputFormatBase64). + HasClientMemoryLimit(1024). + HasClientMetadataRequestUseConnectionCtx(true). + HasClientPrefetchThreads(2). + HasClientResultChunkSize(48). + HasClientResultColumnCaseInsensitive(true). + HasClientSessionKeepAlive(true). + HasClientSessionKeepAliveHeartbeatFrequency(2400). + HasClientTimestampTypeMapping(sdk.ClientTimestampTypeMappingNtz). + HasDateInputFormat("YYYY-MM-DD"). + HasDateOutputFormat("YY-MM-DD"). + HasEnableUnloadPhysicalTypeOptimization(false). + HasErrorOnNondeterministicMerge(false). + HasErrorOnNondeterministicUpdate(true). + HasGeographyOutputFormat(sdk.GeographyOutputFormatWKB). + HasGeometryOutputFormat(sdk.GeometryOutputFormatWKB). + HasJdbcTreatDecimalAsInt(false). + HasJdbcTreatTimestampNtzAsUtc(true). + HasJdbcUseSessionTimezone(false). + HasJsonIndent(4). + HasLockTimeout(21222). + HasLogLevel(sdk.LogLevelError). + HasMultiStatementCount(0). + HasNoorderSequenceAsDefault(false). + HasOdbcTreatDecimalAsInt(true). + HasQueryTag("some_tag"). + HasQuotedIdentifiersIgnoreCase(true). + HasRowsPerResultset(2). + HasS3StageVpceDnsName("vpce-id.s3.region.vpce.amazonaws.com"). + HasSearchPath("$public, $current"). + HasSimulatedDataSharingConsumer("some_consumer"). + HasStatementQueuedTimeoutInSeconds(10). + HasStatementTimeoutInSeconds(10). + HasStrictJsonOutput(true). + HasTimestampDayIsAlways24h(true). + HasTimestampInputFormat("YYYY-MM-DD"). + HasTimestampLtzOutputFormat("YYYY-MM-DD HH24:MI:SS"). + HasTimestampNtzOutputFormat("YYYY-MM-DD HH24:MI:SS"). + HasTimestampOutputFormat("YYYY-MM-DD HH24:MI:SS"). + HasTimestampTypeMapping(sdk.TimestampTypeMappingLtz). + HasTimestampTzOutputFormat("YYYY-MM-DD HH24:MI:SS"). + HasTimezone("Europe/Warsaw"). + HasTimeInputFormat("HH24:MI"). + HasTimeOutputFormat("HH24:MI"). + HasTraceLevel(sdk.TraceLevelOnEvent). + HasTransactionAbortOnError(true). + HasTransactionDefaultIsolationLevel(sdk.TransactionDefaultIsolationLevelReadCommitted). + HasTwoDigitCenturyStart(1980). + HasUnsupportedDdlAction(sdk.UnsupportedDDLActionFail). + HasUseCachedResult(false). + HasWeekOfYearPolicy(1). + HasWeekStart(1). + HasEnableUnredactedQuerySyntaxError(true). + HasNetworkPolicy(networkPolicy.ID().Name()). + HasPreventUnloadToInternalStages(true), + ), + }, + // import when all parameters set + { + ResourceName: "snowflake_user.u", + ImportState: true, + ImportStateVerify: true, + ImportStateCheck: assert.AssertThatImport(t, + resourceparametersassert.ImportedUserResourceParameters(t, userId.Name()). + HasAbortDetachedQuery(true). + HasAutocommit(false). + HasBinaryInputFormat(sdk.BinaryInputFormatUTF8). + HasBinaryOutputFormat(sdk.BinaryOutputFormatBase64). + HasClientMemoryLimit(1024). + HasClientMetadataRequestUseConnectionCtx(true). + HasClientPrefetchThreads(2). + HasClientResultChunkSize(48). + HasClientResultColumnCaseInsensitive(true). + HasClientSessionKeepAlive(true). + HasClientSessionKeepAliveHeartbeatFrequency(2400). + HasClientTimestampTypeMapping(sdk.ClientTimestampTypeMappingNtz). + HasDateInputFormat("YYYY-MM-DD"). + HasDateOutputFormat("YY-MM-DD"). + HasEnableUnloadPhysicalTypeOptimization(false). + HasErrorOnNondeterministicMerge(false). + HasErrorOnNondeterministicUpdate(true). + HasGeographyOutputFormat(sdk.GeographyOutputFormatWKB). + HasGeometryOutputFormat(sdk.GeometryOutputFormatWKB). + HasJdbcTreatDecimalAsInt(false). + HasJdbcTreatTimestampNtzAsUtc(true). + HasJdbcUseSessionTimezone(false). + HasJsonIndent(4). + HasLockTimeout(21222). + HasLogLevel(sdk.LogLevelError). + HasMultiStatementCount(0). + HasNoorderSequenceAsDefault(false). + HasOdbcTreatDecimalAsInt(true). + HasQueryTag("some_tag"). + HasQuotedIdentifiersIgnoreCase(true). + HasRowsPerResultset(2). + HasS3StageVpceDnsName("vpce-id.s3.region.vpce.amazonaws.com"). + HasSearchPath("$public, $current"). + HasSimulatedDataSharingConsumer("some_consumer"). + HasStatementQueuedTimeoutInSeconds(10). + HasStatementTimeoutInSeconds(10). + HasStrictJsonOutput(true). + HasTimestampDayIsAlways24h(true). + HasTimestampInputFormat("YYYY-MM-DD"). + HasTimestampLtzOutputFormat("YYYY-MM-DD HH24:MI:SS"). + HasTimestampNtzOutputFormat("YYYY-MM-DD HH24:MI:SS"). + HasTimestampOutputFormat("YYYY-MM-DD HH24:MI:SS"). + HasTimestampTypeMapping(sdk.TimestampTypeMappingLtz). + HasTimestampTzOutputFormat("YYYY-MM-DD HH24:MI:SS"). + HasTimezone("Europe/Warsaw"). + HasTimeInputFormat("HH24:MI"). + HasTimeOutputFormat("HH24:MI"). + HasTraceLevel(sdk.TraceLevelOnEvent). + HasTransactionAbortOnError(true). + HasTransactionDefaultIsolationLevel(sdk.TransactionDefaultIsolationLevelReadCommitted). + HasTwoDigitCenturyStart(1980). + HasUnsupportedDdlAction(sdk.UnsupportedDDLActionFail). + HasUseCachedResult(false). + HasWeekOfYearPolicy(1). + HasWeekStart(1). + HasEnableUnredactedQuerySyntaxError(true). + HasNetworkPolicy(networkPolicy.ID().Name()). + HasPreventUnloadToInternalStages(true), + ), + }, + // unset all the parameters + { + Config: config.FromModel(t, userModel), + Check: assert.AssertThat(t, + objectparametersassert.UserParameters(t, userId). + HasAllDefaults(). + HasAllDefaultsExplicit(), + // TODO [SNOW-1348101][next PR]: check setting parameters on resource level (such assertions not generated yet) + // resourceparametersassert.UserResourceParameters(t, "u").Has(), + ), + }, + }, + }) +} diff --git a/pkg/resources/user_parameters.go b/pkg/resources/user_parameters.go new file mode 100644 index 0000000000..4ea60ed208 --- /dev/null +++ b/pkg/resources/user_parameters.go @@ -0,0 +1,392 @@ +package resources + +import ( + "context" + "strconv" + "strings" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +var ( + userParametersSchema = make(map[string]*schema.Schema) + userParametersCustomDiff = ParametersCustomDiff( + userParametersProvider, + parameter[sdk.UserParameter]{sdk.UserParameterAbortDetachedQuery, valueTypeBool, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterAutocommit, valueTypeBool, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterBinaryInputFormat, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterBinaryOutputFormat, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterClientMemoryLimit, valueTypeInt, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterClientMetadataRequestUseConnectionCtx, valueTypeBool, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterClientPrefetchThreads, valueTypeInt, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterClientResultChunkSize, valueTypeInt, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterClientResultColumnCaseInsensitive, valueTypeBool, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterClientSessionKeepAlive, valueTypeBool, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterClientSessionKeepAliveHeartbeatFrequency, valueTypeInt, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterClientTimestampTypeMapping, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterDateInputFormat, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterDateOutputFormat, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterEnableUnloadPhysicalTypeOptimization, valueTypeBool, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterErrorOnNondeterministicMerge, valueTypeBool, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterErrorOnNondeterministicUpdate, valueTypeBool, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterGeographyOutputFormat, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterGeometryOutputFormat, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterJdbcTreatDecimalAsInt, valueTypeBool, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterJdbcTreatTimestampNtzAsUtc, valueTypeBool, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterJdbcUseSessionTimezone, valueTypeBool, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterJsonIndent, valueTypeInt, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterLockTimeout, valueTypeInt, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterLogLevel, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterMultiStatementCount, valueTypeInt, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterNoorderSequenceAsDefault, valueTypeBool, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterOdbcTreatDecimalAsInt, valueTypeBool, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterQueryTag, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterQuotedIdentifiersIgnoreCase, valueTypeBool, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterRowsPerResultset, valueTypeInt, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterS3StageVpceDnsName, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterSearchPath, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterSimulatedDataSharingConsumer, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterStatementQueuedTimeoutInSeconds, valueTypeInt, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterStatementTimeoutInSeconds, valueTypeInt, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterStrictJsonOutput, valueTypeBool, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterTimestampDayIsAlways24h, valueTypeBool, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterTimestampInputFormat, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterTimestampLtzOutputFormat, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterTimestampNtzOutputFormat, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterTimestampOutputFormat, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterTimestampTypeMapping, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterTimestampTzOutputFormat, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterTimezone, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterTimeInputFormat, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterTimeOutputFormat, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterTraceLevel, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterTransactionAbortOnError, valueTypeBool, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterTransactionDefaultIsolationLevel, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterTwoDigitCenturyStart, valueTypeInt, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterUnsupportedDdlAction, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterUseCachedResult, valueTypeBool, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterWeekOfYearPolicy, valueTypeInt, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterWeekStart, valueTypeInt, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterEnableUnredactedQuerySyntaxError, valueTypeBool, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterNetworkPolicy, valueTypeString, sdk.ParameterTypeUser}, + parameter[sdk.UserParameter]{sdk.UserParameterPreventUnloadToInternalStages, valueTypeBool, sdk.ParameterTypeUser}, + ) +) + +func init() { + // TODO [SNOW-1348101][next PR]: reuse this struct + type parameterDef struct { + Name sdk.UserParameter + Type schema.ValueType + Description string + // DiffSuppress schema.SchemaDiffSuppressFunc + // ValidateDiag schema.SchemaValidateDiagFunc + } + // TODO [SNOW-1348101][next PR]: move to the SDK + userParameterFields := []parameterDef{ + // session params + {Name: sdk.UserParameterAbortDetachedQuery, Type: schema.TypeBool, Description: "Specifies the action that Snowflake performs for in-progress queries if connectivity is lost due to abrupt termination of a session (e.g. network outage, browser termination, service interruption)."}, + {Name: sdk.UserParameterAutocommit, Type: schema.TypeBool, Description: "Specifies whether autocommit is enabled for the session. Autocommit determines whether a DML statement, when executed without an active transaction, is automatically committed after the statement successfully completes. For more information, see [Transactions](https://docs.snowflake.com/en/sql-reference/transactions)."}, + {Name: sdk.UserParameterBinaryInputFormat, Type: schema.TypeString, Description: "The format of VARCHAR values passed as input to VARCHAR-to-BINARY conversion functions. For more information, see [Binary input and output](https://docs.snowflake.com/en/sql-reference/binary-input-output)."}, + {Name: sdk.UserParameterBinaryOutputFormat, Type: schema.TypeString, Description: "The format for VARCHAR values returned as output by BINARY-to-VARCHAR conversion functions. For more information, see [Binary input and output](https://docs.snowflake.com/en/sql-reference/binary-input-output)."}, + {Name: sdk.UserParameterClientMemoryLimit, Type: schema.TypeInt, Description: "Parameter that specifies the maximum amount of memory the JDBC driver or ODBC driver should use for the result set from queries (in MB)."}, + {Name: sdk.UserParameterClientMetadataRequestUseConnectionCtx, Type: schema.TypeBool, Description: "For specific ODBC functions and JDBC methods, this parameter can change the default search scope from all databases/schemas to the current database/schema. The narrower search typically returns fewer rows and executes more quickly."}, + {Name: sdk.UserParameterClientPrefetchThreads, Type: schema.TypeInt, Description: "Parameter that specifies the number of threads used by the client to pre-fetch large result sets. The driver will attempt to honor the parameter value, but defines the minimum and maximum values (depending on your system’s resources) to improve performance."}, + {Name: sdk.UserParameterClientResultChunkSize, Type: schema.TypeInt, Description: "Parameter that specifies the maximum size of each set (or chunk) of query results to download (in MB). The JDBC driver downloads query results in chunks."}, + {Name: sdk.UserParameterClientResultColumnCaseInsensitive, Type: schema.TypeBool, Description: "Parameter that indicates whether to match column name case-insensitively in ResultSet.get* methods in JDBC."}, + {Name: sdk.UserParameterClientSessionKeepAlive, Type: schema.TypeBool, Description: "Parameter that indicates whether to force a user to log in again after a period of inactivity in the session."}, + {Name: sdk.UserParameterClientSessionKeepAliveHeartbeatFrequency, Type: schema.TypeInt, Description: "Number of seconds in-between client attempts to update the token for the session."}, + {Name: sdk.UserParameterClientTimestampTypeMapping, Type: schema.TypeString, Description: "Specifies the [TIMESTAMP_* variation](https://docs.snowflake.com/en/sql-reference/data-types-datetime.html#label-datatypes-timestamp-variations) to use when binding timestamp variables for JDBC or ODBC applications that use the bind API to load data."}, + {Name: sdk.UserParameterDateInputFormat, Type: schema.TypeString, Description: "Specifies the input format for the DATE data type. For more information, see [Date and time input and output formats](https://docs.snowflake.com/en/sql-reference/date-time-input-output)."}, + {Name: sdk.UserParameterDateOutputFormat, Type: schema.TypeString, Description: "Specifies the display format for the DATE data type. For more information, see [Date and time input and output formats](https://docs.snowflake.com/en/sql-reference/date-time-input-output)."}, + {Name: sdk.UserParameterEnableUnloadPhysicalTypeOptimization, Type: schema.TypeBool, Description: "Specifies whether to set the schema for unloaded Parquet files based on the logical column data types (i.e. the types in the unload SQL query or source table) or on the unloaded column values (i.e. the smallest data types and precision that support the values in the output columns of the unload SQL statement or source table)."}, + {Name: sdk.UserParameterErrorOnNondeterministicMerge, Type: schema.TypeBool, Description: "Specifies whether to return an error when the [MERGE](https://docs.snowflake.com/en/sql-reference/sql/merge) command is used to update or delete a target row that joins multiple source rows and the system cannot determine the action to perform on the target row."}, + {Name: sdk.UserParameterErrorOnNondeterministicUpdate, Type: schema.TypeBool, Description: "Specifies whether to return an error when the [UPDATE](https://docs.snowflake.com/en/sql-reference/sql/update) command is used to update a target row that joins multiple source rows and the system cannot determine the action to perform on the target row."}, + {Name: sdk.UserParameterGeographyOutputFormat, Type: schema.TypeString, Description: "Display format for [GEOGRAPHY values](https://docs.snowflake.com/en/sql-reference/data-types-geospatial.html#label-data-types-geography)."}, + {Name: sdk.UserParameterGeometryOutputFormat, Type: schema.TypeString, Description: "Display format for [GEOMETRY values](https://docs.snowflake.com/en/sql-reference/data-types-geospatial.html#label-data-types-geometry)."}, + {Name: sdk.UserParameterJdbcTreatDecimalAsInt, Type: schema.TypeBool, Description: "Specifies how JDBC processes columns that have a scale of zero (0)."}, + {Name: sdk.UserParameterJdbcTreatTimestampNtzAsUtc, Type: schema.TypeBool, Description: "Specifies how JDBC processes TIMESTAMP_NTZ values."}, + {Name: sdk.UserParameterJdbcUseSessionTimezone, Type: schema.TypeBool, Description: "Specifies whether the JDBC Driver uses the time zone of the JVM or the time zone of the session (specified by the [TIMEZONE](https://docs.snowflake.com/en/sql-reference/parameters#label-timezone) parameter) for the getDate(), getTime(), and getTimestamp() methods of the ResultSet class."}, + {Name: sdk.UserParameterJsonIndent, Type: schema.TypeInt, Description: "Specifies the number of blank spaces to indent each new element in JSON output in the session. Also specifies whether to insert newline characters after each element."}, + {Name: sdk.UserParameterLockTimeout, Type: schema.TypeInt, Description: "Number of seconds to wait while trying to lock a resource, before timing out and aborting the statement."}, + {Name: sdk.UserParameterLogLevel, Type: schema.TypeString, Description: "Specifies the severity level of messages that should be ingested and made available in the active event table. Messages at the specified level (and at more severe levels) are ingested. For more information about log levels, see [Setting log level](https://docs.snowflake.com/en/developer-guide/logging-tracing/logging-log-level)."}, + {Name: sdk.UserParameterMultiStatementCount, Type: schema.TypeInt, Description: "Number of statements to execute when using the multi-statement capability."}, + {Name: sdk.UserParameterNoorderSequenceAsDefault, Type: schema.TypeBool, Description: "Specifies whether the ORDER or NOORDER property is set by default when you create a new sequence or add a new table column. The ORDER and NOORDER properties determine whether or not the values are generated for the sequence or auto-incremented column in [increasing or decreasing order](https://docs.snowflake.com/en/user-guide/querying-sequences.html#label-querying-sequences-increasing-values)."}, + {Name: sdk.UserParameterOdbcTreatDecimalAsInt, Type: schema.TypeBool, Description: "Specifies how ODBC processes columns that have a scale of zero (0)."}, + {Name: sdk.UserParameterQueryTag, Type: schema.TypeString, Description: "Optional string that can be used to tag queries and other SQL statements executed within a session. The tags are displayed in the output of the [QUERY_HISTORY, QUERY_HISTORY_BY_*](https://docs.snowflake.com/en/sql-reference/functions/query_history) functions."}, + {Name: sdk.UserParameterQuotedIdentifiersIgnoreCase, Type: schema.TypeBool, Description: "Specifies whether letters in double-quoted object identifiers are stored and resolved as uppercase letters. By default, Snowflake preserves the case of alphabetic characters when storing and resolving double-quoted identifiers (see [Identifier resolution](https://docs.snowflake.com/en/sql-reference/identifiers-syntax.html#label-identifier-casing)). You can use this parameter in situations in which [third-party applications always use double quotes around identifiers](https://docs.snowflake.com/en/sql-reference/identifiers-syntax.html#label-identifier-casing-parameter)."}, + {Name: sdk.UserParameterRowsPerResultset, Type: schema.TypeInt, Description: "Specifies the maximum number of rows returned in a result set. A value of 0 specifies no maximum."}, + {Name: sdk.UserParameterS3StageVpceDnsName, Type: schema.TypeString, Description: "Specifies the DNS name of an Amazon S3 interface endpoint. Requests sent to the internal stage of an account via [AWS PrivateLink for Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/privatelink-interface-endpoints.html) use this endpoint to connect. For more information, see [Accessing Internal stages with dedicated interface endpoints](https://docs.snowflake.com/en/user-guide/private-internal-stages-aws.html#label-aws-privatelink-internal-stage-network-isolation)."}, + {Name: sdk.UserParameterSearchPath, Type: schema.TypeString, Description: "Specifies the path to search to resolve unqualified object names in queries. For more information, see [Name resolution in queries](https://docs.snowflake.com/en/sql-reference/name-resolution.html#label-object-name-resolution-search-path). Comma-separated list of identifiers. An identifier can be a fully or partially qualified schema name."}, + {Name: sdk.UserParameterSimulatedDataSharingConsumer, Type: schema.TypeString, Description: "Specifies the name of a consumer account to simulate for testing/validating shared data, particularly shared secure views. When this parameter is set in a session, shared views return rows as if executed in the specified consumer account rather than the provider account. For more information, see [Introduction to Secure Data Sharing](https://docs.snowflake.com/en/user-guide/data-sharing-intro) and [Working with shares](https://docs.snowflake.com/en/user-guide/data-sharing-provider)."}, + {Name: sdk.UserParameterStatementQueuedTimeoutInSeconds, Type: schema.TypeInt, Description: "Amount of time, in seconds, a SQL statement (query, DDL, DML, etc.) remains queued for a warehouse before it is canceled by the system. This parameter can be used in conjunction with the [MAX_CONCURRENCY_LEVEL](https://docs.snowflake.com/en/sql-reference/parameters#label-max-concurrency-level) parameter to ensure a warehouse is never backlogged."}, + {Name: sdk.UserParameterStatementTimeoutInSeconds, Type: schema.TypeInt, Description: "Amount of time, in seconds, after which a running SQL statement (query, DDL, DML, etc.) is canceled by the system."}, + {Name: sdk.UserParameterStrictJsonOutput, Type: schema.TypeBool, Description: "This parameter specifies whether JSON output in a session is compatible with the general standard (as described by [http://json.org](http://json.org)). By design, Snowflake allows JSON input that contains non-standard values; however, these non-standard values might result in Snowflake outputting JSON that is incompatible with other platforms and languages. This parameter, when enabled, ensures that Snowflake outputs valid/compatible JSON."}, + {Name: sdk.UserParameterTimestampDayIsAlways24h, Type: schema.TypeBool, Description: "Specifies whether the [DATEADD](https://docs.snowflake.com/en/sql-reference/functions/dateadd) function (and its aliases) always consider a day to be exactly 24 hours for expressions that span multiple days."}, + {Name: sdk.UserParameterTimestampInputFormat, Type: schema.TypeString, Description: "Specifies the input format for the TIMESTAMP data type alias. For more information, see [Date and time input and output formats](https://docs.snowflake.com/en/sql-reference/date-time-input-output). Any valid, supported timestamp format or AUTO (AUTO specifies that Snowflake attempts to automatically detect the format of timestamps stored in the system during the session)."}, + {Name: sdk.UserParameterTimestampLtzOutputFormat, Type: schema.TypeString, Description: "Specifies the display format for the TIMESTAMP_LTZ data type. If no format is specified, defaults to [TIMESTAMP_OUTPUT_FORMAT](https://docs.snowflake.com/en/sql-reference/parameters#label-timestamp-output-format). For more information, see [Date and time input and output formats](https://docs.snowflake.com/en/sql-reference/date-time-input-output)."}, + {Name: sdk.UserParameterTimestampNtzOutputFormat, Type: schema.TypeString, Description: "Specifies the display format for the TIMESTAMP_NTZ data type."}, + {Name: sdk.UserParameterTimestampOutputFormat, Type: schema.TypeString, Description: "Specifies the display format for the TIMESTAMP data type alias. For more information, see [Date and time input and output formats](https://docs.snowflake.com/en/sql-reference/date-time-input-output)."}, + {Name: sdk.UserParameterTimestampTypeMapping, Type: schema.TypeString, Description: "Specifies the TIMESTAMP_* variation that the TIMESTAMP data type alias maps to."}, + {Name: sdk.UserParameterTimestampTzOutputFormat, Type: schema.TypeString, Description: "Specifies the display format for the TIMESTAMP_TZ data type. If no format is specified, defaults to [TIMESTAMP_OUTPUT_FORMAT](https://docs.snowflake.com/en/sql-reference/parameters#label-timestamp-output-format). For more information, see [Date and time input and output formats](https://docs.snowflake.com/en/sql-reference/date-time-input-output)."}, + {Name: sdk.UserParameterTimezone, Type: schema.TypeString, Description: "Specifies the time zone for the session. You can specify a [time zone name](https://data.iana.org/time-zones/tzdb-2021a/zone1970.tab) or a [link name](https://data.iana.org/time-zones/tzdb-2021a/backward) from release 2021a of the [IANA Time Zone Database](https://www.iana.org/time-zones) (e.g. America/Los_Angeles, Europe/London, UTC, Etc/GMT, etc.)."}, + {Name: sdk.UserParameterTimeInputFormat, Type: schema.TypeString, Description: "Specifies the input format for the TIME data type. For more information, see [Date and time input and output formats](https://docs.snowflake.com/en/sql-reference/date-time-input-output). Any valid, supported time format or AUTO (AUTO specifies that Snowflake attempts to automatically detect the format of times stored in the system during the session)."}, + {Name: sdk.UserParameterTimeOutputFormat, Type: schema.TypeString, Description: "Specifies the display format for the TIME data type. For more information, see [Date and time input and output formats](https://docs.snowflake.com/en/sql-reference/date-time-input-output)."}, + {Name: sdk.UserParameterTraceLevel, Type: schema.TypeString, Description: "Controls how trace events are ingested into the event table. For more information about trace levels, see [Setting trace level](https://docs.snowflake.com/en/developer-guide/logging-tracing/tracing-trace-level)."}, + {Name: sdk.UserParameterTransactionAbortOnError, Type: schema.TypeBool, Description: "Specifies the action to perform when a statement issued within a non-autocommit transaction returns with an error."}, + {Name: sdk.UserParameterTransactionDefaultIsolationLevel, Type: schema.TypeString, Description: "Specifies the isolation level for transactions in the user session."}, + {Name: sdk.UserParameterTwoDigitCenturyStart, Type: schema.TypeInt, Description: "Specifies the “century start” year for 2-digit years (i.e. the earliest year such dates can represent). This parameter prevents ambiguous dates when importing or converting data with the `YY` date format component (i.e. years represented as 2 digits)."}, + {Name: sdk.UserParameterUnsupportedDdlAction, Type: schema.TypeString, Description: "Determines if an unsupported (i.e. non-default) value specified for a constraint property returns an error."}, + {Name: sdk.UserParameterUseCachedResult, Type: schema.TypeBool, Description: "Specifies whether to reuse persisted query results, if available, when a matching query is submitted."}, + {Name: sdk.UserParameterWeekOfYearPolicy, Type: schema.TypeInt, Description: "Specifies how the weeks in a given year are computed. `0`: The semantics used are equivalent to the ISO semantics, in which a week belongs to a given year if at least 4 days of that week are in that year. `1`: January 1 is included in the first week of the year and December 31 is included in the last week of the year."}, + {Name: sdk.UserParameterWeekStart, Type: schema.TypeInt, Description: "Specifies the first day of the week (used by week-related date functions). `0`: Legacy Snowflake behavior is used (i.e. ISO-like semantics). `1` (Monday) to `7` (Sunday): All the week-related functions use weeks that start on the specified day of the week."}, + {Name: sdk.UserParameterEnableUnredactedQuerySyntaxError, Type: schema.TypeBool, Description: "Controls whether query text is redacted if a SQL query fails due to a syntax or parsing error. If `FALSE`, the content of a failed query is redacted in the views, pages, and functions that provide a query history. Only users with a role that is granted or inherits the AUDIT privilege can set the ENABLE_UNREDACTED_QUERY_SYNTAX_ERROR parameter. When using the ALTER USER command to set the parameter to `TRUE` for a particular user, modify the user that you want to see the query text, not the user who executed the query (if those are different users)."}, + {Name: sdk.UserParameterNetworkPolicy, Type: schema.TypeString, Description: "Specifies the network policy to enforce for your account. Network policies enable restricting access to your account based on users’ IP address. For more details, see [Controlling network traffic with network policies](https://docs.snowflake.com/en/user-guide/network-policies). Any existing network policy (created using [CREATE NETWORK POLICY](https://docs.snowflake.com/en/sql-reference/sql/create-network-policy))."}, + {Name: sdk.UserParameterPreventUnloadToInternalStages, Type: schema.TypeBool, Description: "Specifies whether to prevent data unload operations to internal (Snowflake) stages using [COPY INTO ](https://docs.snowflake.com/en/sql-reference/sql/copy-into-location) statements."}, + } + + // TODO [SNOW-1348101][next PR]: extract this method after moving to SDK + for _, field := range userParameterFields { + fieldName := strings.ToLower(string(field.Name)) + + userParametersSchema[fieldName] = &schema.Schema{ + Type: field.Type, + Description: enrichWithReferenceToParameterDocs(field.Name, field.Description), + Computed: true, + Optional: true, + // TODO [SNOW-1348101][next PR]: uncomment and fill out + // ValidateDiagFunc: field.ValidateDiag, + // DiffSuppressFunc: field.DiffSuppress, + } + } +} + +func userParametersProvider(ctx context.Context, d ResourceIdProvider, meta any) ([]*sdk.Parameter, error) { + return parametersProvider(ctx, d, meta.(*provider.Context), userParametersProviderFunc) +} + +func userParametersProviderFunc(c *sdk.Client) showParametersFunc[sdk.AccountObjectIdentifier] { + return c.Users.ShowParameters +} + +// TODO [SNOW-1348101][next PR]: make generic based on type definition +func handleUserParameterRead(d *schema.ResourceData, warehouseParameters []*sdk.Parameter) diag.Diagnostics { + for _, p := range warehouseParameters { + switch p.Key { + case + string(sdk.UserParameterClientMemoryLimit), + string(sdk.UserParameterClientPrefetchThreads), + string(sdk.UserParameterClientResultChunkSize), + string(sdk.UserParameterClientSessionKeepAliveHeartbeatFrequency), + string(sdk.UserParameterJsonIndent), + string(sdk.UserParameterLockTimeout), + string(sdk.UserParameterMultiStatementCount), + string(sdk.UserParameterRowsPerResultset), + string(sdk.UserParameterStatementQueuedTimeoutInSeconds), + string(sdk.UserParameterStatementTimeoutInSeconds), + string(sdk.UserParameterTwoDigitCenturyStart), + string(sdk.UserParameterWeekOfYearPolicy), + string(sdk.UserParameterWeekStart): + value, err := strconv.Atoi(p.Value) + if err != nil { + return diag.FromErr(err) + } + if err := d.Set(strings.ToLower(p.Key), value); err != nil { + return diag.FromErr(err) + } + case + string(sdk.UserParameterBinaryInputFormat), + string(sdk.UserParameterBinaryOutputFormat), + string(sdk.UserParameterClientTimestampTypeMapping), + string(sdk.UserParameterDateInputFormat), + string(sdk.UserParameterDateOutputFormat), + string(sdk.UserParameterGeographyOutputFormat), + string(sdk.UserParameterGeometryOutputFormat), + string(sdk.UserParameterLogLevel), + string(sdk.UserParameterQueryTag), + string(sdk.UserParameterS3StageVpceDnsName), + string(sdk.UserParameterSearchPath), + string(sdk.UserParameterSimulatedDataSharingConsumer), + string(sdk.UserParameterTimestampInputFormat), + string(sdk.UserParameterTimestampLtzOutputFormat), + string(sdk.UserParameterTimestampNtzOutputFormat), + string(sdk.UserParameterTimestampOutputFormat), + string(sdk.UserParameterTimestampTypeMapping), + string(sdk.UserParameterTimestampTzOutputFormat), + string(sdk.UserParameterTimezone), + string(sdk.UserParameterTimeInputFormat), + string(sdk.UserParameterTimeOutputFormat), + string(sdk.UserParameterTraceLevel), + string(sdk.UserParameterTransactionDefaultIsolationLevel), + string(sdk.UserParameterUnsupportedDdlAction), + string(sdk.UserParameterNetworkPolicy): + if err := d.Set(strings.ToLower(p.Key), p.Value); err != nil { + return diag.FromErr(err) + } + case + string(sdk.UserParameterAbortDetachedQuery), + string(sdk.UserParameterAutocommit), + string(sdk.UserParameterClientMetadataRequestUseConnectionCtx), + string(sdk.UserParameterClientResultColumnCaseInsensitive), + string(sdk.UserParameterClientSessionKeepAlive), + string(sdk.UserParameterEnableUnloadPhysicalTypeOptimization), + string(sdk.UserParameterErrorOnNondeterministicMerge), + string(sdk.UserParameterErrorOnNondeterministicUpdate), + string(sdk.UserParameterJdbcTreatDecimalAsInt), + string(sdk.UserParameterJdbcTreatTimestampNtzAsUtc), + string(sdk.UserParameterJdbcUseSessionTimezone), + string(sdk.UserParameterNoorderSequenceAsDefault), + string(sdk.UserParameterOdbcTreatDecimalAsInt), + string(sdk.UserParameterQuotedIdentifiersIgnoreCase), + string(sdk.UserParameterStrictJsonOutput), + string(sdk.UserParameterTimestampDayIsAlways24h), + string(sdk.UserParameterTransactionAbortOnError), + string(sdk.UserParameterUseCachedResult), + string(sdk.UserParameterEnableUnredactedQuerySyntaxError), + string(sdk.UserParameterPreventUnloadToInternalStages): + value, err := strconv.ParseBool(p.Value) + if err != nil { + return diag.FromErr(err) + } + if err := d.Set(strings.ToLower(p.Key), value); err != nil { + return diag.FromErr(err) + } + } + } + + return nil +} + +// TODO [SNOW-1348330]: consider using SessionParameters#setParam during parameters rework +// (because currently setParam already is able to set the right parameter based on the string value input, +// but GetConfigPropertyAsPointerAllowingZeroValue receives typed value, +// so this would be unnecessary running in circles) +// TODO [SNOW-1348101]: include mappers in the param definition (after moving it to the SDK: identity versus concrete) +func handleUserParametersCreate(d *schema.ResourceData, createOpts *sdk.CreateUserOptions) diag.Diagnostics { + return JoinDiags( + handleParameterCreate(d, sdk.UserParameterAbortDetachedQuery, &createOpts.SessionParameters.AbortDetachedQuery), + handleParameterCreate(d, sdk.UserParameterAutocommit, &createOpts.SessionParameters.Autocommit), + handleParameterCreateWithMapping(d, sdk.UserParameterBinaryInputFormat, &createOpts.SessionParameters.BinaryInputFormat, stringToStringEnumProvider(sdk.ToBinaryInputFormat)), + handleParameterCreateWithMapping(d, sdk.UserParameterBinaryOutputFormat, &createOpts.SessionParameters.BinaryOutputFormat, stringToStringEnumProvider(sdk.ToBinaryOutputFormat)), + handleParameterCreate(d, sdk.UserParameterClientMemoryLimit, &createOpts.SessionParameters.ClientMemoryLimit), + handleParameterCreate(d, sdk.UserParameterClientMetadataRequestUseConnectionCtx, &createOpts.SessionParameters.ClientMetadataRequestUseConnectionCtx), + handleParameterCreate(d, sdk.UserParameterClientPrefetchThreads, &createOpts.SessionParameters.ClientPrefetchThreads), + handleParameterCreate(d, sdk.UserParameterClientResultChunkSize, &createOpts.SessionParameters.ClientResultChunkSize), + handleParameterCreate(d, sdk.UserParameterClientResultColumnCaseInsensitive, &createOpts.SessionParameters.ClientResultColumnCaseInsensitive), + handleParameterCreate(d, sdk.UserParameterClientSessionKeepAlive, &createOpts.SessionParameters.ClientSessionKeepAlive), + handleParameterCreate(d, sdk.UserParameterClientSessionKeepAliveHeartbeatFrequency, &createOpts.SessionParameters.ClientSessionKeepAliveHeartbeatFrequency), + handleParameterCreateWithMapping(d, sdk.UserParameterClientTimestampTypeMapping, &createOpts.SessionParameters.ClientTimestampTypeMapping, stringToStringEnumProvider(sdk.ToClientTimestampTypeMapping)), + handleParameterCreate(d, sdk.UserParameterDateInputFormat, &createOpts.SessionParameters.DateInputFormat), + handleParameterCreate(d, sdk.UserParameterDateOutputFormat, &createOpts.SessionParameters.DateOutputFormat), + handleParameterCreate(d, sdk.UserParameterEnableUnloadPhysicalTypeOptimization, &createOpts.SessionParameters.EnableUnloadPhysicalTypeOptimization), + handleParameterCreate(d, sdk.UserParameterErrorOnNondeterministicMerge, &createOpts.SessionParameters.ErrorOnNondeterministicMerge), + handleParameterCreate(d, sdk.UserParameterErrorOnNondeterministicUpdate, &createOpts.SessionParameters.ErrorOnNondeterministicUpdate), + handleParameterCreateWithMapping(d, sdk.UserParameterGeographyOutputFormat, &createOpts.SessionParameters.GeographyOutputFormat, stringToStringEnumProvider(sdk.ToGeographyOutputFormat)), + handleParameterCreateWithMapping(d, sdk.UserParameterGeometryOutputFormat, &createOpts.SessionParameters.GeometryOutputFormat, stringToStringEnumProvider(sdk.ToGeometryOutputFormat)), + handleParameterCreate(d, sdk.UserParameterJdbcTreatDecimalAsInt, &createOpts.SessionParameters.JdbcTreatDecimalAsInt), + handleParameterCreate(d, sdk.UserParameterJdbcTreatTimestampNtzAsUtc, &createOpts.SessionParameters.JdbcTreatTimestampNtzAsUtc), + handleParameterCreate(d, sdk.UserParameterJdbcUseSessionTimezone, &createOpts.SessionParameters.JdbcUseSessionTimezone), + handleParameterCreate(d, sdk.UserParameterJsonIndent, &createOpts.SessionParameters.JSONIndent), + handleParameterCreate(d, sdk.UserParameterLockTimeout, &createOpts.SessionParameters.LockTimeout), + handleParameterCreateWithMapping(d, sdk.UserParameterLogLevel, &createOpts.SessionParameters.LogLevel, stringToStringEnumProvider(sdk.ToLogLevel)), + handleParameterCreate(d, sdk.UserParameterMultiStatementCount, &createOpts.SessionParameters.MultiStatementCount), + handleParameterCreate(d, sdk.UserParameterNoorderSequenceAsDefault, &createOpts.SessionParameters.NoorderSequenceAsDefault), + handleParameterCreate(d, sdk.UserParameterOdbcTreatDecimalAsInt, &createOpts.SessionParameters.OdbcTreatDecimalAsInt), + handleParameterCreate(d, sdk.UserParameterQueryTag, &createOpts.SessionParameters.QueryTag), + handleParameterCreate(d, sdk.UserParameterQuotedIdentifiersIgnoreCase, &createOpts.SessionParameters.QuotedIdentifiersIgnoreCase), + handleParameterCreate(d, sdk.UserParameterRowsPerResultset, &createOpts.SessionParameters.RowsPerResultset), + handleParameterCreate(d, sdk.UserParameterS3StageVpceDnsName, &createOpts.SessionParameters.S3StageVpceDnsName), + handleParameterCreate(d, sdk.UserParameterSearchPath, &createOpts.SessionParameters.SearchPath), + handleParameterCreate(d, sdk.UserParameterSimulatedDataSharingConsumer, &createOpts.SessionParameters.SimulatedDataSharingConsumer), + handleParameterCreate(d, sdk.UserParameterStatementQueuedTimeoutInSeconds, &createOpts.SessionParameters.StatementQueuedTimeoutInSeconds), + handleParameterCreate(d, sdk.UserParameterStatementTimeoutInSeconds, &createOpts.SessionParameters.StatementTimeoutInSeconds), + handleParameterCreate(d, sdk.UserParameterStrictJsonOutput, &createOpts.SessionParameters.StrictJSONOutput), + handleParameterCreate(d, sdk.UserParameterTimestampDayIsAlways24h, &createOpts.SessionParameters.TimestampDayIsAlways24h), + handleParameterCreate(d, sdk.UserParameterTimestampInputFormat, &createOpts.SessionParameters.TimestampInputFormat), + handleParameterCreate(d, sdk.UserParameterTimestampLtzOutputFormat, &createOpts.SessionParameters.TimestampLTZOutputFormat), + handleParameterCreate(d, sdk.UserParameterTimestampNtzOutputFormat, &createOpts.SessionParameters.TimestampNTZOutputFormat), + handleParameterCreate(d, sdk.UserParameterTimestampOutputFormat, &createOpts.SessionParameters.TimestampOutputFormat), + handleParameterCreateWithMapping(d, sdk.UserParameterTimestampTypeMapping, &createOpts.SessionParameters.TimestampTypeMapping, stringToStringEnumProvider(sdk.ToTimestampTypeMapping)), + handleParameterCreate(d, sdk.UserParameterTimestampTzOutputFormat, &createOpts.SessionParameters.TimestampTZOutputFormat), + handleParameterCreate(d, sdk.UserParameterTimezone, &createOpts.SessionParameters.Timezone), + handleParameterCreate(d, sdk.UserParameterTimeInputFormat, &createOpts.SessionParameters.TimeInputFormat), + handleParameterCreate(d, sdk.UserParameterTimeOutputFormat, &createOpts.SessionParameters.TimeOutputFormat), + handleParameterCreateWithMapping(d, sdk.UserParameterTraceLevel, &createOpts.SessionParameters.TraceLevel, stringToStringEnumProvider(sdk.ToTraceLevel)), + handleParameterCreate(d, sdk.UserParameterTransactionAbortOnError, &createOpts.SessionParameters.TransactionAbortOnError), + handleParameterCreateWithMapping(d, sdk.UserParameterTransactionDefaultIsolationLevel, &createOpts.SessionParameters.TransactionDefaultIsolationLevel, stringToStringEnumProvider(sdk.ToTransactionDefaultIsolationLevel)), + handleParameterCreate(d, sdk.UserParameterTwoDigitCenturyStart, &createOpts.SessionParameters.TwoDigitCenturyStart), + handleParameterCreateWithMapping(d, sdk.UserParameterUnsupportedDdlAction, &createOpts.SessionParameters.UnsupportedDDLAction, stringToStringEnumProvider(sdk.ToUnsupportedDDLAction)), + handleParameterCreate(d, sdk.UserParameterUseCachedResult, &createOpts.SessionParameters.UseCachedResult), + handleParameterCreate(d, sdk.UserParameterWeekOfYearPolicy, &createOpts.SessionParameters.WeekOfYearPolicy), + handleParameterCreate(d, sdk.UserParameterWeekStart, &createOpts.SessionParameters.WeekStart), + handleParameterCreate(d, sdk.UserParameterEnableUnredactedQuerySyntaxError, &createOpts.ObjectParameters.EnableUnredactedQuerySyntaxError), + handleParameterCreateWithMapping(d, sdk.UserParameterNetworkPolicy, &createOpts.ObjectParameters.NetworkPolicy, stringToAccountObjectIdentifier), + handleParameterCreate(d, sdk.UserParameterPreventUnloadToInternalStages, &createOpts.ObjectParameters.PreventUnloadToInternalStages), + ) +} + +func handleUserParametersUpdate(d *schema.ResourceData, set *sdk.UserSet, unset *sdk.UserUnset) diag.Diagnostics { + return JoinDiags( + handleParameterUpdate(d, sdk.UserParameterAbortDetachedQuery, &set.SessionParameters.AbortDetachedQuery, &unset.SessionParameters.AbortDetachedQuery), + handleParameterUpdate(d, sdk.UserParameterAutocommit, &set.SessionParameters.Autocommit, &unset.SessionParameters.Autocommit), + handleParameterUpdateWithMapping(d, sdk.UserParameterBinaryInputFormat, &set.SessionParameters.BinaryInputFormat, &unset.SessionParameters.BinaryInputFormat, stringToStringEnumProvider(sdk.ToBinaryInputFormat)), + handleParameterUpdateWithMapping(d, sdk.UserParameterBinaryOutputFormat, &set.SessionParameters.BinaryOutputFormat, &unset.SessionParameters.BinaryOutputFormat, stringToStringEnumProvider(sdk.ToBinaryOutputFormat)), + handleParameterUpdate(d, sdk.UserParameterClientMemoryLimit, &set.SessionParameters.ClientMemoryLimit, &unset.SessionParameters.ClientMemoryLimit), + handleParameterUpdate(d, sdk.UserParameterClientMetadataRequestUseConnectionCtx, &set.SessionParameters.ClientMetadataRequestUseConnectionCtx, &unset.SessionParameters.ClientMetadataRequestUseConnectionCtx), + handleParameterUpdate(d, sdk.UserParameterClientPrefetchThreads, &set.SessionParameters.ClientPrefetchThreads, &unset.SessionParameters.ClientPrefetchThreads), + handleParameterUpdate(d, sdk.UserParameterClientResultChunkSize, &set.SessionParameters.ClientResultChunkSize, &unset.SessionParameters.ClientResultChunkSize), + handleParameterUpdate(d, sdk.UserParameterClientResultColumnCaseInsensitive, &set.SessionParameters.ClientResultColumnCaseInsensitive, &unset.SessionParameters.ClientResultColumnCaseInsensitive), + handleParameterUpdate(d, sdk.UserParameterClientSessionKeepAlive, &set.SessionParameters.ClientSessionKeepAlive, &unset.SessionParameters.ClientSessionKeepAlive), + handleParameterUpdate(d, sdk.UserParameterClientSessionKeepAliveHeartbeatFrequency, &set.SessionParameters.ClientSessionKeepAliveHeartbeatFrequency, &unset.SessionParameters.ClientSessionKeepAliveHeartbeatFrequency), + handleParameterUpdateWithMapping(d, sdk.UserParameterClientTimestampTypeMapping, &set.SessionParameters.ClientTimestampTypeMapping, &unset.SessionParameters.ClientTimestampTypeMapping, stringToStringEnumProvider(sdk.ToClientTimestampTypeMapping)), + handleParameterUpdate(d, sdk.UserParameterDateInputFormat, &set.SessionParameters.DateInputFormat, &unset.SessionParameters.DateInputFormat), + handleParameterUpdate(d, sdk.UserParameterDateOutputFormat, &set.SessionParameters.DateOutputFormat, &unset.SessionParameters.DateOutputFormat), + handleParameterUpdate(d, sdk.UserParameterEnableUnloadPhysicalTypeOptimization, &set.SessionParameters.EnableUnloadPhysicalTypeOptimization, &unset.SessionParameters.EnableUnloadPhysicalTypeOptimization), + handleParameterUpdate(d, sdk.UserParameterErrorOnNondeterministicMerge, &set.SessionParameters.ErrorOnNondeterministicMerge, &unset.SessionParameters.ErrorOnNondeterministicMerge), + handleParameterUpdate(d, sdk.UserParameterErrorOnNondeterministicUpdate, &set.SessionParameters.ErrorOnNondeterministicUpdate, &unset.SessionParameters.ErrorOnNondeterministicUpdate), + handleParameterUpdateWithMapping(d, sdk.UserParameterGeographyOutputFormat, &set.SessionParameters.GeographyOutputFormat, &unset.SessionParameters.GeographyOutputFormat, stringToStringEnumProvider(sdk.ToGeographyOutputFormat)), + handleParameterUpdateWithMapping(d, sdk.UserParameterGeometryOutputFormat, &set.SessionParameters.GeometryOutputFormat, &unset.SessionParameters.GeometryOutputFormat, stringToStringEnumProvider(sdk.ToGeometryOutputFormat)), + handleParameterUpdate(d, sdk.UserParameterJdbcTreatDecimalAsInt, &set.SessionParameters.JdbcTreatDecimalAsInt, &unset.SessionParameters.JdbcTreatDecimalAsInt), + handleParameterUpdate(d, sdk.UserParameterJdbcTreatTimestampNtzAsUtc, &set.SessionParameters.JdbcTreatTimestampNtzAsUtc, &unset.SessionParameters.JdbcTreatTimestampNtzAsUtc), + handleParameterUpdate(d, sdk.UserParameterJdbcUseSessionTimezone, &set.SessionParameters.JdbcUseSessionTimezone, &unset.SessionParameters.JdbcUseSessionTimezone), + handleParameterUpdate(d, sdk.UserParameterJsonIndent, &set.SessionParameters.JSONIndent, &unset.SessionParameters.JSONIndent), + handleParameterUpdate(d, sdk.UserParameterLockTimeout, &set.SessionParameters.LockTimeout, &unset.SessionParameters.LockTimeout), + handleParameterUpdateWithMapping(d, sdk.UserParameterLogLevel, &set.SessionParameters.LogLevel, &unset.SessionParameters.LogLevel, stringToStringEnumProvider(sdk.ToLogLevel)), + handleParameterUpdate(d, sdk.UserParameterMultiStatementCount, &set.SessionParameters.MultiStatementCount, &unset.SessionParameters.MultiStatementCount), + handleParameterUpdate(d, sdk.UserParameterNoorderSequenceAsDefault, &set.SessionParameters.NoorderSequenceAsDefault, &unset.SessionParameters.NoorderSequenceAsDefault), + handleParameterUpdate(d, sdk.UserParameterOdbcTreatDecimalAsInt, &set.SessionParameters.OdbcTreatDecimalAsInt, &unset.SessionParameters.OdbcTreatDecimalAsInt), + handleParameterUpdate(d, sdk.UserParameterQueryTag, &set.SessionParameters.QueryTag, &unset.SessionParameters.QueryTag), + handleParameterUpdate(d, sdk.UserParameterQuotedIdentifiersIgnoreCase, &set.SessionParameters.QuotedIdentifiersIgnoreCase, &unset.SessionParameters.QuotedIdentifiersIgnoreCase), + handleParameterUpdate(d, sdk.UserParameterRowsPerResultset, &set.SessionParameters.RowsPerResultset, &unset.SessionParameters.RowsPerResultset), + handleParameterUpdate(d, sdk.UserParameterS3StageVpceDnsName, &set.SessionParameters.S3StageVpceDnsName, &unset.SessionParameters.S3StageVpceDnsName), + handleParameterUpdate(d, sdk.UserParameterSearchPath, &set.SessionParameters.SearchPath, &unset.SessionParameters.SearchPath), + handleParameterUpdate(d, sdk.UserParameterSimulatedDataSharingConsumer, &set.SessionParameters.SimulatedDataSharingConsumer, &unset.SessionParameters.SimulatedDataSharingConsumer), + handleParameterUpdate(d, sdk.UserParameterStatementQueuedTimeoutInSeconds, &set.SessionParameters.StatementQueuedTimeoutInSeconds, &unset.SessionParameters.StatementQueuedTimeoutInSeconds), + handleParameterUpdate(d, sdk.UserParameterStatementTimeoutInSeconds, &set.SessionParameters.StatementTimeoutInSeconds, &unset.SessionParameters.StatementTimeoutInSeconds), + handleParameterUpdate(d, sdk.UserParameterStrictJsonOutput, &set.SessionParameters.StrictJSONOutput, &unset.SessionParameters.StrictJSONOutput), + handleParameterUpdate(d, sdk.UserParameterTimestampDayIsAlways24h, &set.SessionParameters.TimestampDayIsAlways24h, &unset.SessionParameters.TimestampDayIsAlways24h), + handleParameterUpdate(d, sdk.UserParameterTimestampInputFormat, &set.SessionParameters.TimestampInputFormat, &unset.SessionParameters.TimestampInputFormat), + handleParameterUpdate(d, sdk.UserParameterTimestampLtzOutputFormat, &set.SessionParameters.TimestampLTZOutputFormat, &unset.SessionParameters.TimestampLTZOutputFormat), + handleParameterUpdate(d, sdk.UserParameterTimestampNtzOutputFormat, &set.SessionParameters.TimestampNTZOutputFormat, &unset.SessionParameters.TimestampNTZOutputFormat), + handleParameterUpdate(d, sdk.UserParameterTimestampOutputFormat, &set.SessionParameters.TimestampOutputFormat, &unset.SessionParameters.TimestampOutputFormat), + handleParameterUpdateWithMapping(d, sdk.UserParameterTimestampTypeMapping, &set.SessionParameters.TimestampTypeMapping, &unset.SessionParameters.TimestampTypeMapping, stringToStringEnumProvider(sdk.ToTimestampTypeMapping)), + handleParameterUpdate(d, sdk.UserParameterTimestampTzOutputFormat, &set.SessionParameters.TimestampTZOutputFormat, &unset.SessionParameters.TimestampTZOutputFormat), + handleParameterUpdate(d, sdk.UserParameterTimezone, &set.SessionParameters.Timezone, &unset.SessionParameters.Timezone), + handleParameterUpdate(d, sdk.UserParameterTimeInputFormat, &set.SessionParameters.TimeInputFormat, &unset.SessionParameters.TimeInputFormat), + handleParameterUpdate(d, sdk.UserParameterTimeOutputFormat, &set.SessionParameters.TimeOutputFormat, &unset.SessionParameters.TimeOutputFormat), + handleParameterUpdateWithMapping(d, sdk.UserParameterTraceLevel, &set.SessionParameters.TraceLevel, &unset.SessionParameters.TraceLevel, stringToStringEnumProvider(sdk.ToTraceLevel)), + handleParameterUpdate(d, sdk.UserParameterTransactionAbortOnError, &set.SessionParameters.TransactionAbortOnError, &unset.SessionParameters.TransactionAbortOnError), + handleParameterUpdateWithMapping(d, sdk.UserParameterTransactionDefaultIsolationLevel, &set.SessionParameters.TransactionDefaultIsolationLevel, &unset.SessionParameters.TransactionDefaultIsolationLevel, stringToStringEnumProvider(sdk.ToTransactionDefaultIsolationLevel)), + handleParameterUpdate(d, sdk.UserParameterTwoDigitCenturyStart, &set.SessionParameters.TwoDigitCenturyStart, &unset.SessionParameters.TwoDigitCenturyStart), + handleParameterUpdateWithMapping(d, sdk.UserParameterUnsupportedDdlAction, &set.SessionParameters.UnsupportedDDLAction, &unset.SessionParameters.UnsupportedDDLAction, stringToStringEnumProvider(sdk.ToUnsupportedDDLAction)), + handleParameterUpdate(d, sdk.UserParameterUseCachedResult, &set.SessionParameters.UseCachedResult, &unset.SessionParameters.UseCachedResult), + handleParameterUpdate(d, sdk.UserParameterWeekOfYearPolicy, &set.SessionParameters.WeekOfYearPolicy, &unset.SessionParameters.WeekOfYearPolicy), + handleParameterUpdate(d, sdk.UserParameterWeekStart, &set.SessionParameters.WeekStart, &unset.SessionParameters.WeekStart), + handleParameterUpdate(d, sdk.UserParameterEnableUnredactedQuerySyntaxError, &set.ObjectParameters.EnableUnredactedQuerySyntaxError, &unset.ObjectParameters.EnableUnredactedQuerySyntaxError), + handleParameterUpdateWithMapping(d, sdk.UserParameterNetworkPolicy, &set.ObjectParameters.NetworkPolicy, &unset.ObjectParameters.NetworkPolicy, stringToAccountObjectIdentifier), + handleParameterUpdate(d, sdk.UserParameterPreventUnloadToInternalStages, &set.ObjectParameters.PreventUnloadToInternalStages, &unset.ObjectParameters.PreventUnloadToInternalStages), + ) +} diff --git a/pkg/resources/user_parameters_test.go b/pkg/resources/user_parameters_test.go new file mode 100644 index 0000000000..8c8f2f0423 --- /dev/null +++ b/pkg/resources/user_parameters_test.go @@ -0,0 +1,14 @@ +package resources + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +func Test_UserParametersSchema(t *testing.T) { + t.Run("description references parameter docs correctly", func(t *testing.T) { + require.True(t, strings.HasSuffix(userParametersSchema["abort_detached_query"].Description, "For more information, check [ABORT_DETACHED_QUERY docs](https://docs.snowflake.com/en/sql-reference/parameters#abort-detached-query).")) + }) +} diff --git a/pkg/resources/user_public_keys_acceptance_test.go b/pkg/resources/user_public_keys_acceptance_test.go index 1cd39a4af2..8ceb564625 100644 --- a/pkg/resources/user_public_keys_acceptance_test.go +++ b/pkg/resources/user_public_keys_acceptance_test.go @@ -49,7 +49,7 @@ func TestAcc_UserPublicKeys(t *testing.T) { ImportState: true, ImportStateVerify: true, // Ignoring because keys are currently altered outside of snowflake_user resource (in snowflake_user_public_keys). - ImportStateVerifyIgnore: []string{"password", "rsa_public_key", "rsa_public_key_2", "has_rsa_public_key", "must_change_password"}, + ImportStateVerifyIgnore: []string{"password", "rsa_public_key", "rsa_public_key_2", "has_rsa_public_key", "must_change_password", "show_output"}, }, }, }) diff --git a/pkg/resources/warehouse.go b/pkg/resources/warehouse.go index 9ce8ec6a2e..f5952b8570 100644 --- a/pkg/resources/warehouse.go +++ b/pkg/resources/warehouse.go @@ -150,24 +150,18 @@ var warehouseSchema = map[string]*schema.Schema{ } func warehouseParametersProvider(ctx context.Context, d ResourceIdProvider, meta any) ([]*sdk.Parameter, error) { - client := meta.(*provider.Context).Client - id := helpers.DecodeSnowflakeID(d.Id()).(sdk.AccountObjectIdentifier) - warehouseParameters, err := client.Parameters.ShowParameters(ctx, &sdk.ShowParametersOptions{ - In: &sdk.ParametersIn{ - Warehouse: id, - }, - }) - if err != nil { - return nil, err - } - return warehouseParameters, nil + return parametersProvider(ctx, d, meta.(*provider.Context), warehouseParametersProviderFunc) +} + +func warehouseParametersProviderFunc(c *sdk.Client) showParametersFunc[sdk.AccountObjectIdentifier] { + return c.Warehouses.ShowParameters } func handleWarehouseParametersChanges(d *schema.ResourceData, set *sdk.WarehouseSet, unset *sdk.WarehouseUnset) diag.Diagnostics { return JoinDiags( - handleValuePropertyChange[int](d, "max_concurrency_level", &set.MaxConcurrencyLevel, &unset.MaxConcurrencyLevel), - handleValuePropertyChange[int](d, "statement_queued_timeout_in_seconds", &set.StatementQueuedTimeoutInSeconds, &unset.StatementQueuedTimeoutInSeconds), - handleValuePropertyChange[int](d, "statement_timeout_in_seconds", &set.StatementTimeoutInSeconds, &unset.StatementTimeoutInSeconds), + handleParameterUpdate(d, sdk.ObjectParameterMaxConcurrencyLevel, &set.MaxConcurrencyLevel, &unset.MaxConcurrencyLevel), + handleParameterUpdate(d, sdk.ObjectParameterStatementQueuedTimeoutInSeconds, &set.StatementQueuedTimeoutInSeconds, &unset.StatementQueuedTimeoutInSeconds), + handleParameterUpdate(d, sdk.ObjectParameterStatementTimeoutInSeconds, &set.StatementTimeoutInSeconds, &unset.StatementTimeoutInSeconds), ) } @@ -215,9 +209,9 @@ func Warehouse() *schema.Resource { }), ParametersCustomDiff( warehouseParametersProvider, - parameter{sdk.AccountParameterMaxConcurrencyLevel, valueTypeInt, sdk.ParameterTypeWarehouse}, - parameter{sdk.AccountParameterStatementQueuedTimeoutInSeconds, valueTypeInt, sdk.ParameterTypeWarehouse}, - parameter{sdk.AccountParameterStatementTimeoutInSeconds, valueTypeInt, sdk.ParameterTypeWarehouse}, + parameter[sdk.AccountParameter]{sdk.AccountParameterMaxConcurrencyLevel, valueTypeInt, sdk.ParameterTypeWarehouse}, + parameter[sdk.AccountParameter]{sdk.AccountParameterStatementQueuedTimeoutInSeconds, valueTypeInt, sdk.ParameterTypeWarehouse}, + parameter[sdk.AccountParameter]{sdk.AccountParameterStatementTimeoutInSeconds, valueTypeInt, sdk.ParameterTypeWarehouse}, ), ), @@ -385,11 +379,7 @@ func GetReadWarehouseFunc(withExternalChangesMarking bool) schema.ReadContextFun return diag.FromErr(err) } - warehouseParameters, err := client.Parameters.ShowParameters(ctx, &sdk.ShowParametersOptions{ - In: &sdk.ParametersIn{ - Warehouse: id, - }, - }) + warehouseParameters, err := client.Warehouses.ShowParameters(ctx, id) if err != nil { return diag.FromErr(err) } diff --git a/pkg/schemas/user_parameters.go b/pkg/schemas/user_parameters.go new file mode 100644 index 0000000000..23104ccaa0 --- /dev/null +++ b/pkg/schemas/user_parameters.go @@ -0,0 +1,89 @@ +package schemas + +import ( + "slices" + "strings" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +var ( + ShowUserParametersSchema = make(map[string]*schema.Schema) + userParameters = []sdk.UserParameter{ + sdk.UserParameterEnableUnredactedQuerySyntaxError, + sdk.UserParameterNetworkPolicy, + sdk.UserParameterPreventUnloadToInternalStages, + sdk.UserParameterAbortDetachedQuery, + sdk.UserParameterAutocommit, + sdk.UserParameterBinaryInputFormat, + sdk.UserParameterBinaryOutputFormat, + sdk.UserParameterClientMemoryLimit, + sdk.UserParameterClientMetadataRequestUseConnectionCtx, + sdk.UserParameterClientPrefetchThreads, + sdk.UserParameterClientResultChunkSize, + sdk.UserParameterClientResultColumnCaseInsensitive, + sdk.UserParameterClientSessionKeepAlive, + sdk.UserParameterClientSessionKeepAliveHeartbeatFrequency, + sdk.UserParameterClientTimestampTypeMapping, + sdk.UserParameterDateInputFormat, + sdk.UserParameterDateOutputFormat, + sdk.UserParameterEnableUnloadPhysicalTypeOptimization, + sdk.UserParameterErrorOnNondeterministicMerge, + sdk.UserParameterErrorOnNondeterministicUpdate, + sdk.UserParameterGeographyOutputFormat, + sdk.UserParameterGeometryOutputFormat, + sdk.UserParameterJdbcTreatDecimalAsInt, + sdk.UserParameterJdbcTreatTimestampNtzAsUtc, + sdk.UserParameterJdbcUseSessionTimezone, + sdk.UserParameterJsonIndent, + sdk.UserParameterLockTimeout, + sdk.UserParameterLogLevel, + sdk.UserParameterMultiStatementCount, + sdk.UserParameterNoorderSequenceAsDefault, + sdk.UserParameterOdbcTreatDecimalAsInt, + sdk.UserParameterQueryTag, + sdk.UserParameterQuotedIdentifiersIgnoreCase, + sdk.UserParameterRowsPerResultset, + sdk.UserParameterS3StageVpceDnsName, + sdk.UserParameterSearchPath, + sdk.UserParameterSimulatedDataSharingConsumer, + sdk.UserParameterStatementQueuedTimeoutInSeconds, + sdk.UserParameterStatementTimeoutInSeconds, + sdk.UserParameterStrictJsonOutput, + sdk.UserParameterTimestampDayIsAlways24h, + sdk.UserParameterTimestampInputFormat, + sdk.UserParameterTimestampLtzOutputFormat, + sdk.UserParameterTimestampNtzOutputFormat, + sdk.UserParameterTimestampOutputFormat, + sdk.UserParameterTimestampTypeMapping, + sdk.UserParameterTimestampTzOutputFormat, + sdk.UserParameterTimezone, + sdk.UserParameterTimeInputFormat, + sdk.UserParameterTimeOutputFormat, + sdk.UserParameterTraceLevel, + sdk.UserParameterTransactionAbortOnError, + sdk.UserParameterTransactionDefaultIsolationLevel, + sdk.UserParameterTwoDigitCenturyStart, + sdk.UserParameterUnsupportedDdlAction, + sdk.UserParameterUseCachedResult, + sdk.UserParameterWeekOfYearPolicy, + sdk.UserParameterWeekStart, + } +) + +func init() { + for _, param := range userParameters { + ShowUserParametersSchema[strings.ToLower(string(param))] = ParameterListSchema + } +} + +func UserParametersToSchema(parameters []*sdk.Parameter) map[string]any { + userParametersValue := make(map[string]any) + for _, param := range parameters { + if slices.Contains(userParameters, sdk.UserParameter(param.Key)) { + userParametersValue[strings.ToLower(param.Key)] = []map[string]any{ParameterToSchema(param)} + } + } + return userParametersValue +} diff --git a/pkg/sdk/databases.go b/pkg/sdk/databases.go index 8245ea6b3e..da872eb1aa 100644 --- a/pkg/sdk/databases.go +++ b/pkg/sdk/databases.go @@ -37,6 +37,7 @@ type Databases interface { ShowByID(ctx context.Context, id AccountObjectIdentifier) (*Database, error) Describe(ctx context.Context, id AccountObjectIdentifier) (*DatabaseDetails, error) Use(ctx context.Context, id AccountObjectIdentifier) error + ShowParameters(ctx context.Context, id AccountObjectIdentifier) ([]*Parameter, error) } var _ Databases = (*databases)(nil) @@ -852,3 +853,11 @@ func (v *databases) Use(ctx context.Context, id AccountObjectIdentifier) error { // proxy to sessions return v.client.Sessions.UseDatabase(ctx, id) } + +func (v *databases) ShowParameters(ctx context.Context, id AccountObjectIdentifier) ([]*Parameter, error) { + return v.client.Parameters.ShowParameters(ctx, &ShowParametersOptions{ + In: &ParametersIn{ + Database: id, + }, + }) +} diff --git a/pkg/sdk/parameters.go b/pkg/sdk/parameters.go index 5b963db57c..b337764675 100644 --- a/pkg/sdk/parameters.go +++ b/pkg/sdk/parameters.go @@ -672,6 +672,23 @@ const ( GeographyOutputFormatEWKB GeographyOutputFormat = "EWKB" ) +func ToGeographyOutputFormat(s string) (GeographyOutputFormat, error) { + switch strings.ToUpper(s) { + case strings.ToUpper(string(GeographyOutputFormatGeoJSON)): + return GeographyOutputFormatGeoJSON, nil + case string(GeographyOutputFormatWKT): + return GeographyOutputFormatWKT, nil + case string(GeographyOutputFormatWKB): + return GeographyOutputFormatWKB, nil + case string(GeographyOutputFormatEWKT): + return GeographyOutputFormatEWKT, nil + case string(GeographyOutputFormatEWKB): + return GeographyOutputFormatEWKB, nil + default: + return "", fmt.Errorf("invalid geography output format: %s", s) + } +} + type GeometryOutputFormat string const ( @@ -682,6 +699,23 @@ const ( GeometryOutputFormatEWKB GeometryOutputFormat = "EWKB" ) +func ToGeometryOutputFormat(s string) (GeometryOutputFormat, error) { + switch strings.ToUpper(s) { + case strings.ToUpper(string(GeometryOutputFormatGeoJSON)): + return GeometryOutputFormatGeoJSON, nil + case string(GeometryOutputFormatWKT): + return GeometryOutputFormatWKT, nil + case string(GeometryOutputFormatWKB): + return GeometryOutputFormatWKB, nil + case string(GeometryOutputFormatEWKT): + return GeometryOutputFormatEWKT, nil + case string(GeometryOutputFormatEWKB): + return GeometryOutputFormatEWKB, nil + default: + return "", fmt.Errorf("invalid geometry output format: %s", s) + } +} + type BinaryInputFormat string const ( @@ -690,6 +724,19 @@ const ( BinaryInputFormatUTF8 BinaryInputFormat = "UTF8" ) +func ToBinaryInputFormat(s string) (BinaryInputFormat, error) { + switch strings.ToUpper(s) { + case string(BinaryInputFormatHex): + return BinaryInputFormatHex, nil + case string(BinaryInputFormatBase64): + return BinaryInputFormatBase64, nil + case string(BinaryInputFormatUTF8): + return BinaryInputFormatUTF8, nil + default: + return "", fmt.Errorf("invalid binary input format: %s", s) + } +} + type BinaryOutputFormat string const ( @@ -697,6 +744,17 @@ const ( BinaryOutputFormatBase64 BinaryOutputFormat = "BASE64" ) +func ToBinaryOutputFormat(s string) (BinaryOutputFormat, error) { + switch strings.ToUpper(s) { + case string(BinaryOutputFormatHex): + return BinaryOutputFormatHex, nil + case string(BinaryOutputFormatBase64): + return BinaryOutputFormatBase64, nil + default: + return "", fmt.Errorf("invalid binary output format: %s", s) + } +} + type ClientTimestampTypeMapping string const ( @@ -704,6 +762,17 @@ const ( ClientTimestampTypeMappingNtz ClientTimestampTypeMapping = "TIMESTAMP_NTZ" ) +func ToClientTimestampTypeMapping(s string) (ClientTimestampTypeMapping, error) { + switch strings.ToUpper(s) { + case string(ClientTimestampTypeMappingLtz): + return ClientTimestampTypeMappingLtz, nil + case string(ClientTimestampTypeMappingNtz): + return ClientTimestampTypeMappingNtz, nil + default: + return "", fmt.Errorf("invalid client timestamp type mapping: %s", s) + } +} + type TimestampTypeMapping string const ( @@ -712,12 +781,34 @@ const ( TimestampTypeMappingTz TimestampTypeMapping = "TIMESTAMP_TZ" ) +func ToTimestampTypeMapping(s string) (TimestampTypeMapping, error) { + switch strings.ToUpper(s) { + case string(TimestampTypeMappingLtz): + return TimestampTypeMappingLtz, nil + case string(TimestampTypeMappingNtz): + return TimestampTypeMappingNtz, nil + case string(TimestampTypeMappingTz): + return TimestampTypeMappingTz, nil + default: + return "", fmt.Errorf("invalid timestamp type mapping: %s", s) + } +} + type TransactionDefaultIsolationLevel string const ( TransactionDefaultIsolationLevelReadCommitted TransactionDefaultIsolationLevel = "READ COMMITTED" ) +func ToTransactionDefaultIsolationLevel(s string) (TransactionDefaultIsolationLevel, error) { + switch strings.ToUpper(s) { + case string(TransactionDefaultIsolationLevelReadCommitted): + return TransactionDefaultIsolationLevelReadCommitted, nil + default: + return "", fmt.Errorf("invalid transaction default isolation level: %s", s) + } +} + type UnsupportedDDLAction string const ( @@ -725,6 +816,17 @@ const ( UnsupportedDDLActionFail UnsupportedDDLAction = "FAIL" ) +func ToUnsupportedDDLAction(s string) (UnsupportedDDLAction, error) { + switch strings.ToUpper(s) { + case string(UnsupportedDDLActionIgnore): + return UnsupportedDDLActionIgnore, nil + case string(UnsupportedDDLActionFail): + return UnsupportedDDLActionFail, nil + default: + return "", fmt.Errorf("invalid ddl action: %s", s) + } +} + // SessionParameters is based on https://docs.snowflake.com/en/sql-reference/parameters#session-parameters. type SessionParameters struct { AbortDetachedQuery *bool `ddl:"parameter" sql:"ABORT_DETACHED_QUERY"` diff --git a/pkg/sdk/parsers.go b/pkg/sdk/parsers.go index 26dc8b4a07..da3d53fc85 100644 --- a/pkg/sdk/parsers.go +++ b/pkg/sdk/parsers.go @@ -32,7 +32,7 @@ func ParseCommaSeparatedStringArray(value string, trimQuotes bool) []string { for i, item := range listItems { trimmedListItems[i] = strings.TrimSpace(item) if trimQuotes { - trimmedListItems[i] = strings.Trim(trimmedListItems[i], "'") + trimmedListItems[i] = strings.Trim(trimmedListItems[i], "'\"") } } return trimmedListItems diff --git a/pkg/sdk/parsers_test.go b/pkg/sdk/parsers_test.go index c68ce19e47..d31fa0063d 100644 --- a/pkg/sdk/parsers_test.go +++ b/pkg/sdk/parsers_test.go @@ -61,11 +61,41 @@ func TestParseCommaSeparatedStringArray(t *testing.T) { Result: []string{"one", "two", "three"}, }, { - Name: "list without brackets - with quotes", + Name: "list without brackets - with single quotes", Value: "'one','two','three'", TrimQuotes: true, Result: []string{"one", "two", "three"}, }, + { + Name: "list without brackets - with double quotes", + Value: `"one","two","three"`, + TrimQuotes: true, + Result: []string{"one", "two", "three"}, + }, + { + Name: "list with brackets - with double quotes", + Value: `"one","two","three"`, + TrimQuotes: true, + Result: []string{"one", "two", "three"}, + }, + { + Name: "list with brackets - with double quotes, no trimming", + Value: `"one","two","three"`, + TrimQuotes: false, + Result: []string{"\"one\"", "\"two\"", "\"three\""}, + }, + { + Name: "list with brackets - with double quotes", + Value: `["one","two","three"]`, + TrimQuotes: true, + Result: []string{"one", "two", "three"}, + }, + { + Name: "multiple quote types", + Value: `['"'one'"',"'two",'"three'"]`, + TrimQuotes: true, + Result: []string{"one", "two", "three"}, + }, } for _, tc := range testCases { diff --git a/pkg/sdk/schemas.go b/pkg/sdk/schemas.go index 5c398d8918..24b560cbb8 100644 --- a/pkg/sdk/schemas.go +++ b/pkg/sdk/schemas.go @@ -28,6 +28,7 @@ type Schemas interface { Show(ctx context.Context, opts *ShowSchemaOptions) ([]Schema, error) ShowByID(ctx context.Context, id DatabaseObjectIdentifier) (*Schema, error) Use(ctx context.Context, id DatabaseObjectIdentifier) error + ShowParameters(ctx context.Context, id DatabaseObjectIdentifier) ([]*Parameter, error) } var _ Schemas = (*schemas)(nil) @@ -573,3 +574,11 @@ func (v *schemas) ShowByID(ctx context.Context, id DatabaseObjectIdentifier) (*S func (v *schemas) Use(ctx context.Context, id DatabaseObjectIdentifier) error { return v.client.Sessions.UseSchema(ctx, id) } + +func (v *schemas) ShowParameters(ctx context.Context, id DatabaseObjectIdentifier) ([]*Parameter, error) { + return v.client.Parameters.ShowParameters(ctx, &ShowParametersOptions{ + In: &ParametersIn{ + Schema: id, + }, + }) +} diff --git a/pkg/sdk/testint/databases_integration_test.go b/pkg/sdk/testint/databases_integration_test.go index 9fbe65e62f..2c80e42c96 100644 --- a/pkg/sdk/testint/databases_integration_test.go +++ b/pkg/sdk/testint/databases_integration_test.go @@ -114,7 +114,8 @@ func TestInt_DatabasesCreate(t *testing.T) { assert.Equal(t, databaseId.Name(), database.Name) assert.Equal(t, comment, database.Comment) - params := testClientHelper().Parameter.ShowDatabaseParameters(t, databaseId) + params, err := client.Databases.ShowParameters(ctx, databaseId) + require.NoError(t, err) assertParameterEquals := func(t *testing.T, parameterName sdk.AccountParameter, expected string) { t.Helper() assert.Equal(t, expected, helpers.FindParameter(t, params, parameterName).Value) @@ -226,7 +227,8 @@ func TestInt_DatabasesCreateShared(t *testing.T) { assert.Equal(t, databaseId.Name(), database.Name) assert.Equal(t, comment, database.Comment) - params := testClientHelper().Parameter.ShowDatabaseParameters(t, databaseId) + params, err := client.Databases.ShowParameters(ctx, databaseId) + require.NoError(t, err) assertParameterEquals := func(t *testing.T, parameterName sdk.AccountParameter, expected string) { t.Helper() assert.Equal(t, expected, helpers.FindParameter(t, params, parameterName).Value) @@ -310,7 +312,8 @@ func TestInt_DatabasesCreateSecondary(t *testing.T) { assert.Equal(t, databaseId.Name(), database.Name) assert.Equal(t, comment, database.Comment) - params := testClientHelper().Parameter.ShowDatabaseParameters(t, databaseId) + params, err := client.Databases.ShowParameters(ctx, databaseId) + require.NoError(t, err) assertParameterEquals := func(t *testing.T, parameterName sdk.AccountParameter, expected string) { t.Helper() assert.Equal(t, expected, helpers.FindParameter(t, params, parameterName).Value) @@ -492,7 +495,8 @@ func TestInt_DatabasesAlter(t *testing.T) { }) require.NoError(t, err) - params := testClientHelper().Parameter.ShowDatabaseParameters(t, databaseTest.ID()) + params, err := client.Databases.ShowParameters(ctx, databaseTest.ID()) + require.NoError(t, err) assertDatabaseParameterEquals(t, params, sdk.AccountParameterDataRetentionTimeInDays, "42") assertDatabaseParameterEquals(t, params, sdk.AccountParameterMaxDataExtensionTimeInDays, "42") assertDatabaseParameterEquals(t, params, sdk.AccountParameterExternalVolume, externalVolumeTest.Name()) @@ -532,7 +536,8 @@ func TestInt_DatabasesAlter(t *testing.T) { }) require.NoError(t, err) - params = testClientHelper().Parameter.ShowDatabaseParameters(t, databaseTest.ID()) + params, err = client.Databases.ShowParameters(ctx, databaseTest.ID()) + require.NoError(t, err) assertDatabaseParameterEqualsToDefaultValue(t, params, sdk.ObjectParameterDataRetentionTimeInDays) assertDatabaseParameterEqualsToDefaultValue(t, params, sdk.ObjectParameterMaxDataExtensionTimeInDays) assertDatabaseParameterEqualsToDefaultValue(t, params, sdk.ObjectParameterExternalVolume) diff --git a/pkg/sdk/testint/schemas_integration_test.go b/pkg/sdk/testint/schemas_integration_test.go index c4d9a810a3..5effa07bd2 100644 --- a/pkg/sdk/testint/schemas_integration_test.go +++ b/pkg/sdk/testint/schemas_integration_test.go @@ -44,7 +44,8 @@ func TestInt_Schemas(t *testing.T) { require.NoError(t, err) assert.Equal(t, schemaId.Name(), database.Name) - params := testClientHelper().Parameter.ShowSchemaParameters(t, schemaId) + params, err := client.Schemas.ShowParameters(ctx, schemaId) + require.NoError(t, err) assertParameterEqualsToDefaultValue(t, params, sdk.ObjectParameterDataRetentionTimeInDays) assertParameterEqualsToDefaultValue(t, params, sdk.ObjectParameterMaxDataExtensionTimeInDays) assertParameterEqualsToDefaultValue(t, params, sdk.ObjectParameterExternalVolume) @@ -217,7 +218,8 @@ func TestInt_Schemas(t *testing.T) { assert.Equal(t, schemaId.Name(), schema.Name) assert.Equal(t, comment, schema.Comment) - params := testClientHelper().Parameter.ShowSchemaParameters(t, schemaId) + params, err := client.Schemas.ShowParameters(ctx, schemaId) + require.NoError(t, err) assertParameterEquals := func(t *testing.T, parameterName sdk.AccountParameter, expected string) { t.Helper() assert.Equal(t, expected, helpers.FindParameter(t, params, parameterName).Value) @@ -331,7 +333,8 @@ func TestInt_Schemas(t *testing.T) { }) require.NoError(t, err) - params := testClientHelper().Parameter.ShowSchemaParameters(t, schemaTest.ID()) + params, err := client.Schemas.ShowParameters(ctx, schemaTest.ID()) + require.NoError(t, err) assertParameterEquals(t, params, sdk.AccountParameterDataRetentionTimeInDays, "42") assertParameterEquals(t, params, sdk.AccountParameterMaxDataExtensionTimeInDays, "42") assertParameterEquals(t, params, sdk.AccountParameterExternalVolume, externalVolumeTest.Name()) @@ -373,7 +376,8 @@ func TestInt_Schemas(t *testing.T) { }) require.NoError(t, err) - params = testClientHelper().Parameter.ShowSchemaParameters(t, schemaTest.ID()) + params, err = client.Schemas.ShowParameters(ctx, schemaTest.ID()) + require.NoError(t, err) assertParameterEqualsToDefaultValue(t, params, sdk.ObjectParameterDataRetentionTimeInDays) assertParameterEqualsToDefaultValue(t, params, sdk.ObjectParameterMaxDataExtensionTimeInDays) assertParameterEqualsToDefaultValue(t, params, sdk.ObjectParameterExternalVolume) diff --git a/pkg/sdk/testint/users_integration_test.go b/pkg/sdk/testint/users_integration_test.go index 4dc97584ed..6223b2a706 100644 --- a/pkg/sdk/testint/users_integration_test.go +++ b/pkg/sdk/testint/users_integration_test.go @@ -48,9 +48,8 @@ func TestInt_Users(t *testing.T) { networkPolicy, networkPolicyCleanup := testClientHelper().NetworkPolicy.CreateNetworkPolicy(t) t.Cleanup(networkPolicyCleanup) - assertParametersSet := func(t *testing.T, id sdk.AccountObjectIdentifier) { - t.Helper() - assertions.AssertThatObject(t, objectparametersassert.UserParameters(t, id). + assertParametersSet := func(userParametersAssert *objectparametersassert.UserParametersAssert) { + assertions.AssertThatObject(t, userParametersAssert. HasEnableUnredactedQuerySyntaxError(true). HasNetworkPolicy(networkPolicy.ID().Name()). HasPreventUnloadToInternalStages(true). @@ -521,7 +520,12 @@ func TestInt_Users(t *testing.T) { require.NoError(t, err) t.Cleanup(testClientHelper().User.DropUserFunc(t, id)) - assertParametersSet(t, id) + assertParametersSet(objectparametersassert.UserParameters(t, id)) + + // check that ShowParameters works too + parameters, err := client.Users.ShowParameters(ctx, id) + require.NoError(t, err) + assertParametersSet(objectparametersassert.UserParametersPrefetched(t, id, parameters)) }) t.Run("create: with all parameters default", func(t *testing.T) { @@ -535,6 +539,14 @@ func TestInt_Users(t *testing.T) { HasAllDefaults(). HasAllDefaultsExplicit(), ) + + // check that ShowParameters works too + parameters, err := client.Users.ShowParameters(ctx, id) + require.NoError(t, err) + assertions.AssertThatObject(t, objectparametersassert.UserParametersPrefetched(t, id, parameters). + HasAllDefaults(). + HasAllDefaultsExplicit(), + ) }) t.Run("alter: rename", func(t *testing.T) { @@ -736,7 +748,12 @@ func TestInt_Users(t *testing.T) { err = client.Users.Alter(ctx, id, alterOpts) require.NoError(t, err) - assertParametersSet(t, id) + assertParametersSet(objectparametersassert.UserParameters(t, id)) + + // check that ShowParameters works too + parameters, err := client.Users.ShowParameters(ctx, id) + require.NoError(t, err) + assertParametersSet(objectparametersassert.UserParametersPrefetched(t, id, parameters)) // unset is split into two because: // 1. this is how it's written in the docs https://docs.snowflake.com/en/sql-reference/sql/alter-user#syntax @@ -824,6 +841,14 @@ func TestInt_Users(t *testing.T) { HasAllDefaults(). HasAllDefaultsExplicit(), ) + + // check that ShowParameters works too + parameters, err = client.Users.ShowParameters(ctx, id) + require.NoError(t, err) + assertions.AssertThatObject(t, objectparametersassert.UserParametersPrefetched(t, id, parameters). + HasAllDefaults(). + HasAllDefaultsExplicit(), + ) }) t.Run("alter: set and unset tags", func(t *testing.T) { diff --git a/pkg/sdk/testint/warehouses_integration_test.go b/pkg/sdk/testint/warehouses_integration_test.go index 43957cb340..6f2c18bc27 100644 --- a/pkg/sdk/testint/warehouses_integration_test.go +++ b/pkg/sdk/testint/warehouses_integration_test.go @@ -284,7 +284,8 @@ func TestInt_Warehouses(t *testing.T) { warehouse, warehouseCleanup := testClientHelper().Warehouse.CreateWarehouse(t) t.Cleanup(warehouseCleanup) - parameters := testClientHelper().Parameter.ShowWarehouseParameters(t, warehouse.ID()) + parameters, err := client.Warehouses.ShowParameters(ctx, warehouse.ID()) + require.NoError(t, err) assert.Equal(t, "8", helpers.FindParameter(t, parameters, sdk.AccountParameterMaxConcurrencyLevel).Value) assert.Equal(t, "0", helpers.FindParameter(t, parameters, sdk.AccountParameterStatementQueuedTimeoutInSeconds).Value) @@ -297,10 +298,11 @@ func TestInt_Warehouses(t *testing.T) { StatementTimeoutInSeconds: sdk.Int(86400), }, } - err := client.Warehouses.Alter(ctx, warehouse.ID(), alterOptions) + err = client.Warehouses.Alter(ctx, warehouse.ID(), alterOptions) require.NoError(t, err) - parametersAfterSet := testClientHelper().Parameter.ShowWarehouseParameters(t, warehouse.ID()) + parametersAfterSet, err := client.Warehouses.ShowParameters(ctx, warehouse.ID()) + require.NoError(t, err) assert.Equal(t, "4", helpers.FindParameter(t, parametersAfterSet, sdk.AccountParameterMaxConcurrencyLevel).Value) assert.Equal(t, "2", helpers.FindParameter(t, parametersAfterSet, sdk.AccountParameterStatementQueuedTimeoutInSeconds).Value) assert.Equal(t, "86400", helpers.FindParameter(t, parametersAfterSet, sdk.AccountParameterStatementTimeoutInSeconds).Value) @@ -315,7 +317,8 @@ func TestInt_Warehouses(t *testing.T) { err = client.Warehouses.Alter(ctx, warehouse.ID(), alterOptions) require.NoError(t, err) - parametersAfterUnset := testClientHelper().Parameter.ShowWarehouseParameters(t, warehouse.ID()) + parametersAfterUnset, err := client.Warehouses.ShowParameters(ctx, warehouse.ID()) + require.NoError(t, err) assert.Equal(t, "8", helpers.FindParameter(t, parametersAfterUnset, sdk.AccountParameterMaxConcurrencyLevel).Value) assert.Equal(t, "0", helpers.FindParameter(t, parametersAfterUnset, sdk.AccountParameterStatementQueuedTimeoutInSeconds).Value) assert.Equal(t, "172800", helpers.FindParameter(t, parametersAfterUnset, sdk.AccountParameterStatementTimeoutInSeconds).Value) diff --git a/pkg/sdk/users.go b/pkg/sdk/users.go index 7ef682c357..c177bd5231 100644 --- a/pkg/sdk/users.go +++ b/pkg/sdk/users.go @@ -23,6 +23,7 @@ type Users interface { Describe(ctx context.Context, id AccountObjectIdentifier) (*UserDetails, error) Show(ctx context.Context, opts *ShowUserOptions) ([]User, error) ShowByID(ctx context.Context, id AccountObjectIdentifier) (*User, error) + ShowParameters(ctx context.Context, id AccountObjectIdentifier) ([]*Parameter, error) } var _ Users = (*users)(nil) @@ -605,3 +606,11 @@ func (v *users) ShowByID(ctx context.Context, id AccountObjectIdentifier) (*User } return nil, ErrObjectNotExistOrAuthorized } + +func (v *users) ShowParameters(ctx context.Context, id AccountObjectIdentifier) ([]*Parameter, error) { + return v.client.Parameters.ShowParameters(ctx, &ShowParametersOptions{ + In: &ParametersIn{ + User: id, + }, + }) +} diff --git a/pkg/sdk/users_test.go b/pkg/sdk/users_test.go index a8bc2c0fc1..ddb0dfe10b 100644 --- a/pkg/sdk/users_test.go +++ b/pkg/sdk/users_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers/random" + "github.com/stretchr/testify/require" ) func TestUserCreate(t *testing.T) { @@ -345,3 +346,330 @@ func TestUserDescribe(t *testing.T) { assertOptsValidAndSQLEquals(t, opts, "DESCRIBE USER %s", id.FullyQualifiedName()) }) } + +func Test_User_ToGeographyOutputFormat(t *testing.T) { + type test struct { + input string + want GeographyOutputFormat + } + + valid := []test{ + // case insensitive. + {input: "geojson", want: GeographyOutputFormatGeoJSON}, + + // Supported Values + {input: string(GeographyOutputFormatGeoJSON), want: GeographyOutputFormatGeoJSON}, + {input: string(GeographyOutputFormatWKT), want: GeographyOutputFormatWKT}, + {input: string(GeographyOutputFormatWKB), want: GeographyOutputFormatWKB}, + {input: string(GeographyOutputFormatEWKT), want: GeographyOutputFormatEWKT}, + {input: string(GeographyOutputFormatEWKB), want: GeographyOutputFormatEWKB}, + } + + invalid := []test{ + // bad values + {input: ""}, + {input: "foo"}, + + // not supported values (single-quoted) + {input: "'GeoJSON'"}, + } + + for _, tc := range valid { + t.Run(tc.input, func(t *testing.T) { + got, err := ToGeographyOutputFormat(tc.input) + require.NoError(t, err) + require.Equal(t, tc.want, got) + }) + } + + for _, tc := range invalid { + t.Run(tc.input, func(t *testing.T) { + _, err := ToGeographyOutputFormat(tc.input) + require.Error(t, err) + }) + } +} + +func Test_User_ToGeometryOutputFormat(t *testing.T) { + type test struct { + input string + want GeometryOutputFormat + } + + valid := []test{ + // case insensitive. + {input: "geojson", want: GeometryOutputFormatGeoJSON}, + + // Supported Values + {input: string(GeometryOutputFormatGeoJSON), want: GeometryOutputFormatGeoJSON}, + {input: string(GeometryOutputFormatWKT), want: GeometryOutputFormatWKT}, + {input: string(GeometryOutputFormatWKB), want: GeometryOutputFormatWKB}, + {input: string(GeometryOutputFormatEWKT), want: GeometryOutputFormatEWKT}, + {input: string(GeometryOutputFormatEWKB), want: GeometryOutputFormatEWKB}, + } + + invalid := []test{ + // bad values + {input: ""}, + {input: "foo"}, + + // not supported values (single-quoted) + {input: "'GeoJSON'"}, + } + + for _, tc := range valid { + t.Run(tc.input, func(t *testing.T) { + got, err := ToGeometryOutputFormat(tc.input) + require.NoError(t, err) + require.Equal(t, tc.want, got) + }) + } + + for _, tc := range invalid { + t.Run(tc.input, func(t *testing.T) { + _, err := ToGeometryOutputFormat(tc.input) + require.Error(t, err) + }) + } +} + +func Test_User_ToBinaryInputFormat(t *testing.T) { + type test struct { + input string + want BinaryInputFormat + } + + valid := []test{ + // case insensitive. + {input: "hex", want: BinaryInputFormatHex}, + + // Supported Values + {input: string(BinaryInputFormatHex), want: BinaryInputFormatHex}, + {input: string(BinaryInputFormatBase64), want: BinaryInputFormatBase64}, + {input: string(BinaryInputFormatUTF8), want: BinaryInputFormatUTF8}, + } + + invalid := []test{ + // bad values + {input: ""}, + {input: "foo"}, + + // not supported values (single-quoted) + {input: "'HEX'"}, + } + + for _, tc := range valid { + t.Run(tc.input, func(t *testing.T) { + got, err := ToBinaryInputFormat(tc.input) + require.NoError(t, err) + require.Equal(t, tc.want, got) + }) + } + + for _, tc := range invalid { + t.Run(tc.input, func(t *testing.T) { + _, err := ToBinaryInputFormat(tc.input) + require.Error(t, err) + }) + } +} + +func Test_User_ToBinaryOutputFormat(t *testing.T) { + type test struct { + input string + want BinaryOutputFormat + } + + valid := []test{ + // case insensitive. + {input: "hex", want: BinaryOutputFormatHex}, + + // Supported Values + {input: string(BinaryOutputFormatHex), want: BinaryOutputFormatHex}, + {input: string(BinaryOutputFormatBase64), want: BinaryOutputFormatBase64}, + } + + invalid := []test{ + // bad values + {input: ""}, + {input: "foo"}, + + // not supported values (single-quoted) + {input: "'HEX'"}, + } + + for _, tc := range valid { + t.Run(tc.input, func(t *testing.T) { + got, err := ToBinaryOutputFormat(tc.input) + require.NoError(t, err) + require.Equal(t, tc.want, got) + }) + } + + for _, tc := range invalid { + t.Run(tc.input, func(t *testing.T) { + _, err := ToBinaryOutputFormat(tc.input) + require.Error(t, err) + }) + } +} + +func Test_User_ToClientTimestampTypeMapping(t *testing.T) { + type test struct { + input string + want ClientTimestampTypeMapping + } + + valid := []test{ + // case insensitive. + {input: "timestamp_ltz", want: ClientTimestampTypeMappingLtz}, + + // Supported Values + {input: string(ClientTimestampTypeMappingLtz), want: ClientTimestampTypeMappingLtz}, + {input: string(ClientTimestampTypeMappingNtz), want: ClientTimestampTypeMappingNtz}, + } + + invalid := []test{ + // bad values + {input: ""}, + {input: "foo"}, + + // not supported values (single-quoted) + {input: "'TIMESTAMP_LTZ'"}, + } + + for _, tc := range valid { + t.Run(tc.input, func(t *testing.T) { + got, err := ToClientTimestampTypeMapping(tc.input) + require.NoError(t, err) + require.Equal(t, tc.want, got) + }) + } + + for _, tc := range invalid { + t.Run(tc.input, func(t *testing.T) { + _, err := ToClientTimestampTypeMapping(tc.input) + require.Error(t, err) + }) + } +} + +func Test_User_ToTimestampTypeMapping(t *testing.T) { + type test struct { + input string + want TimestampTypeMapping + } + + valid := []test{ + // case insensitive. + {input: "timestamp_ltz", want: TimestampTypeMappingLtz}, + + // Supported Values + {input: string(TimestampTypeMappingLtz), want: TimestampTypeMappingLtz}, + {input: string(TimestampTypeMappingNtz), want: TimestampTypeMappingNtz}, + {input: string(TimestampTypeMappingTz), want: TimestampTypeMappingTz}, + } + + invalid := []test{ + // bad values + {input: ""}, + {input: "foo"}, + + // not supported values (single-quoted) + {input: "'TIMESTAMP_LTZ'"}, + } + + for _, tc := range valid { + t.Run(tc.input, func(t *testing.T) { + got, err := ToTimestampTypeMapping(tc.input) + require.NoError(t, err) + require.Equal(t, tc.want, got) + }) + } + + for _, tc := range invalid { + t.Run(tc.input, func(t *testing.T) { + _, err := ToTimestampTypeMapping(tc.input) + require.Error(t, err) + }) + } +} + +func Test_User_ToTransactionDefaultIsolationLevel(t *testing.T) { + type test struct { + input string + want TransactionDefaultIsolationLevel + } + + valid := []test{ + // case insensitive. + {input: "read committed", want: TransactionDefaultIsolationLevelReadCommitted}, + + // Supported Values + {input: string(TransactionDefaultIsolationLevelReadCommitted), want: TransactionDefaultIsolationLevelReadCommitted}, + } + + invalid := []test{ + // bad values + {input: ""}, + {input: "foo"}, + + // not supported values (single-quoted) + {input: "'READ COMMITTED'"}, + } + + for _, tc := range valid { + t.Run(tc.input, func(t *testing.T) { + got, err := ToTransactionDefaultIsolationLevel(tc.input) + require.NoError(t, err) + require.Equal(t, tc.want, got) + }) + } + + for _, tc := range invalid { + t.Run(tc.input, func(t *testing.T) { + _, err := ToTransactionDefaultIsolationLevel(tc.input) + require.Error(t, err) + }) + } +} + +func Test_User_ToUnsupportedDDLAction(t *testing.T) { + type test struct { + input string + want UnsupportedDDLAction + } + + valid := []test{ + // case insensitive. + {input: "ignore", want: UnsupportedDDLActionIgnore}, + + // Supported Values + {input: string(UnsupportedDDLActionIgnore), want: UnsupportedDDLActionIgnore}, + {input: string(UnsupportedDDLActionFail), want: UnsupportedDDLActionFail}, + } + + invalid := []test{ + // bad values + {input: ""}, + {input: "foo"}, + + // not supported values (single-quoted) + {input: "'IGNORE'"}, + } + + for _, tc := range valid { + t.Run(tc.input, func(t *testing.T) { + got, err := ToUnsupportedDDLAction(tc.input) + require.NoError(t, err) + require.Equal(t, tc.want, got) + }) + } + + for _, tc := range invalid { + t.Run(tc.input, func(t *testing.T) { + _, err := ToUnsupportedDDLAction(tc.input) + require.Error(t, err) + }) + } +} diff --git a/pkg/sdk/warehouses.go b/pkg/sdk/warehouses.go index 330361ff07..26dbeb89e8 100644 --- a/pkg/sdk/warehouses.go +++ b/pkg/sdk/warehouses.go @@ -28,6 +28,7 @@ type Warehouses interface { Show(ctx context.Context, opts *ShowWarehouseOptions) ([]Warehouse, error) ShowByID(ctx context.Context, id AccountObjectIdentifier) (*Warehouse, error) Describe(ctx context.Context, id AccountObjectIdentifier) (*WarehouseDetails, error) + ShowParameters(ctx context.Context, id AccountObjectIdentifier) ([]*Parameter, error) } var _ Warehouses = (*warehouses)(nil) @@ -621,3 +622,11 @@ func (v *Warehouse) ID() AccountObjectIdentifier { func (v *Warehouse) ObjectType() ObjectType { return ObjectTypeWarehouse } + +func (c *warehouses) ShowParameters(ctx context.Context, id AccountObjectIdentifier) ([]*Parameter, error) { + return c.client.Parameters.ShowParameters(ctx, &ShowParametersOptions{ + In: &ParametersIn{ + Warehouse: id, + }, + }) +} diff --git a/templates/resources/user.md.tmpl b/templates/resources/user.md.tmpl new file mode 100644 index 0000000000..9d371d4b57 --- /dev/null +++ b/templates/resources/user.md.tmpl @@ -0,0 +1,32 @@ +--- +page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" +subcategory: "" +description: |- +{{ if gt (len (split .Description "")) 1 -}} +{{ index (split .Description "") 1 | plainmarkdown | trimspace | prefixlines " " }} +{{- else -}} +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} +{{- end }} +--- + +!> **V1 release candidate** This resource was reworked and is a release candidate for the V1. We do not expect significant changes in it before the V1. We will welcome any feedback and adjust the resource if needed. Any errors reported will be resolved with a higher priority. We encourage checking this resource out before the V1 release. Please follow the [migration guide](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/MIGRATION_GUIDE.md#v094x--v0950) to use it. + +# {{.Name}} ({{.Type}}) + +{{ .Description | trimspace }} + +{{ if .HasExample -}} +## Example Usage + +{{ tffile (printf "examples/resources/%s/resource.tf" .Name)}} +{{- end }} + +{{ .SchemaMarkdown | trimspace }} +{{- if .HasImport }} + +## Import + +Import is supported using the following syntax: + +{{ codefile "shell" (printf "examples/resources/%s/import.sh" .Name)}} +{{- end }} diff --git a/v1-preparations/CHANGES_BEFORE_V1.md b/v1-preparations/CHANGES_BEFORE_V1.md index d9cf10240f..2f952f7344 100644 --- a/v1-preparations/CHANGES_BEFORE_V1.md +++ b/v1-preparations/CHANGES_BEFORE_V1.md @@ -30,7 +30,7 @@ It won't be possible to use the above values directly (it will be for the string ## Snowflake parameters [Snowflake parameters](https://docs.snowflake.com/en/sql-reference/parameters) have different types and hierarchies. In the earlier versions of the provider they have been handled non-intuitively by setting the deault values inside the provider (e.g. [#2356](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2356)). We want to change that. Because of that we decided to: -- make all parameters available for the given object available in the resource (without the need to use the `snowflake_object_parameter` resource which future will be discussed in the next few weeks) +- make all parameters available for the given object available in the resource (without the need to use the `snowflake_object_parameter` resource which future will be discussed in the next few weeks; for the V1 ready resources, you should not use `snowflake_` and `snowflake_object_parameter` together: if you manage `` through terraform, and you want to set the parameter on the object's level, it must be done in `snowflake_` resource) - remove the default values from Snowflake parameters in every resource before the V1. This is an important **breaking change**. In the previous versions usually not setting the given parameter resulted in using the provider default. This was different from creating the same object without the parameter by hand (because Snowflake just takes the parameter from the hierarchy in such case). - provider will identify both the internal and the external changes to these parameters on both `value` and `level` levels, e.g.: - setting the parameter inside the config and then manually unsetting it to the same value on the higher level will result in detecting a change diff --git a/v1-preparations/ESSENTIAL_GA_OBJECTS.MD b/v1-preparations/ESSENTIAL_GA_OBJECTS.MD index e468373d56..9e9d3ea9f1 100644 --- a/v1-preparations/ESSENTIAL_GA_OBJECTS.MD +++ b/v1-preparations/ESSENTIAL_GA_OBJECTS.MD @@ -21,7 +21,7 @@ newer provider versions. We will address these while working on the given object | RESOURCE MONITOR | ❌ | [#1990](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1990), [#1832](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1832), [#1821](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1821), [#1754](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1754), [#1716](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1716), [#1714](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1714), [#1624](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1624), [#1500](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1500), [#1175](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1175) | | ROLE | 👨‍💻 | - | | SECURITY INTEGRATION | 🚀 | [#2855](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2855), [#2719](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2719), [#2568](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2568), [#2177](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2177), [#1851](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1851), [#1773](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1773), [#1741](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1741), [#1637](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1637), [#1503](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1503), [#1498](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1498), [#1421](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1421), [#1224](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1224) | -| USER | 👨‍💻 | [#2942](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2942), [#2938](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2938), [#2902](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2902), [#2817](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2817), [#2662](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2662), [#1572](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1572), [#1535](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1535), [#1155](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1155) | +| USER | 👨‍💻 | [#2970](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2970), [#2951](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2951), [#2942](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2942), [#2938](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2938), [#2902](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2902), [#2817](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2817), [#2662](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2662), [#1572](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1572), [#1535](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1535), [#1155](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1155) | | WAREHOUSE | 🚀 | issues in the older versions: [resources](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues?q=label%3Aresource%3Awarehouse+) and [datasources](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues?q=label%3Adata_source%3Awarehouses+) | | FUNCTION | ❌ | [2859](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2859), [#2735](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2735), [#2426](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2426), [#1479](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1479), [#1393](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1393), [#1208](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1208), [#1079](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1079) | | MASKING POLICY | ❌ | [#2236](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2236), [#2035](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2035), [#1799](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1799), [#1764](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1764), [#1656](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1656), [#1444](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1444), [#1422](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1422), [#1097](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1097) | diff --git a/v1-preparations/REMAINING_GA_OBJECTS.MD b/v1-preparations/REMAINING_GA_OBJECTS.MD index ebdb328e3c..36a3b4f483 100644 --- a/v1-preparations/REMAINING_GA_OBJECTS.MD +++ b/v1-preparations/REMAINING_GA_OBJECTS.MD @@ -22,11 +22,11 @@ Known issues lists open issues touching the given object. Note that some of thes | EXTERNAL ACCESS INTEGRATION | ❌ | [#2546](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2546) | | FAILOVER GROUP | ❌ | [#2516](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2516), [#2332](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2332), [#1418](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1418) | | MANAGED ACCOUNT | ❌ | - | -| NOTIFICATION INTEGRATION | ❌ | [#1051](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1051) | +| NOTIFICATION INTEGRATION | ❌ | [#2966](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2966), [#2965](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2965), [#1051](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1051) | | REPLICATION GROUP | ❌ | [#1602](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1602) | | SHARE | ❌ | [#2189](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2189), [#1279](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1279), [#630](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/630) | | STORAGE INTEGRATION | ❌ | [#2624](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2624), [#1445](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1445) | -| ALERT | ❌ | [#2829](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2829), [#2541](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2541), [#1811](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1811), [#1753](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1753) | +| ALERT | ❌ | [#2963](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2963), [#2829](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2829), [#2541](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2541), [#1811](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1811), [#1753](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1753) | | DYNAMIC TABLE | ❌ | - | | EVENT TABLE | ❌ | [#1888](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1888) | | EXTERNAL FUNCTION | ❌ | [#1901](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1901) | @@ -39,4 +39,4 @@ Known issues lists open issues touching the given object. Note that some of thes | PIPE | ❌ | [#2785](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2785), [#2075](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2075), [#1781](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1781), [#1707](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1707), [#1478](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1478), [#533](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/533) | | SECRET | ❌ | [#2545](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2545) | | SEQUENCE | ❌ | [#2589](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2589) | -| SESSION POLICY | ❌ | [#2870](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2870) | +| SESSION POLICY | ❌ | [#2870](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2870) |