diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000..5a91344267 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,32 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' + +--- + +**Provider Version** + +The provider version you are using. + +**Terraform Version** + +The version of Terraform you were using when the bug was encountered. + +**Describe the bug** + +A clear and concise description of what the bug is. + +**Expected behavior** + +A clear and concise description of what you expected to happen. + +**Code samples and commands** + +Please add code examples and commands that were run to cause the problem. + +**Additional context** + +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000000..28e4e06a9d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,24 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: feature-request +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** + +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** + +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** + +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** + +Add any other context or screenshots about the feature request here. diff --git a/Makefile b/Makefile index b745a5569d..b631f1a0df 100644 --- a/Makefile +++ b/Makefile @@ -99,12 +99,12 @@ clean: ## clean the repo rm -rf dist .PHONY: clean -docs: build ## generate some docs - ./scripts/update-readme.sh update +docs: + go run ./docgen .PHONY: docs -check-docs: build ## check that docs have been generated - ./scripts/update-readme.sh check +check-docs: docs ## check that docs have been generated + git diff --exit-code -- docs .PHONY: check-docs check-mod: diff --git a/README.md b/README.md index 0512c7661c..fdf9db37c2 100644 --- a/README.md +++ b/README.md @@ -24,426 +24,9 @@ You can also just download a binary from our [releases](https://github.com/chanz TODO fogg config -## Authentication +## Usage -We currently support username + password, browser and keypair authenthication. We suggest that you do so via environment variables. Define a config with the non-senstive field like- - -```hcl -provider "snowflake" { - account = "..." - role = "..." - region = "..." -} -``` - -Then set `SNOWFLAKE_USER` and either `SNOWFLAKE_PASSWORD` or `SNOWFLAKE_PRIVATE_KEY_PATH`. - -### Keypair Authentication Environment Variables -You should generate the public and private keys and set up environment variables. - -```shell -cd ~/.ssh -openssl genrsa -out snowflake_key 4096 -openssl rsa -in snowflake_key -pubout -out snowflake_key.pub -``` - -To export the variables into your provider: -```shell -export SNOWFLAKE_USER="..." -export SNOWFLAKE_PRIVATE_KEY_PATH="~/.ssh/snowflake_key" -``` -### OAuth Access Token -If you have an OAuth access token, export these credentials as environment variables: -```shell -export SNOWFLAKE_USER='...' -export SNOWFLAKE_OAUTH_ACCESS_TOKEN='...' -``` - -Note that once this access token expires, you'll need to request a new one through an external application. - -### Username and Password Environment Variables -If you choose to use Username and Password Authentication, export these credentials: -```shell -export SNOWFLAKE_USER='...' -export SNOWFLAKE_PASSWORD='...' -``` - -## Resources - -We support managing a subset of snowflakedb resources, with a focus on access control and management. We've built and support the resources we use. If you are lookig for others to be supported we are more than happy to get PRs merged. - -You can see a number of examples [here](examples). - - - -### snowflake_account_grant - -**Note**: The snowflake_account_grant resource creates exclusive attachments of grants. -Across the entire Snowflake account, all of the accounts to which a single grant is attached must be declared -by a single snowflake_account_grant resource. This means that even any snowflake_account that have the attached -grant via any other mechanism (including other Terraform resources) will have that attached grant revoked by this resource. -These resources do not enforce exclusive attachment of a grant, it is the user's responsibility to enforce this. - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|-----------|--------|---------------------------------------|----------|-----------|----------|---------| -| privilege | string | The privilege to grant on the schema. | true | false | false | "USAGE" | -| roles | set | Grants privilege to these roles. | true | false | false | | - -### snowflake_database - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|-----------------------------|--------|-------------------------------------------------------------------------------|----------|-----------|----------|---------| -| comment | string | | true | false | false | "" | -| data_retention_time_in_days | int | | true | false | true | | -| from_database | string | Specify a database to create a clone from. | true | false | false | | -| from_share | map | Specify a provider and a share in this map to create a database from a share. | true | false | false | | -| name | string | | false | true | false | | - -### snowflake_database_grant - -**Note**: The snowflake_database_grant resource creates exclusive attachments of grants. -Across the entire Snowflake account, all of the databases to which a single grant is attached must be declared -by a single snowflake_database_grant resource. This means that even any snowflake_database that have the attached -grant via any other mechanism (including other Terraform resources) will have that attached grant revoked by this resource. -These resources do not enforce exclusive attachment of a grant, it is the user's responsibility to enforce this. - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|---------------|--------|--------------------------------------------------------|----------|-----------|----------|---------| -| database_name | string | The name of the database on which to grant privileges. | false | true | false | | -| privilege | string | The privilege to grant on the database. | true | false | false | "USAGE" | -| roles | set | Grants privilege to these roles. | true | false | false | | -| shares | set | Grants privilege to these shares. | true | false | false | | - -### snowflake_integration_grant - -**Note**: The snowflake_integration_grant resource creates exclusive attachments of grants. -Across the entire Snowflake account, all of the integrations to which a single grant is attached must be declared -by a single snowflake_integration_grant resource. This means that even any snowflake_integration that have the attached -grant via any other mechanism (including other Terraform resources) will have that attached grant revoked by this resource. -These resources do not enforce exclusive attachment of a grant, it is the user's responsibility to enforce this. - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|------------------|--------|------------------------------------------------------------------|----------|-----------|----------|---------| -| integration_name | string | Identifier for the integration; must be unique for your account. | false | true | false | | -| privilege | string | The privilege to grant on the integration. | true | false | false | "USAGE" | -| roles | set | Grants privilege to these roles. | true | false | false | | - -### snowflake_managed_account - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|----------------|--------|------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|----------| -| admin_name | string | Identifier, as well as login name, for the initial user in the managed account. This user serves as the account administrator for the account. | false | true | false | | -| admin_password | string | Password for the initial user in the managed account. | false | true | false | | -| cloud | string | Cloud in which the managed account is located. | false | false | true | | -| comment | string | Specifies a comment for the managed account. | true | false | false | | -| created_on | string | Date and time when the managed account was created. | false | false | true | | -| locator | string | Display name of the managed account. | false | false | true | | -| name | string | Identifier for the managed account; must be unique for your account. | false | true | false | | -| region | string | Snowflake Region in which the managed account is located. | false | false | true | | -| type | string | Specifies the type of managed account. | true | false | false | "READER" | -| url | string | URL for accessing the managed account, particularly through the web interface. | false | false | true | | - -### snowflake_pipe - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|----------------------|--------|-----------------------------------------------------------------------------------------------------------------|----------|-----------|----------|---------| -| auto_ingest | bool | Specifies a auto_ingest param for the pipe. | true | false | false | false | -| aws_sns_topic | string | Specifies AWS SNS Topic that SQS managed by Snowflake will subscribe to. | true | false | false | | -| comment | string | Specifies a comment for the pipe. | true | false | false | | -| copy_statement | string | Specifies the copy statement for the pipe. | false | true | false | | -| database | string | The database in which to create the pipe. | false | true | false | | -| name | string | Specifies the identifier for the pipe; must be unique for the database and schema in which the pipe is created. | false | true | false | | -| notification_channel | string | Amazon Resource Name of the Amazon SQS queue for the stage named in the DEFINITION column. | false | false | true | | -| owner | string | Name of the role that owns the pipe. | false | false | true | | -| schema | string | The schema in which to create the pipe. | false | true | false | | - -### snowflake_resource_monitor - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|----------------------------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|---------| -| credit_quota | float | The amount of credits allocated monthly to the resource monitor, round up to 2 decimal places. | true | false | true | | -| end_timestamp | string | The date and time when the resource monitor suspends the assigned warehouses. | true | false | false | | -| frequency | string | The frequency interval at which the credit usage resets to 0. If you set a frequency for a resource monitor, you must also set START_TIMESTAMP. | true | false | true | | -| name | string | Identifier for the resource monitor; must be unique for your account. | false | true | false | | -| notify_triggers | set | A list of percentage thresholds at which to send an alert to subscribed users. | true | false | false | | -| start_timestamp | string | The date and time when the resource monitor starts monitoring credit usage for the assigned warehouses. | true | false | true | | -| suspend_immediate_triggers | set | A list of percentage thresholds at which to immediately suspend all warehouses. | true | false | false | | -| suspend_triggers | set | A list of percentage thresholds at which to suspend all warehouses. | true | false | false | | - -### snowflake_resource_monitor_grant - -**Note**: The snowflake_resource_monitor_grant resource creates exclusive attachments of grants. -Across the entire Snowflake account, all of the resource_monitors to which a single grant is attached must be declared -by a single snowflake_resource_monitor_grant resource. This means that even any snowflake_resource_monitor that have the attached -grant via any other mechanism (including other Terraform resources) will have that attached grant revoked by this resource. -These resources do not enforce exclusive attachment of a grant, it is the user's responsibility to enforce this. - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|--------------|--------|-----------------------------------------------------------------------|----------|-----------|----------|-----------| -| monitor_name | string | Identifier for the resource monitor; must be unique for your account. | false | true | false | | -| privilege | string | The privilege to grant on the resource monitor. | true | false | false | "MONITOR" | -| roles | set | Grants privilege to these roles. | true | false | false | | - -### snowflake_role - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|---------|--------|-------------|----------|-----------|----------|---------| -| comment | string | | true | false | false | | -| name | string | | false | true | false | | - -### snowflake_role_grants - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|-----------|--------|---------------------------------------|----------|-----------|----------|---------| -| role_name | string | The name of the role we are granting. | false | true | false | | -| roles | set | Grants role to this specified role. | true | false | false | | -| users | set | Grants role to this specified user. | true | false | false | | - -### snowflake_schema - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|---------------------|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|---------| -| comment | string | Specifies a comment for the schema. | true | false | false | | -| data_retention_days | int | Specifies the number of days for which Time Travel actions (CLONE and UNDROP) can be performed on the schema, as well as specifying the default Time Travel retention time for all tables created in the schema. | true | false | false | 1 | -| database | string | The database in which to create the schema. | false | true | false | | -| is_managed | bool | Specifies a managed schema. Managed access schemas centralize privilege management with the schema owner. | true | false | false | false | -| is_transient | bool | Specifies a 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. | true | false | false | false | -| name | string | Specifies the identifier for the schema; must be unique for the database in which the schema is created. | false | true | false | | - -### snowflake_schema_grant - -**Note**: The snowflake_schema_grant resource creates exclusive attachments of grants. -Across the entire Snowflake account, all of the schemas to which a single grant is attached must be declared -by a single snowflake_schema_grant resource. This means that even any snowflake_schema that have the attached -grant via any other mechanism (including other Terraform resources) will have that attached grant revoked by this resource. -These resources do not enforce exclusive attachment of a grant, it is the user's responsibility to enforce this. - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|---------------|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|---------| -| database_name | string | The name of the database containing the schema on which to grant privileges. | false | true | false | | -| on_future | bool | When this is set to true, apply this grant on all future schemas in the given database. The schema_name and shares fields must be unset in order to use on_future. | true | false | false | false | -| privilege | string | The privilege to grant on the current or future schema. Note that if "OWNERSHIP" is specified, ensure that the role that terraform is using is granted access. | true | false | false | "USAGE" | -| roles | set | Grants privilege to these roles. | true | false | false | | -| schema_name | string | The name of the schema on which to grant privileges. | true | false | false | | -| shares | set | Grants privilege to these shares (only valid if on_future is unset). | true | false | false | | - -### snowflake_share - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|----------|--------|-------------------------------------------------------------------------------------------------------|----------|-----------|----------|---------| -| accounts | list | A list of accounts to be added to the share. | true | false | false | | -| comment | string | Specifies a comment for the managed account. | true | false | false | | -| name | string | Specifies the identifier for the share; must be unique for the account in which the share is created. | false | true | false | | - -### snowflake_stage - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|---------------------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|---------| -| aws_external_id | string | | true | false | true | | -| comment | string | Specifies a comment for the stage. | true | false | false | | -| copy_options | string | Specifies the copy options for the stage. | true | false | false | | -| credentials | string | Specifies the credentials for the stage. | true | false | false | | -| database | string | The database in which to create the stage. | false | true | false | | -| encryption | string | Specifies the encryption settings for the stage. | true | false | false | | -| file_format | string | Specifies the file format for the stage. | true | false | false | | -| name | string | Specifies the identifier for the stage; must be unique for the database and schema in which the stage is created. | false | true | false | | -| schema | string | The schema in which to create the stage. | false | true | false | | -| snowflake_iam_user | string | | true | false | true | | -| storage_integration | string | Specifies the name of the storage integration used to delegate authentication responsibility for external cloud storage to a Snowflake identity and access management (IAM) entity. | true | false | false | | -| url | string | Specifies the URL for the stage. | true | false | false | | - -### snowflake_stage_grant - -**Note**: The snowflake_stage_grant resource creates exclusive attachments of grants. -Across the entire Snowflake account, all of the stages to which a single grant is attached must be declared -by a single snowflake_stage_grant resource. This means that even any snowflake_stage that have the attached -grant via any other mechanism (including other Terraform resources) will have that attached grant revoked by this resource. -These resources do not enforce exclusive attachment of a grant, it is the user's responsibility to enforce this. - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|---------------|--------|-------------------------------------------------------------------------------------|----------|-----------|----------|---------| -| database_name | string | The name of the database containing the current stage on which to grant privileges. | false | true | false | | -| privilege | string | The privilege to grant on the stage. | true | false | false | "USAGE" | -| roles | set | Grants privilege to these roles. | true | false | false | | -| schema_name | string | The name of the schema containing the current stage on which to grant privileges. | false | true | false | | -| shares | set | Grants privilege to these shares. | true | false | false | | -| stage_name | string | The name of the stage on which to grant privileges. | false | true | false | | - -### snowflake_storage_integration - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|---------------------------|--------|---------------------------------------------------------------------------------------------------------------|----------|-----------|----------|------------------| -| azure_tenant_id | string | | true | false | false | "" | -| comment | string | | true | false | false | "" | -| created_on | string | Date and time when the storage integration was created. | false | false | true | | -| enabled | bool | | true | false | false | true | -| name | string | | false | true | false | | -| storage_allowed_locations | list | Explicitly limits external stages that use the integration to reference one or more storage locations. | false | true | false | | -| storage_aws_external_id | string | The external ID that Snowflake will use when assuming the AWS role. | false | false | true | | -| storage_aws_iam_user_arn | string | The Snowflake user that will attempt to assume the AWS role. | false | false | true | | -| storage_aws_role_arn | string | | true | false | false | "" | -| storage_blocked_locations | list | Explicitly prohibits external stages that use the integration from referencing one or more storage locations. | true | false | false | | -| storage_provider | string | | false | true | false | | -| type | string | | true | false | false | "EXTERNAL_STAGE" | - -### snowflake_table_grant - -**Note**: The snowflake_table_grant resource creates exclusive attachments of grants. -Across the entire Snowflake account, all of the tables to which a single grant is attached must be declared -by a single snowflake_table_grant resource. This means that even any snowflake_table that have the attached -grant via any other mechanism (including other Terraform resources) will have that attached grant revoked by this resource. -These resources do not enforce exclusive attachment of a grant, it is the user's responsibility to enforce this. - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|---------------|--------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|----------| -| database_name | string | The name of the database containing the current or future tables on which to grant privileges. | false | true | false | | -| on_future | bool | When this is set to true and a schema_name is provided, apply this grant on all future tables in the given schema. When this is true and no schema_name is provided apply this grant on all future tables in the given database. The table_name and shares fields must be unset in order to use on_future. | true | false | false | false | -| privilege | string | The privilege to grant on the current or future table. | true | false | false | "SELECT" | -| roles | set | Grants privilege to these roles. | true | false | false | | -| schema_name | string | The name of the schema containing the current or future tables on which to grant privileges. | true | false | false | | -| shares | set | Grants privilege to these shares (only valid if on_future is unset). | true | false | false | | -| table_name | string | The name of the table on which to grant privileges immediately (only valid if on_future is unset). | true | false | false | | - -### snowflake_task - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|----------------------|--------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|---------| -| after | string | Specifies the predecessor task in the same database and schema of the current task. When a run of the predecessor task finishes successfully, it triggers this task (after a brief lag). | true | false | false | | -| comment | string | Specifies a comment for the task. | true | false | false | | -| database | string | The database in which to create the task. | false | true | false | | -| enabled | bool | Specifies if the task should be started (enabled) after creation or should remain suspended (default). | true | false | false | false | -| name | string | Specifies the identifier for the task; must be unique for the database and schema in which the task is created. | false | true | false | | -| schedule | string | The schedule for periodically running the task. This can be a cron or interval in minutes. | true | false | false | | -| schema | string | The schema in which to create the task. | false | true | false | | -| session_parameters | map | Specifies session parameters to set for the session when the task runs. A task supports all session parameters. | true | false | false | | -| sql_statement | string | Any single SQL statement, or a call to a stored procedure, executed when the task runs. | false | true | false | | -| user_task_timeout_ms | int | Specifies the time limit on a single run of the task before it times out (in milliseconds). | true | false | false | | -| warehouse | string | The warehouse the task will use. | false | true | false | | -| when | string | Specifies a Boolean SQL expression; multiple conditions joined with AND/OR are supported. | true | false | false | | - -### snowflake_user - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|----------------------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|---------| -| comment | string | | true | false | false | | -| default_namespace | string | Specifies the namespace (database only or database and schema) that is active by default for the user’s session upon login. | true | false | false | | -| default_role | string | Specifies the role that is active by default for the user’s session upon login. | true | false | true | | -| default_warehouse | string | Specifies the virtual warehouse that is active by default for the user’s session upon login. | true | false | false | | -| disabled | bool | | true | false | true | | -| has_rsa_public_key | bool | Will be true if user as an RSA key set. | false | false | true | | -| login_name | string | The name users use to log in. If not supplied, snowflake will use name instead. | true | false | true | | -| must_change_password | bool | Specifies whether the user is forced to change their password on next login (including their first/initial login) into the system. | true | false | false | | -| name | string | Name of the user. Note that if you do not supply login_name this will be used as login_name. [doc](https://docs.snowflake.net/manuals/sql-reference/sql/create-user.html#required-parameters) | false | true | false | | -| password | string | **WARNING:** this will put the password in the terraform state file. Use carefully. | true | false | false | | -| 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. | true | false | false | | -| 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. | true | false | false | | - -### snowflake_view - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|-----------|--------|-------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|----------| -| comment | string | Specifies a comment for the view. | true | false | false | | -| database | string | The database in which to create the view. Don't use the | character. | false | true | false | | -| is_secure | bool | Specifies that the view is secure. | true | false | false | false | -| name | string | Specifies the identifier for the view; must be unique for the schema in which the view is created. Don't use the | character. | false | true | false | | -| schema | string | The schema in which to create the view. Don't use the | character. | true | false | false | "PUBLIC" | -| statement | string | Specifies the query used to create the view. | false | true | false | | - -### snowflake_view_grant - -**Note**: The snowflake_view_grant resource creates exclusive attachments of grants. -Across the entire Snowflake account, all of the views to which a single grant is attached must be declared -by a single snowflake_view_grant resource. This means that even any snowflake_view that have the attached -grant via any other mechanism (including other Terraform resources) will have that attached grant revoked by this resource. -These resources do not enforce exclusive attachment of a grant, it is the user's responsibility to enforce this. - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|---------------|--------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|----------| -| database_name | string | The name of the database containing the current or future views on which to grant privileges. | false | true | false | | -| on_future | bool | When this is set to true and a schema_name is provided, apply this grant on all future views in the given schema. When this is true and no schema_name is provided apply this grant on all future views in the given database. The view_name and shares fields must be unset in order to use on_future. | true | false | false | false | -| privilege | string | The privilege to grant on the current or future view. | true | false | false | "SELECT" | -| roles | set | Grants privilege to these roles. | true | false | false | | -| schema_name | string | The name of the schema containing the current or future views on which to grant privileges. | true | false | false | | -| shares | set | Grants privilege to these shares (only valid if on_future is unset). | true | false | false | | -| view_name | string | The name of the view on which to grant privileges immediately (only valid if on_future is unset). | true | false | false | | - -### snowflake_warehouse - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|------------------------------|--------|------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|---------| -| auto_resume | bool | Specifies whether to automatically resume a warehouse when a SQL statement (e.g. query) is submitted to it. | true | false | true | | -| auto_suspend | int | Specifies the number of seconds of inactivity after which a warehouse is automatically suspended. | true | false | true | | -| comment | string | | true | false | false | "" | -| initially_suspended | bool | Specifies whether the warehouse is created initially in the ‘Suspended’ state. | true | false | false | | -| max_cluster_count | int | Specifies the maximum number of server clusters for the warehouse. | true | false | true | | -| min_cluster_count | int | Specifies the minimum number of server clusters for the warehouse (only applies to multi-cluster warehouses). | true | false | true | | -| name | string | | false | true | false | | -| resource_monitor | string | Specifies the name of a resource monitor that is explicitly assigned to the warehouse. | true | false | true | | -| scaling_policy | string | Specifies the policy for automatically starting and shutting down clusters in a multi-cluster warehouse running in Auto-scale mode. | true | false | true | | -| statement_timeout_in_seconds | int | Specifies the time, in seconds, after which a running SQL statement (query, DDL, DML, etc.) is canceled by the system | true | false | false | 0 | -| wait_for_provisioning | bool | Specifies whether the warehouse, after being resized, waits for all the servers to provision before executing any queued or new queries. | true | false | false | | -| warehouse_size | string | | true | false | true | | - -### snowflake_warehouse_grant - -**Note**: The snowflake_warehouse_grant resource creates exclusive attachments of grants. -Across the entire Snowflake account, all of the warehouses to which a single grant is attached must be declared -by a single snowflake_warehouse_grant resource. This means that even any snowflake_warehouse that have the attached -grant via any other mechanism (including other Terraform resources) will have that attached grant revoked by this resource. -These resources do not enforce exclusive attachment of a grant, it is the user's responsibility to enforce this. - -#### properties - -| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | -|----------------|--------|---------------------------------------------------------|----------|-----------|----------|---------| -| privilege | string | The privilege to grant on the warehouse. | true | false | false | "USAGE" | -| roles | set | Grants privilege to these roles. | true | false | false | | -| warehouse_name | string | The name of the warehouse on which to grant privileges. | false | true | false | | - +In-depth docs are available [on the Terraform registry](https://registry.terraform.io/providers/chanzuckerberg/snowflake/latest). ## Development @@ -461,7 +44,7 @@ The 'unit' tests are run in `github.com/chanzuckerberg/terraform-provider-snowf You can run these first two sets of tests with `make test`. -The 'acceptance' tests run the full stack, creating, modifying and destroying resources in a live snowflake account. To run them you need a snowflake account and the proper environment variables set- SNOWFLAKE_ACCOUNT, SNOWFLAKE_USER, SNOWFLAKE_PASSWORD, SNOWFLAKE_ROLE. These tests are slower but have higher fidelity. +The 'acceptance' tests run the full stack, creating, modifying and destroying resources in a live snowflake account. To run them you need a snowflake account and the proper authentication set up. These tests are slower but have higher fidelity. To run all tests, including the acceptance tests, run `make test-acceptance`. diff --git a/docgen/main.go b/docgen/main.go new file mode 100644 index 0000000000..964057cbb1 --- /dev/null +++ b/docgen/main.go @@ -0,0 +1,111 @@ +package main + +import ( + "fmt" + "log" + "os" + "path" + "sort" + "strings" + + "github.com/chanzuckerberg/terraform-provider-snowflake/pkg/provider" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/olekukonko/tablewriter" +) + +func main() { + docsPath := "docs/resources" + + resources := provider.Provider().ResourcesMap + + for name, resource := range resources { + shortName := strings.TrimPrefix(name, "snowflake_") + + f, err := os.Create(path.Join(docsPath, fmt.Sprintf("%s.md", shortName))) + if err != nil { + log.Fatal(err) + } + + _, err = f.WriteString(fmt.Sprintf("\n# %s\n\n", name)) + if err != nil { + log.Fatalf("unable to write doc file %#v", err) + } + + _, err = f.WriteString("\n\n") + if err != nil { + log.Fatalf("unable to write doc file %#v", err) + } + + if strings.HasSuffix(name, "_grant") { + grant_resource_name := strings.Replace(name, "_grant", "", -1) + granted_to_name := strings.Replace(grant_resource_name, "snowflake_", "", -1) + _, err := f.WriteString(fmt.Sprintf( + `**Note**: The %s resource creates exclusive attachments of grants. + Across the entire Snowflake account, all of the %ss to which a single grant is attached must be declared + by a single %s resource. This means that even any %s that have the attached + grant via any other mechanism (including other Terraform resources) will have that attached grant revoked by this resource. + These resources do not enforce exclusive attachment of a grant, it is the user's responsibility to enforce this. + `, name, granted_to_name, name, grant_resource_name)) + if err != nil { + log.Fatalf("unable to write doc file %#v", err) + } + _, err = f.WriteString("\n") + if err != nil { + log.Fatalf("unable to write doc file %#v", err) + } + } + _, err = f.WriteString("## properties\n\n") + if err != nil { + log.Fatalf("unable to write doc file %#v", err) + } + + table := tablewriter.NewWriter(f) + table.SetAutoWrapText(false) + table.SetHeader([]string{"name", "type", "description", "optional", " required", "computed", "default"}) + table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) + table.SetCenterSeparator("|") + + properties := make([]string, 0) + for k := range resource.Schema { + properties = append(properties, k) + } + sort.Strings(properties) + for _, property := range properties { + s := resource.Schema[property] + table.Append([]string{property, typeString(s.Type), s.Description, boolString(s.Optional), boolString(s.Required), boolString(s.Computed), interfaceString(s.Default)}) + } + table.Render() + f.Close() + } +} + +func typeString(t schema.ValueType) string { + switch t { + case schema.TypeBool: + return "bool" + case schema.TypeInt: + return "int" + case schema.TypeFloat: + return "float" + case schema.TypeString: + return "string" + case schema.TypeList: + return "list" + case schema.TypeMap: + return "map" + case schema.TypeSet: + return "set" + } + return "?" +} + +func boolString(t bool) string { + return fmt.Sprintf("%t", t) +} + +func interfaceString(t interface{}) string { + if t == nil { + return "" + } + return fmt.Sprintf("%#v", t) +} diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000000..dd3c6b6e7c --- /dev/null +++ b/docs/index.md @@ -0,0 +1,94 @@ +# Snowflake Provider + +This is a terraform provider plugin for managing [Snowflake](http://snowflakedb.com) accounts. +Coverage is focused on part of Snowflake related to access control. + +## Example + +```hcl +provider snowflake { + // required + username = "..." + account = "..." + region = "..." + + // optional, at exactly one must be set + password = "..." + oauth_access_token = "..." + private_key_path = "..." + + // optional + role = "..." +} +``` + +## Authentication + +The Snowflake provider support multiple ways to authenticate: + +* Password +* OAuth Access Token +* Browser Auth +* Private Key + +In all cases account, username, and region are required. + +### Keypair Authentication Environment Variables + +You should generate the public and private keys and set up environment variables. + +```shell + +cd ~/.ssh +openssl genrsa -out snowflake_key 4096 +openssl rsa -in snowflake_key -pubout -out snowflake_key.pub +``` + +To export the variables into your provider: + +```shell +export SNOWFLAKE_USER="..." +export SNOWFLAKE_PRIVATE_KEY_PATH="~/.ssh/snowflake_key" +``` + +### OAuth Access Token + +If you have an OAuth access token, export these credentials as environment variables: + +```shell +export SNOWFLAKE_USER='...' +export SNOWFLAKE_OAUTH_ACCESS_TOKEN='...' +``` + +Note that once this access token expires, you'll need to request a new one through an external application. + +### Username and Password Environment Variables + +If you choose to use Username and Password Authentication, export these credentials: + +```shell +export SNOWFLAKE_USER='...' +export SNOWFLAKE_PASSWORD='...' +``` + +## Argument Reference + +In addition to [generic `provider` arguments](https://www.terraform.io/docs/configuration/providers.html) +(e.g. `alias` and `version`), the following arguments are supported in the Snowflake + `provider` block: + +* `account` - (required) The name of the Snowflake account. Can also come from the + `SNOWFLAKE_ACCOUNT` environment variable. +* `username` - (required) Username for username+password authentication. Can come from the + `SNOWFLAKE_PASSWORD` environment variable. +* `region` - (required) [Snowflake region](https://docs.snowflake.com/en/user-guide/intro-regions.html) to use. Can be source from the `SNOWFLAKE_REGION` environment variable. +* `password` - (optional) Password for username+password auth. Cannot be used with `browser_auth` or + `private_key_path`. Can be source from `SNOWFLAKE_PASSWORD` environment variable. +* `oauth_access_token` - (optional) Token for use with OAuth. Generating the token is left to other + tools. Cannot be used with `browser_auth`, `private_key_path` or `password`. Can be source from + `SNOWFLAKE_OAUTH_ACCESS_TOKEN` environment variable. +* `private_key_path` - (optional) Path to a private key for using keypair authentication.. Cannot be + used with `browser_auth`, `oauth_access_token` or `password`. Can be source from + `SNOWFLAKE_PRIVATE_KEY_PATH` environment variable. +* `role` - (optional) Snowflake role to use for operations. If left unset, default role for user + will be used. Can come from the `SNOWFLAKE_ROLE` environment variable. diff --git a/docs/resources/account_grant.md b/docs/resources/account_grant.md new file mode 100644 index 0000000000..7ce685f9c9 --- /dev/null +++ b/docs/resources/account_grant.md @@ -0,0 +1,17 @@ + +# snowflake_account_grant + + + +**Note**: The snowflake_account_grant resource creates exclusive attachments of grants. + Across the entire Snowflake account, all of the accounts to which a single grant is attached must be declared + by a single snowflake_account_grant resource. This means that even any snowflake_account that have the attached + grant via any other mechanism (including other Terraform resources) will have that attached grant revoked by this resource. + These resources do not enforce exclusive attachment of a grant, it is the user's responsibility to enforce this. + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|-----------|--------|---------------------------------------|----------|-----------|----------|---------| +| privilege | string | The privilege to grant on the schema. | true | false | false | "USAGE" | +| roles | set | Grants privilege to these roles. | true | false | false | | diff --git a/docs/resources/database.md b/docs/resources/database.md new file mode 100644 index 0000000000..33da12cdce --- /dev/null +++ b/docs/resources/database.md @@ -0,0 +1,14 @@ + +# snowflake_database + + + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|-----------------------------|--------|-------------------------------------------------------------------------------|----------|-----------|----------|---------| +| comment | string | | true | false | false | "" | +| data_retention_time_in_days | int | | true | false | true | | +| from_database | string | Specify a database to create a clone from. | true | false | false | | +| from_share | map | Specify a provider and a share in this map to create a database from a share. | true | false | false | | +| name | string | | false | true | false | | diff --git a/docs/resources/database_grant.md b/docs/resources/database_grant.md new file mode 100644 index 0000000000..d600dd871d --- /dev/null +++ b/docs/resources/database_grant.md @@ -0,0 +1,19 @@ + +# snowflake_database_grant + + + +**Note**: The snowflake_database_grant resource creates exclusive attachments of grants. + Across the entire Snowflake account, all of the databases to which a single grant is attached must be declared + by a single snowflake_database_grant resource. This means that even any snowflake_database that have the attached + grant via any other mechanism (including other Terraform resources) will have that attached grant revoked by this resource. + These resources do not enforce exclusive attachment of a grant, it is the user's responsibility to enforce this. + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|---------------|--------|--------------------------------------------------------|----------|-----------|----------|---------| +| database_name | string | The name of the database on which to grant privileges. | false | true | false | | +| privilege | string | The privilege to grant on the database. | true | false | false | "USAGE" | +| roles | set | Grants privilege to these roles. | true | false | false | | +| shares | set | Grants privilege to these shares. | true | false | false | | diff --git a/docs/resources/integration_grant.md b/docs/resources/integration_grant.md new file mode 100644 index 0000000000..a04eeb4941 --- /dev/null +++ b/docs/resources/integration_grant.md @@ -0,0 +1,18 @@ + +# snowflake_integration_grant + + + +**Note**: The snowflake_integration_grant resource creates exclusive attachments of grants. + Across the entire Snowflake account, all of the integrations to which a single grant is attached must be declared + by a single snowflake_integration_grant resource. This means that even any snowflake_integration that have the attached + grant via any other mechanism (including other Terraform resources) will have that attached grant revoked by this resource. + These resources do not enforce exclusive attachment of a grant, it is the user's responsibility to enforce this. + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|------------------|--------|------------------------------------------------------------------|----------|-----------|----------|---------| +| integration_name | string | Identifier for the integration; must be unique for your account. | false | true | false | | +| privilege | string | The privilege to grant on the integration. | true | false | false | "USAGE" | +| roles | set | Grants privilege to these roles. | true | false | false | | diff --git a/docs/resources/managed_account.md b/docs/resources/managed_account.md new file mode 100644 index 0000000000..619828a895 --- /dev/null +++ b/docs/resources/managed_account.md @@ -0,0 +1,19 @@ + +# snowflake_managed_account + + + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|----------------|--------|------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|----------| +| admin_name | string | Identifier, as well as login name, for the initial user in the managed account. This user serves as the account administrator for the account. | false | true | false | | +| admin_password | string | Password for the initial user in the managed account. | false | true | false | | +| cloud | string | Cloud in which the managed account is located. | false | false | true | | +| comment | string | Specifies a comment for the managed account. | true | false | false | | +| created_on | string | Date and time when the managed account was created. | false | false | true | | +| locator | string | Display name of the managed account. | false | false | true | | +| name | string | Identifier for the managed account; must be unique for your account. | false | true | false | | +| region | string | Snowflake Region in which the managed account is located. | false | false | true | | +| type | string | Specifies the type of managed account. | true | false | false | "READER" | +| url | string | URL for accessing the managed account, particularly through the web interface. | false | false | true | | diff --git a/docs/resources/pipe.md b/docs/resources/pipe.md new file mode 100644 index 0000000000..2371425981 --- /dev/null +++ b/docs/resources/pipe.md @@ -0,0 +1,17 @@ + +# snowflake_pipe + + + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|----------------------|--------|-----------------------------------------------------------------------------------------------------------------|----------|-----------|----------|---------| +| auto_ingest | bool | Specifies a auto_ingest param for the pipe. | true | false | false | false | +| comment | string | Specifies a comment for the pipe. | true | false | false | | +| copy_statement | string | Specifies the copy statement for the pipe. | false | true | false | | +| database | string | The database in which to create the pipe. | false | true | false | | +| name | string | Specifies the identifier for the pipe; must be unique for the database and schema in which the pipe is created. | false | true | false | | +| notification_channel | string | Amazon Resource Name of the Amazon SQS queue for the stage named in the DEFINITION column. | false | false | true | | +| owner | string | Name of the role that owns the pipe. | false | false | true | | +| schema | string | The schema in which to create the pipe. | false | true | false | | diff --git a/docs/resources/resource_monitor.md b/docs/resources/resource_monitor.md new file mode 100644 index 0000000000..38c1e71588 --- /dev/null +++ b/docs/resources/resource_monitor.md @@ -0,0 +1,17 @@ + +# snowflake_resource_monitor + + + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|----------------------------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|---------| +| credit_quota | float | The amount of credits allocated monthly to the resource monitor, round up to 2 decimal places. | true | false | true | | +| end_timestamp | string | The date and time when the resource monitor suspends the assigned warehouses. | true | false | false | | +| frequency | string | The frequency interval at which the credit usage resets to 0. If you set a frequency for a resource monitor, you must also set START_TIMESTAMP. | true | false | true | | +| name | string | Identifier for the resource monitor; must be unique for your account. | false | true | false | | +| notify_triggers | set | A list of percentage thresholds at which to send an alert to subscribed users. | true | false | false | | +| start_timestamp | string | The date and time when the resource monitor starts monitoring credit usage for the assigned warehouses. | true | false | true | | +| suspend_immediate_triggers | set | A list of percentage thresholds at which to immediately suspend all warehouses. | true | false | false | | +| suspend_triggers | set | A list of percentage thresholds at which to suspend all warehouses. | true | false | false | | diff --git a/docs/resources/resource_monitor_grant.md b/docs/resources/resource_monitor_grant.md new file mode 100644 index 0000000000..dc135aacc8 --- /dev/null +++ b/docs/resources/resource_monitor_grant.md @@ -0,0 +1,18 @@ + +# snowflake_resource_monitor_grant + + + +**Note**: The snowflake_resource_monitor_grant resource creates exclusive attachments of grants. + Across the entire Snowflake account, all of the resource_monitors to which a single grant is attached must be declared + by a single snowflake_resource_monitor_grant resource. This means that even any snowflake_resource_monitor that have the attached + grant via any other mechanism (including other Terraform resources) will have that attached grant revoked by this resource. + These resources do not enforce exclusive attachment of a grant, it is the user's responsibility to enforce this. + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|--------------|--------|-----------------------------------------------------------------------|----------|-----------|----------|-----------| +| monitor_name | string | Identifier for the resource monitor; must be unique for your account. | false | true | false | | +| privilege | string | The privilege to grant on the resource monitor. | true | false | false | "MONITOR" | +| roles | set | Grants privilege to these roles. | true | false | false | | diff --git a/docs/resources/role.md b/docs/resources/role.md new file mode 100644 index 0000000000..f998296689 --- /dev/null +++ b/docs/resources/role.md @@ -0,0 +1,11 @@ + +# snowflake_role + + + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|---------|--------|-------------|----------|-----------|----------|---------| +| comment | string | | true | false | false | | +| name | string | | false | true | false | | diff --git a/docs/resources/role_grants.md b/docs/resources/role_grants.md new file mode 100644 index 0000000000..3399559534 --- /dev/null +++ b/docs/resources/role_grants.md @@ -0,0 +1,12 @@ + +# snowflake_role_grants + + + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|-----------|--------|---------------------------------------|----------|-----------|----------|---------| +| role_name | string | The name of the role we are granting. | false | true | false | | +| roles | set | Grants role to this specified role. | true | false | false | | +| users | set | Grants role to this specified user. | true | false | false | | diff --git a/docs/resources/schema.md b/docs/resources/schema.md new file mode 100644 index 0000000000..71b7415d26 --- /dev/null +++ b/docs/resources/schema.md @@ -0,0 +1,15 @@ + +# snowflake_schema + + + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|---------------------|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|---------| +| comment | string | Specifies a comment for the schema. | true | false | false | | +| data_retention_days | int | Specifies the number of days for which Time Travel actions (CLONE and UNDROP) can be performed on the schema, as well as specifying the default Time Travel retention time for all tables created in the schema. | true | false | false | 1 | +| database | string | The database in which to create the schema. | false | true | false | | +| is_managed | bool | Specifies a managed schema. Managed access schemas centralize privilege management with the schema owner. | true | false | false | false | +| is_transient | bool | Specifies a 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. | true | false | false | false | +| name | string | Specifies the identifier for the schema; must be unique for the database in which the schema is created. | false | true | false | | diff --git a/docs/resources/schema_grant.md b/docs/resources/schema_grant.md new file mode 100644 index 0000000000..5e6344291f --- /dev/null +++ b/docs/resources/schema_grant.md @@ -0,0 +1,21 @@ + +# snowflake_schema_grant + + + +**Note**: The snowflake_schema_grant resource creates exclusive attachments of grants. + Across the entire Snowflake account, all of the schemas to which a single grant is attached must be declared + by a single snowflake_schema_grant resource. This means that even any snowflake_schema that have the attached + grant via any other mechanism (including other Terraform resources) will have that attached grant revoked by this resource. + These resources do not enforce exclusive attachment of a grant, it is the user's responsibility to enforce this. + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|---------------|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|---------| +| database_name | string | The name of the database containing the schema on which to grant privileges. | false | true | false | | +| on_future | bool | When this is set to true, apply this grant on all future schemas in the given database. The schema_name and shares fields must be unset in order to use on_future. | true | false | false | false | +| privilege | string | The privilege to grant on the current or future schema. Note that if "OWNERSHIP" is specified, ensure that the role that terraform is using is granted access. | true | false | false | "USAGE" | +| roles | set | Grants privilege to these roles. | true | false | false | | +| schema_name | string | The name of the schema on which to grant privileges. | true | false | false | | +| shares | set | Grants privilege to these shares (only valid if on_future is unset). | true | false | false | | diff --git a/docs/resources/share.md b/docs/resources/share.md new file mode 100644 index 0000000000..cab58c21c5 --- /dev/null +++ b/docs/resources/share.md @@ -0,0 +1,12 @@ + +# snowflake_share + + + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|----------|--------|-------------------------------------------------------------------------------------------------------|----------|-----------|----------|---------| +| accounts | list | A list of accounts to be added to the share. | true | false | false | | +| comment | string | Specifies a comment for the managed account. | true | false | false | | +| name | string | Specifies the identifier for the share; must be unique for the account in which the share is created. | false | true | false | | diff --git a/docs/resources/stage.md b/docs/resources/stage.md new file mode 100644 index 0000000000..df40b17826 --- /dev/null +++ b/docs/resources/stage.md @@ -0,0 +1,21 @@ + +# snowflake_stage + + + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|---------------------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|---------| +| aws_external_id | string | | true | false | true | | +| comment | string | Specifies a comment for the stage. | true | false | false | | +| copy_options | string | Specifies the copy options for the stage. | true | false | false | | +| credentials | string | Specifies the credentials for the stage. | true | false | false | | +| database | string | The database in which to create the stage. | false | true | false | | +| encryption | string | Specifies the encryption settings for the stage. | true | false | false | | +| file_format | string | Specifies the file format for the stage. | true | false | false | | +| name | string | Specifies the identifier for the stage; must be unique for the database and schema in which the stage is created. | false | true | false | | +| schema | string | The schema in which to create the stage. | false | true | false | | +| snowflake_iam_user | string | | true | false | true | | +| storage_integration | string | Specifies the name of the storage integration used to delegate authentication responsibility for external cloud storage to a Snowflake identity and access management (IAM) entity. | true | false | false | | +| url | string | Specifies the URL for the stage. | true | false | false | | diff --git a/docs/resources/stage_grant.md b/docs/resources/stage_grant.md new file mode 100644 index 0000000000..71086027f9 --- /dev/null +++ b/docs/resources/stage_grant.md @@ -0,0 +1,21 @@ + +# snowflake_stage_grant + + + +**Note**: The snowflake_stage_grant resource creates exclusive attachments of grants. + Across the entire Snowflake account, all of the stages to which a single grant is attached must be declared + by a single snowflake_stage_grant resource. This means that even any snowflake_stage that have the attached + grant via any other mechanism (including other Terraform resources) will have that attached grant revoked by this resource. + These resources do not enforce exclusive attachment of a grant, it is the user's responsibility to enforce this. + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|---------------|--------|-------------------------------------------------------------------------------------|----------|-----------|----------|---------| +| database_name | string | The name of the database containing the current stage on which to grant privileges. | false | true | false | | +| privilege | string | The privilege to grant on the stage. | true | false | false | "USAGE" | +| roles | set | Grants privilege to these roles. | true | false | false | | +| schema_name | string | The name of the schema containing the current stage on which to grant privileges. | false | true | false | | +| shares | set | Grants privilege to these shares. | true | false | false | | +| stage_name | string | The name of the stage on which to grant privileges. | false | true | false | | diff --git a/docs/resources/storage_integration.md b/docs/resources/storage_integration.md new file mode 100644 index 0000000000..1e5db50c0c --- /dev/null +++ b/docs/resources/storage_integration.md @@ -0,0 +1,21 @@ + +# snowflake_storage_integration + + + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|---------------------------|--------|---------------------------------------------------------------------------------------------------------------|----------|-----------|----------|------------------| +| azure_tenant_id | string | | true | false | false | "" | +| comment | string | | true | false | false | "" | +| created_on | string | Date and time when the storage integration was created. | false | false | true | | +| enabled | bool | | true | false | false | true | +| name | string | | false | true | false | | +| storage_allowed_locations | list | Explicitly limits external stages that use the integration to reference one or more storage locations. | false | true | false | | +| storage_aws_external_id | string | The external ID that Snowflake will use when assuming the AWS role. | false | false | true | | +| storage_aws_iam_user_arn | string | The Snowflake user that will attempt to assume the AWS role. | false | false | true | | +| storage_aws_role_arn | string | | true | false | false | "" | +| storage_blocked_locations | list | Explicitly prohibits external stages that use the integration from referencing one or more storage locations. | true | false | false | | +| storage_provider | string | | false | true | false | | +| type | string | | true | false | false | "EXTERNAL_STAGE" | diff --git a/docs/resources/table_grant.md b/docs/resources/table_grant.md new file mode 100644 index 0000000000..782511048e --- /dev/null +++ b/docs/resources/table_grant.md @@ -0,0 +1,22 @@ + +# snowflake_table_grant + + + +**Note**: The snowflake_table_grant resource creates exclusive attachments of grants. + Across the entire Snowflake account, all of the tables to which a single grant is attached must be declared + by a single snowflake_table_grant resource. This means that even any snowflake_table that have the attached + grant via any other mechanism (including other Terraform resources) will have that attached grant revoked by this resource. + These resources do not enforce exclusive attachment of a grant, it is the user's responsibility to enforce this. + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|---------------|--------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|----------| +| database_name | string | The name of the database containing the current or future tables on which to grant privileges. | false | true | false | | +| on_future | bool | When this is set to true and a schema_name is provided, apply this grant on all future tables in the given schema. When this is true and no schema_name is provided apply this grant on all future tables in the given database. The table_name and shares fields must be unset in order to use on_future. | true | false | false | false | +| privilege | string | The privilege to grant on the current or future table. | true | false | false | "SELECT" | +| roles | set | Grants privilege to these roles. | true | false | false | | +| schema_name | string | The name of the schema containing the current or future tables on which to grant privileges. | true | false | false | | +| shares | set | Grants privilege to these shares (only valid if on_future is unset). | true | false | false | | +| table_name | string | The name of the table on which to grant privileges immediately (only valid if on_future is unset). | true | false | false | | diff --git a/docs/resources/task.md b/docs/resources/task.md new file mode 100644 index 0000000000..5c391b58d2 --- /dev/null +++ b/docs/resources/task.md @@ -0,0 +1,21 @@ + +# snowflake_task + + + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|----------------------|--------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|---------| +| after | string | Specifies the predecessor task in the same database and schema of the current task. When a run of the predecessor task finishes successfully, it triggers this task (after a brief lag). | true | false | false | | +| comment | string | Specifies a comment for the task. | true | false | false | | +| database | string | The database in which to create the task. | false | true | false | | +| enabled | bool | Specifies if the task should be started (enabled) after creation or should remain suspended (default). | true | false | false | false | +| name | string | Specifies the identifier for the task; must be unique for the database and schema in which the task is created. | false | true | false | | +| schedule | string | The schedule for periodically running the task. This can be a cron or interval in minutes. | true | false | false | | +| schema | string | The schema in which to create the task. | false | true | false | | +| session_parameters | map | Specifies session parameters to set for the session when the task runs. A task supports all session parameters. | true | false | false | | +| sql_statement | string | Any single SQL statement, or a call to a stored procedure, executed when the task runs. | false | true | false | | +| user_task_timeout_ms | int | Specifies the time limit on a single run of the task before it times out (in milliseconds). | true | false | false | | +| warehouse | string | The warehouse the task will use. | false | true | false | | +| when | string | Specifies a Boolean SQL expression; multiple conditions joined with AND/OR are supported. | true | false | false | | diff --git a/docs/resources/user.md b/docs/resources/user.md new file mode 100644 index 0000000000..3fe74128f5 --- /dev/null +++ b/docs/resources/user.md @@ -0,0 +1,21 @@ + +# snowflake_user + + + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|----------------------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|---------| +| comment | string | | true | false | false | | +| default_namespace | string | Specifies the namespace (database only or database and schema) that is active by default for the user’s session upon login. | true | false | false | | +| default_role | string | Specifies the role that is active by default for the user’s session upon login. | true | false | true | | +| default_warehouse | string | Specifies the virtual warehouse that is active by default for the user’s session upon login. | true | false | false | | +| disabled | bool | | true | false | true | | +| has_rsa_public_key | bool | Will be true if user as an RSA key set. | false | false | true | | +| login_name | string | The name users use to log in. If not supplied, snowflake will use name instead. | true | false | true | | +| must_change_password | bool | Specifies whether the user is forced to change their password on next login (including their first/initial login) into the system. | true | false | false | | +| name | string | Name of the user. Note that if you do not supply login_name this will be used as login_name. [doc](https://docs.snowflake.net/manuals/sql-reference/sql/create-user.html#required-parameters) | false | true | false | | +| password | string | **WARNING:** this will put the password in the terraform state file. Use carefully. | true | false | false | | +| 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. | true | false | false | | +| 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. | true | false | false | | diff --git a/docs/resources/view.md b/docs/resources/view.md new file mode 100644 index 0000000000..605aae19d5 --- /dev/null +++ b/docs/resources/view.md @@ -0,0 +1,16 @@ + +# snowflake_view + + + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|------------|--------|-------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|----------| +| comment | string | Specifies a comment for the view. | true | false | false | | +| database | string | The database in which to create the view. Don't use the | character. | false | true | false | | +| is_secure | bool | Specifies that the view is secure. | true | false | false | false | +| name | string | Specifies the identifier for the view; must be unique for the schema in which the view is created. Don't use the | character. | false | true | false | | +| or_replace | bool | Overwrites the View if it exists. | true | false | false | false | +| schema | string | The schema in which to create the view. Don't use the | character. | true | false | false | "PUBLIC" | +| statement | string | Specifies the query used to create the view. | false | true | false | | diff --git a/docs/resources/view_grant.md b/docs/resources/view_grant.md new file mode 100644 index 0000000000..c4b30672b6 --- /dev/null +++ b/docs/resources/view_grant.md @@ -0,0 +1,22 @@ + +# snowflake_view_grant + + + +**Note**: The snowflake_view_grant resource creates exclusive attachments of grants. + Across the entire Snowflake account, all of the views to which a single grant is attached must be declared + by a single snowflake_view_grant resource. This means that even any snowflake_view that have the attached + grant via any other mechanism (including other Terraform resources) will have that attached grant revoked by this resource. + These resources do not enforce exclusive attachment of a grant, it is the user's responsibility to enforce this. + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|---------------|--------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|----------| +| database_name | string | The name of the database containing the current or future views on which to grant privileges. | false | true | false | | +| on_future | bool | When this is set to true and a schema_name is provided, apply this grant on all future views in the given schema. When this is true and no schema_name is provided apply this grant on all future views in the given database. The view_name and shares fields must be unset in order to use on_future. | true | false | false | false | +| privilege | string | The privilege to grant on the current or future view. | true | false | false | "SELECT" | +| roles | set | Grants privilege to these roles. | true | false | false | | +| schema_name | string | The name of the schema containing the current or future views on which to grant privileges. | true | false | false | | +| shares | set | Grants privilege to these shares (only valid if on_future is unset). | true | false | false | | +| view_name | string | The name of the view on which to grant privileges immediately (only valid if on_future is unset). | true | false | false | | diff --git a/docs/resources/warehouse.md b/docs/resources/warehouse.md new file mode 100644 index 0000000000..1d0c87085c --- /dev/null +++ b/docs/resources/warehouse.md @@ -0,0 +1,21 @@ + +# snowflake_warehouse + + + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|------------------------------|--------|------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|----------|---------| +| auto_resume | bool | Specifies whether to automatically resume a warehouse when a SQL statement (e.g. query) is submitted to it. | true | false | true | | +| auto_suspend | int | Specifies the number of seconds of inactivity after which a warehouse is automatically suspended. | true | false | true | | +| comment | string | | true | false | false | "" | +| initially_suspended | bool | Specifies whether the warehouse is created initially in the ‘Suspended’ state. | true | false | false | | +| max_cluster_count | int | Specifies the maximum number of server clusters for the warehouse. | true | false | true | | +| min_cluster_count | int | Specifies the minimum number of server clusters for the warehouse (only applies to multi-cluster warehouses). | true | false | true | | +| name | string | | false | true | false | | +| resource_monitor | string | Specifies the name of a resource monitor that is explicitly assigned to the warehouse. | true | false | true | | +| scaling_policy | string | Specifies the policy for automatically starting and shutting down clusters in a multi-cluster warehouse running in Auto-scale mode. | true | false | true | | +| statement_timeout_in_seconds | int | Specifies the time, in seconds, after which a running SQL statement (query, DDL, DML, etc.) is canceled by the system | true | false | false | 0 | +| wait_for_provisioning | bool | Specifies whether the warehouse, after being resized, waits for all the servers to provision before executing any queued or new queries. | true | false | false | | +| warehouse_size | string | | true | false | true | | diff --git a/docs/resources/warehouse_grant.md b/docs/resources/warehouse_grant.md new file mode 100644 index 0000000000..f8b755b02c --- /dev/null +++ b/docs/resources/warehouse_grant.md @@ -0,0 +1,18 @@ + +# snowflake_warehouse_grant + + + +**Note**: The snowflake_warehouse_grant resource creates exclusive attachments of grants. + Across the entire Snowflake account, all of the warehouses to which a single grant is attached must be declared + by a single snowflake_warehouse_grant resource. This means that even any snowflake_warehouse that have the attached + grant via any other mechanism (including other Terraform resources) will have that attached grant revoked by this resource. + These resources do not enforce exclusive attachment of a grant, it is the user's responsibility to enforce this. + +## properties + +| NAME | TYPE | DESCRIPTION | OPTIONAL | REQUIRED | COMPUTED | DEFAULT | +|----------------|--------|---------------------------------------------------------|----------|-----------|----------|---------| +| privilege | string | The privilege to grant on the warehouse. | true | false | false | "USAGE" | +| roles | set | Grants privilege to these roles. | true | false | false | | +| warehouse_name | string | The name of the warehouse on which to grant privileges. | false | true | false | | diff --git a/go.mod b/go.mod index 66217012c2..d7709b0929 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,6 @@ require ( github.com/chanzuckerberg/go-misc v0.0.0-20200713202614-1c7b6844ebd6 github.com/hashicorp/terraform-plugin-sdk v1.12.0 github.com/jmoiron/sqlx v1.2.0 - github.com/mattn/go-runewidth v0.0.9 // indirect github.com/mitchellh/go-homedir v1.1.0 github.com/olekukonko/tablewriter v0.0.4 github.com/opentracing/opentracing-go v1.1.0 // indirect diff --git a/go.sum b/go.sum index f6a17f2828..25319129e9 100644 --- a/go.sum +++ b/go.sum @@ -250,8 +250,6 @@ github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/ github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= diff --git a/main.go b/main.go index 29f35af15a..750873bbd5 100644 --- a/main.go +++ b/main.go @@ -4,28 +4,17 @@ import ( "flag" "fmt" "log" - "os" - "sort" - "strings" "github.com/chanzuckerberg/go-misc/ver" "github.com/chanzuckerberg/terraform-provider-snowflake/pkg/provider" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/plugin" "github.com/hashicorp/terraform-plugin-sdk/terraform" - "github.com/olekukonko/tablewriter" ) func main() { - doc := flag.Bool("doc", false, "spit out docs for resources here") version := flag.Bool("version", false, "spit out version for resources here") flag.Parse() - if *doc { - generateDocs() - return - } - if *version { verString, err := ver.VersionStr() if err != nil { @@ -42,73 +31,3 @@ func main() { }) } - -func generateDocs() { - // schema := provider.Provider().Schema - resources := provider.Provider().ResourcesMap - - names := make([]string, 0) - for k := range resources { - names = append(names, k) - } - sort.Strings(names) - for _, name := range names { - resource := resources[name] - fmt.Printf("\n### %s\n\n", name) - if strings.HasSuffix(name, "_grant") { - grant_resource_name := strings.Replace(name, "_grant", "", -1) - granted_to_name := strings.Replace(grant_resource_name, "snowflake_", "", -1) - fmt.Printf( - `**Note**: The %s resource creates exclusive attachments of grants. -Across the entire Snowflake account, all of the %ss to which a single grant is attached must be declared -by a single %s resource. This means that even any %s that have the attached -grant via any other mechanism (including other Terraform resources) will have that attached grant revoked by this resource. -These resources do not enforce exclusive attachment of a grant, it is the user's responsibility to enforce this. -`, name, granted_to_name, name, grant_resource_name) - fmt.Println("") - } - fmt.Printf("#### properties\n\n") - - table := tablewriter.NewWriter(os.Stdout) - table.SetAutoWrapText(false) - table.SetHeader([]string{"name", "type", "description", "optional", " required", "computed", "default"}) - table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) - table.SetCenterSeparator("|") - - properties := make([]string, 0) - for k := range resource.Schema { - properties = append(properties, k) - } - sort.Strings(properties) - for _, property := range properties { - s := resource.Schema[property] - table.Append([]string{property, typeString(s.Type), s.Description, boolString(s.Optional), boolString(s.Required), boolString(s.Computed), interfaceString(s.Default)}) - } - table.Render() - } - -} - -func typeString(t schema.ValueType) string { - switch t { - case schema.TypeBool: - return "bool" - case schema.TypeInt: - return "int" - case schema.TypeFloat: - return "float" - case schema.TypeString: - return "string" - case schema.TypeList: - return "list" - case schema.TypeMap: - return "map" - case schema.TypeSet: - return "set" - } - return "?" -} - -func boolString(t bool) string { return fmt.Sprintf("%t", t) } - -func interfaceString(t interface{}) string { return fmt.Sprintf("%#v", t) } diff --git a/pkg/provider/provider.go b/pkg/provider/provider.go index f18347d927..3db0bdd5cb 100644 --- a/pkg/provider/provider.go +++ b/pkg/provider/provider.go @@ -17,50 +17,50 @@ import ( func Provider() *schema.Provider { return &schema.Provider{ Schema: map[string]*schema.Schema{ - "account": &schema.Schema{ + "account": { Type: schema.TypeString, Required: true, DefaultFunc: schema.EnvDefaultFunc("SNOWFLAKE_ACCOUNT", nil), }, - "username": &schema.Schema{ + "username": { Type: schema.TypeString, Required: true, DefaultFunc: schema.EnvDefaultFunc("SNOWFLAKE_USER", nil), }, - "password": &schema.Schema{ + "password": { Type: schema.TypeString, Optional: true, DefaultFunc: schema.EnvDefaultFunc("SNOWFLAKE_PASSWORD", nil), Sensitive: true, - ConflictsWith: []string{"browser_auth", "private_key_path"}, + ConflictsWith: []string{"browser_auth", "private_key_path", "oauth_access_token"}, }, - "oauth_access_token": &schema.Schema{ + "oauth_access_token": { Type: schema.TypeString, Optional: true, DefaultFunc: schema.EnvDefaultFunc("SNOWFLAKE_OAUTH_ACCESS_TOKEN", nil), Sensitive: true, ConflictsWith: []string{"browser_auth", "private_key_path", "password"}, }, - "browser_auth": &schema.Schema{ + "browser_auth": { Type: schema.TypeBool, Optional: true, DefaultFunc: schema.EnvDefaultFunc("SNOWFLAKE_USE_BROWSER_AUTH", nil), Sensitive: false, ConflictsWith: []string{"password", "private_key_path", "oauth_access_token"}, }, - "private_key_path": &schema.Schema{ + "private_key_path": { Type: schema.TypeString, Optional: true, DefaultFunc: schema.EnvDefaultFunc("SNOWFLAKE_PRIVATE_KEY_PATH", nil), Sensitive: true, ConflictsWith: []string{"browser_auth", "password", "oauth_access_token"}, }, - "role": &schema.Schema{ + "role": { Type: schema.TypeString, Optional: true, DefaultFunc: schema.EnvDefaultFunc("SNOWFLAKE_ROLE", nil), }, - "region": &schema.Schema{ + "region": { Type: schema.TypeString, Required: true, DefaultFunc: schema.EnvDefaultFunc("SNOWFLAKE_REGION", "us-west-2"), diff --git a/pkg/resources/account_grant.go b/pkg/resources/account_grant.go index 09b83a1b8b..8a809129ed 100644 --- a/pkg/resources/account_grant.go +++ b/pkg/resources/account_grant.go @@ -20,7 +20,7 @@ var validAccountPrivileges = newPrivilegeSet( ) var accountGrantSchema = map[string]*schema.Schema{ - "privilege": &schema.Schema{ + "privilege": { Type: schema.TypeString, Optional: true, Description: "The privilege to grant on the schema.", @@ -28,7 +28,7 @@ var accountGrantSchema = map[string]*schema.Schema{ ValidateFunc: validation.StringInSlice(validAccountPrivileges.toList(), true), ForceNew: true, }, - "roles": &schema.Schema{ + "roles": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, diff --git a/pkg/resources/database.go b/pkg/resources/database.go index e8d99b3f61..587897c6a6 100644 --- a/pkg/resources/database.go +++ b/pkg/resources/database.go @@ -12,29 +12,29 @@ import ( ) var databaseSchema = map[string]*schema.Schema{ - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Required: true, ForceNew: false, }, - "comment": &schema.Schema{ + "comment": { Type: schema.TypeString, Optional: true, Default: "", }, - "data_retention_time_in_days": &schema.Schema{ + "data_retention_time_in_days": { Type: schema.TypeInt, Optional: true, Computed: true, }, - "from_share": &schema.Schema{ + "from_share": { Type: schema.TypeMap, Description: "Specify a provider and a share in this map to create a database from a share.", Optional: true, ForceNew: true, ConflictsWith: []string{"from_database"}, }, - "from_database": &schema.Schema{ + "from_database": { Type: schema.TypeString, Description: "Specify a database to create a clone from.", Optional: true, diff --git a/pkg/resources/database_grant.go b/pkg/resources/database_grant.go index 4cb8cabce3..202ed8736f 100644 --- a/pkg/resources/database_grant.go +++ b/pkg/resources/database_grant.go @@ -18,13 +18,13 @@ var ValidDatabasePrivileges = newPrivilegeSet( ) var databaseGrantSchema = map[string]*schema.Schema{ - "database_name": &schema.Schema{ + "database_name": { Type: schema.TypeString, Required: true, Description: "The name of the database on which to grant privileges.", ForceNew: true, }, - "privilege": &schema.Schema{ + "privilege": { Type: schema.TypeString, Optional: true, Description: "The privilege to grant on the database.", @@ -32,14 +32,14 @@ var databaseGrantSchema = map[string]*schema.Schema{ ValidateFunc: validation.StringInSlice(ValidDatabasePrivileges.toList(), true), ForceNew: true, }, - "roles": &schema.Schema{ + "roles": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, Description: "Grants privilege to these roles.", ForceNew: true, }, - "shares": &schema.Schema{ + "shares": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, diff --git a/pkg/resources/integration_grant.go b/pkg/resources/integration_grant.go index 5591c072d5..a58feb231a 100644 --- a/pkg/resources/integration_grant.go +++ b/pkg/resources/integration_grant.go @@ -12,13 +12,13 @@ var validIntegrationPrivileges = newPrivilegeSet( privilegeOwnership, ) var integrationGrantSchema = map[string]*schema.Schema{ - "integration_name": &schema.Schema{ + "integration_name": { Type: schema.TypeString, Required: true, Description: "Identifier for the integration; must be unique for your account.", ForceNew: true, }, - "privilege": &schema.Schema{ + "privilege": { Type: schema.TypeString, Optional: true, Description: "The privilege to grant on the integration.", @@ -26,7 +26,7 @@ var integrationGrantSchema = map[string]*schema.Schema{ ValidateFunc: validation.StringInSlice(validIntegrationPrivileges.toList(), true), ForceNew: true, }, - "roles": &schema.Schema{ + "roles": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, diff --git a/pkg/resources/managed_account.go b/pkg/resources/managed_account.go index 95e1fe12cd..6b9b46f98d 100644 --- a/pkg/resources/managed_account.go +++ b/pkg/resources/managed_account.go @@ -25,19 +25,19 @@ var managedAccountProperties = []string{ } var managedAccountSchema = map[string]*schema.Schema{ - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Required: true, Description: "Identifier for the managed account; must be unique for your account.", ForceNew: true, }, - "admin_name": &schema.Schema{ + "admin_name": { Type: schema.TypeString, Required: true, Description: "Identifier, as well as login name, for the initial user in the managed account. This user serves as the account administrator for the account.", ForceNew: true, }, - "admin_password": &schema.Schema{ + "admin_password": { Type: schema.TypeString, Required: true, Sensitive: true, @@ -45,7 +45,7 @@ var managedAccountSchema = map[string]*schema.Schema{ ValidateFunc: snowflakeValidation.ValidatePassword, ForceNew: true, }, - "type": &schema.Schema{ + "type": { Type: schema.TypeString, Optional: true, Default: SnowflakeReaderAccountType, @@ -53,33 +53,33 @@ var managedAccountSchema = map[string]*schema.Schema{ ValidateFunc: validation.StringInSlice([]string{SnowflakeReaderAccountType}, true), ForceNew: true, }, - "comment": &schema.Schema{ + "comment": { Type: schema.TypeString, Optional: true, Description: "Specifies a comment for the managed account.", ForceNew: true, }, - "cloud": &schema.Schema{ + "cloud": { Type: schema.TypeString, Computed: true, Description: "Cloud in which the managed account is located.", }, - "region": &schema.Schema{ + "region": { Type: schema.TypeString, Computed: true, Description: "Snowflake Region in which the managed account is located.", }, - "locator": &schema.Schema{ + "locator": { Type: schema.TypeString, Computed: true, Description: "Display name of the managed account.", }, - "created_on": &schema.Schema{ + "created_on": { Type: schema.TypeString, Computed: true, Description: "Date and time when the managed account was created.", }, - "url": &schema.Schema{ + "url": { Type: schema.TypeString, Computed: true, Description: "URL for accessing the managed account, particularly through the web interface.", diff --git a/pkg/resources/pipe.go b/pkg/resources/pipe.go index 39c7b40a91..28e3eddf6e 100644 --- a/pkg/resources/pipe.go +++ b/pkg/resources/pipe.go @@ -17,30 +17,30 @@ const ( ) var pipeSchema = map[string]*schema.Schema{ - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Required: true, ForceNew: true, Description: "Specifies the identifier for the pipe; must be unique for the database and schema in which the pipe is created.", }, - "schema": &schema.Schema{ + "schema": { Type: schema.TypeString, Required: true, ForceNew: true, Description: "The schema in which to create the pipe.", }, - "database": &schema.Schema{ + "database": { Type: schema.TypeString, Required: true, ForceNew: true, Description: "The database in which to create the pipe.", }, - "comment": &schema.Schema{ + "comment": { Type: schema.TypeString, Optional: true, Description: "Specifies a comment for the pipe.", }, - "copy_statement": &schema.Schema{ + "copy_statement": { Type: schema.TypeString, Required: true, ForceNew: true, @@ -52,26 +52,26 @@ var pipeSchema = map[string]*schema.Schema{ return false }, }, - "aws_sns_topic": &schema.Schema{ + "aws_sns_topic": { Type: schema.TypeString, Optional: true, Required: false, ForceNew: true, Description: "Specifies AWS SNS Topic that SQS managed by Snowflake will subscribe to.", }, - "auto_ingest": &schema.Schema{ + "auto_ingest": { Type: schema.TypeBool, Optional: true, Default: false, ForceNew: true, Description: "Specifies a auto_ingest param for the pipe.", }, - "notification_channel": &schema.Schema{ + "notification_channel": { Type: schema.TypeString, Computed: true, Description: "Amazon Resource Name of the Amazon SQS queue for the stage named in the DEFINITION column.", }, - "owner": &schema.Schema{ + "owner": { Type: schema.TypeString, Computed: true, Description: "Name of the role that owns the pipe.", diff --git a/pkg/resources/resource_monitor.go b/pkg/resources/resource_monitor.go index 99fc77aa17..5e3b3cbddb 100644 --- a/pkg/resources/resource_monitor.go +++ b/pkg/resources/resource_monitor.go @@ -15,20 +15,20 @@ import ( var validFrequencies = []string{"MONTHLY", "DAILY", "WEEKLY", "YEARLY", "NEVER"} var resourceMonitorSchema = map[string]*schema.Schema{ - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Required: true, Description: "Identifier for the resource monitor; must be unique for your account.", ForceNew: true, }, - "credit_quota": &schema.Schema{ + "credit_quota": { Type: schema.TypeFloat, Optional: true, Computed: true, Description: "The amount of credits allocated monthly to the resource monitor, round up to 2 decimal places.", ForceNew: true, }, - "frequency": &schema.Schema{ + "frequency": { Type: schema.TypeString, Optional: true, Computed: true, @@ -36,34 +36,34 @@ var resourceMonitorSchema = map[string]*schema.Schema{ ValidateFunc: validation.StringInSlice(validFrequencies, false), ForceNew: true, }, - "start_timestamp": &schema.Schema{ + "start_timestamp": { Type: schema.TypeString, Optional: true, Computed: true, Description: "The date and time when the resource monitor starts monitoring credit usage for the assigned warehouses.", ForceNew: true, }, - "end_timestamp": &schema.Schema{ + "end_timestamp": { Type: schema.TypeString, Optional: true, Description: "The date and time when the resource monitor suspends the assigned warehouses.", ForceNew: true, }, - "suspend_triggers": &schema.Schema{ + "suspend_triggers": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeInt}, Optional: true, Description: "A list of percentage thresholds at which to suspend all warehouses.", ForceNew: true, }, - "suspend_immediate_triggers": &schema.Schema{ + "suspend_immediate_triggers": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeInt}, Optional: true, Description: "A list of percentage thresholds at which to immediately suspend all warehouses.", ForceNew: true, }, - "notify_triggers": &schema.Schema{ + "notify_triggers": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeInt}, Optional: true, diff --git a/pkg/resources/resource_monitor_grant.go b/pkg/resources/resource_monitor_grant.go index d6fbf519cd..f244a63d33 100644 --- a/pkg/resources/resource_monitor_grant.go +++ b/pkg/resources/resource_monitor_grant.go @@ -13,13 +13,13 @@ var validResourceMonitorPrivileges = newPrivilegeSet( ) var resourceMonitorGrantSchema = map[string]*schema.Schema{ - "monitor_name": &schema.Schema{ + "monitor_name": { Type: schema.TypeString, Required: true, Description: "Identifier for the resource monitor; must be unique for your account.", ForceNew: true, }, - "privilege": &schema.Schema{ + "privilege": { Type: schema.TypeString, Optional: true, Description: "The privilege to grant on the resource monitor.", @@ -27,7 +27,7 @@ var resourceMonitorGrantSchema = map[string]*schema.Schema{ ValidateFunc: validation.StringInSlice(validResourceMonitorPrivileges.toList(), true), ForceNew: true, }, - "roles": &schema.Schema{ + "roles": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, diff --git a/pkg/resources/role.go b/pkg/resources/role.go index 668776b3bd..14e17ac5f5 100644 --- a/pkg/resources/role.go +++ b/pkg/resources/role.go @@ -10,11 +10,11 @@ import ( var roleProperties = []string{"comment"} var roleSchema = map[string]*schema.Schema{ - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Required: true, }, - "comment": &schema.Schema{ + "comment": { Type: schema.TypeString, Optional: true, // TODO validation diff --git a/pkg/resources/role_grants.go b/pkg/resources/role_grants.go index 666e6056a0..8e96eb76c5 100644 --- a/pkg/resources/role_grants.go +++ b/pkg/resources/role_grants.go @@ -18,7 +18,7 @@ func RoleGrants() *schema.Resource { Update: UpdateRoleGrants, Schema: map[string]*schema.Schema{ - "role_name": &schema.Schema{ + "role_name": { Type: schema.TypeString, Elem: &schema.Schema{Type: schema.TypeString}, Required: true, @@ -27,13 +27,13 @@ func RoleGrants() *schema.Resource { return snowflake.ValidateIdentifier(val) }, }, - "roles": &schema.Schema{ + "roles": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, Description: "Grants role to this specified role.", }, - "users": &schema.Schema{ + "users": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, diff --git a/pkg/resources/schema.go b/pkg/resources/schema.go index f5347cfb99..56e86c62a3 100644 --- a/pkg/resources/schema.go +++ b/pkg/resources/schema.go @@ -19,37 +19,37 @@ const ( ) var schemaSchema = map[string]*schema.Schema{ - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Required: true, Description: "Specifies the identifier for the schema; must be unique for the database in which the schema is created.", ForceNew: true, }, - "database": &schema.Schema{ + "database": { Type: schema.TypeString, Required: true, Description: "The database in which to create the schema.", ForceNew: true, }, - "comment": &schema.Schema{ + "comment": { Type: schema.TypeString, Optional: true, Description: "Specifies a comment for the schema.", }, - "is_transient": &schema.Schema{ + "is_transient": { Type: schema.TypeBool, Optional: true, Default: false, Description: "Specifies a 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.", ForceNew: true, }, - "is_managed": &schema.Schema{ + "is_managed": { Type: schema.TypeBool, Optional: true, Default: false, Description: "Specifies a managed schema. Managed access schemas centralize privilege management with the schema owner.", }, - "data_retention_days": &schema.Schema{ + "data_retention_days": { Type: schema.TypeInt, Optional: true, Default: 1, diff --git a/pkg/resources/schema_grant.go b/pkg/resources/schema_grant.go index ea6a9689ed..5a94412b99 100644 --- a/pkg/resources/schema_grant.go +++ b/pkg/resources/schema_grant.go @@ -32,19 +32,19 @@ var validSchemaPrivileges = newPrivilegeSet( ) var schemaGrantSchema = map[string]*schema.Schema{ - "schema_name": &schema.Schema{ + "schema_name": { Type: schema.TypeString, Optional: true, Description: "The name of the schema on which to grant privileges.", ForceNew: true, }, - "database_name": &schema.Schema{ + "database_name": { Type: schema.TypeString, Required: true, Description: "The name of the database containing the schema on which to grant privileges.", ForceNew: true, }, - "privilege": &schema.Schema{ + "privilege": { Type: schema.TypeString, Optional: true, Description: "The privilege to grant on the current or future schema. Note that if \"OWNERSHIP\" is specified, ensure that the role that terraform is using is granted access.", @@ -52,21 +52,21 @@ var schemaGrantSchema = map[string]*schema.Schema{ ValidateFunc: validation.StringInSlice(validSchemaPrivileges.toList(), true), ForceNew: true, }, - "roles": &schema.Schema{ + "roles": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, Description: "Grants privilege to these roles.", ForceNew: true, }, - "shares": &schema.Schema{ + "shares": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, Description: "Grants privilege to these shares (only valid if on_future is unset).", ForceNew: true, }, - "on_future": &schema.Schema{ + "on_future": { Type: schema.TypeBool, Optional: true, Description: "When this is set to true, apply this grant on all future schemas in the given database. The schema_name and shares fields must be unset in order to use on_future.", diff --git a/pkg/resources/share.go b/pkg/resources/share.go index 614cdcd9d5..82733c3717 100644 --- a/pkg/resources/share.go +++ b/pkg/resources/share.go @@ -17,17 +17,17 @@ var shareProperties = []string{ } var shareSchema = map[string]*schema.Schema{ - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Required: true, Description: "Specifies the identifier for the share; must be unique for the account in which the share is created.", }, - "comment": &schema.Schema{ + "comment": { Type: schema.TypeString, Optional: true, Description: "Specifies a comment for the managed account.", }, - "accounts": &schema.Schema{ + "accounts": { // Changed from Set to List to use DiffSuppressFunc: https://github.com/hashicorp/terraform-plugin-sdk/issues/160 Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}, diff --git a/pkg/resources/stage.go b/pkg/resources/stage.go index 26d1136583..a51529edf8 100644 --- a/pkg/resources/stage.go +++ b/pkg/resources/stage.go @@ -17,56 +17,56 @@ const ( ) var stageSchema = map[string]*schema.Schema{ - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Required: true, Description: "Specifies the identifier for the stage; must be unique for the database and schema in which the stage is created.", ForceNew: true, }, - "database": &schema.Schema{ + "database": { Type: schema.TypeString, Required: true, Description: "The database in which to create the stage.", ForceNew: true, }, - "schema": &schema.Schema{ + "schema": { Type: schema.TypeString, Required: true, Description: "The schema in which to create the stage.", ForceNew: true, }, - "url": &schema.Schema{ + "url": { Type: schema.TypeString, Optional: true, Description: "Specifies the URL for the stage.", }, - "credentials": &schema.Schema{ + "credentials": { Type: schema.TypeString, Optional: true, Description: "Specifies the credentials for the stage.", Sensitive: true, }, - "storage_integration": &schema.Schema{ + "storage_integration": { Type: schema.TypeString, Optional: true, Description: "Specifies the name of the storage integration used to delegate authentication responsibility for external cloud storage to a Snowflake identity and access management (IAM) entity.", }, - "file_format": &schema.Schema{ + "file_format": { Type: schema.TypeString, Optional: true, Description: "Specifies the file format for the stage.", }, - "copy_options": &schema.Schema{ + "copy_options": { Type: schema.TypeString, Optional: true, Description: "Specifies the copy options for the stage.", }, - "encryption": &schema.Schema{ + "encryption": { Type: schema.TypeString, Optional: true, Description: "Specifies the encryption settings for the stage.", }, - "comment": &schema.Schema{ + "comment": { Type: schema.TypeString, Optional: true, Description: "Specifies a comment for the stage.", diff --git a/pkg/resources/stage_grant.go b/pkg/resources/stage_grant.go index 6a3c03974e..72c1f907d5 100644 --- a/pkg/resources/stage_grant.go +++ b/pkg/resources/stage_grant.go @@ -17,25 +17,25 @@ var ValidStagePrivileges = newPrivilegeSet( ) var stageGrantSchema = map[string]*schema.Schema{ - "stage_name": &schema.Schema{ + "stage_name": { Type: schema.TypeString, Required: true, Description: "The name of the stage on which to grant privileges.", ForceNew: true, }, - "schema_name": &schema.Schema{ + "schema_name": { Type: schema.TypeString, Required: true, Description: "The name of the schema containing the current stage on which to grant privileges.", ForceNew: true, }, - "database_name": &schema.Schema{ + "database_name": { Type: schema.TypeString, Required: true, Description: "The name of the database containing the current stage on which to grant privileges.", ForceNew: true, }, - "privilege": &schema.Schema{ + "privilege": { Type: schema.TypeString, Optional: true, Description: "The privilege to grant on the stage.", @@ -43,14 +43,14 @@ var stageGrantSchema = map[string]*schema.Schema{ ValidateFunc: validation.StringInSlice(ValidStagePrivileges.toList(), true), ForceNew: true, }, - "roles": &schema.Schema{ + "roles": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, Description: "Grants privilege to these roles.", ForceNew: true, }, - "shares": &schema.Schema{ + "shares": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, diff --git a/pkg/resources/storage_integration.go b/pkg/resources/storage_integration.go index 8edaab19eb..287e01f364 100644 --- a/pkg/resources/storage_integration.go +++ b/pkg/resources/storage_integration.go @@ -13,66 +13,66 @@ import ( var storageIntegrationSchema = map[string]*schema.Schema{ // The first part of the schema is shared between all integration vendors - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Required: true, ForceNew: true, }, - "comment": &schema.Schema{ + "comment": { Type: schema.TypeString, Optional: true, Default: "", }, - "type": &schema.Schema{ + "type": { Type: schema.TypeString, Optional: true, Default: "EXTERNAL_STAGE", ValidateFunc: validation.StringInSlice([]string{"EXTERNAL_STAGE"}, true), }, - "enabled": &schema.Schema{ + "enabled": { Type: schema.TypeBool, Optional: true, Default: true, }, - "storage_allowed_locations": &schema.Schema{ + "storage_allowed_locations": { Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}, Required: true, Description: "Explicitly limits external stages that use the integration to reference one or more storage locations.", }, - "storage_blocked_locations": &schema.Schema{ + "storage_blocked_locations": { Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, Description: "Explicitly prohibits external stages that use the integration from referencing one or more storage locations.", }, // This part of the schema is the cloudProviderParams in the Snowflake documentation and differs between vendors - "storage_provider": &schema.Schema{ + "storage_provider": { Type: schema.TypeString, Required: true, ValidateFunc: validation.StringInSlice([]string{"S3", "GCS", "AZURE"}, false), }, - "storage_aws_external_id": &schema.Schema{ + "storage_aws_external_id": { Type: schema.TypeString, Computed: true, Description: "The external ID that Snowflake will use when assuming the AWS role.", }, - "storage_aws_iam_user_arn": &schema.Schema{ + "storage_aws_iam_user_arn": { Type: schema.TypeString, Computed: true, Description: "The Snowflake user that will attempt to assume the AWS role.", }, - "storage_aws_role_arn": &schema.Schema{ + "storage_aws_role_arn": { Type: schema.TypeString, Optional: true, Default: "", }, - "azure_tenant_id": &schema.Schema{ + "azure_tenant_id": { Type: schema.TypeString, Optional: true, Default: "", }, - "created_on": &schema.Schema{ + "created_on": { Type: schema.TypeString, Computed: true, Description: "Date and time when the storage integration was created.", diff --git a/pkg/resources/table_grant.go b/pkg/resources/table_grant.go index 2004a71519..945c61dd3e 100644 --- a/pkg/resources/table_grant.go +++ b/pkg/resources/table_grant.go @@ -18,25 +18,25 @@ var validTablePrivileges = newPrivilegeSet( ) var tableGrantSchema = map[string]*schema.Schema{ - "table_name": &schema.Schema{ + "table_name": { Type: schema.TypeString, Optional: true, Description: "The name of the table on which to grant privileges immediately (only valid if on_future is unset).", ForceNew: true, }, - "schema_name": &schema.Schema{ + "schema_name": { Type: schema.TypeString, Optional: true, Description: "The name of the schema containing the current or future tables on which to grant privileges.", ForceNew: true, }, - "database_name": &schema.Schema{ + "database_name": { Type: schema.TypeString, Required: true, Description: "The name of the database containing the current or future tables on which to grant privileges.", ForceNew: true, }, - "privilege": &schema.Schema{ + "privilege": { Type: schema.TypeString, Optional: true, Description: "The privilege to grant on the current or future table.", @@ -44,21 +44,21 @@ var tableGrantSchema = map[string]*schema.Schema{ ValidateFunc: validation.StringInSlice(validTablePrivileges.toList(), true), ForceNew: true, }, - "roles": &schema.Schema{ + "roles": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, Description: "Grants privilege to these roles.", ForceNew: true, }, - "shares": &schema.Schema{ + "shares": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, Description: "Grants privilege to these shares (only valid if on_future is unset).", ForceNew: true, }, - "on_future": &schema.Schema{ + "on_future": { Type: schema.TypeBool, Optional: true, Description: "When this is set to true and a schema_name is provided, apply this grant on all future tables in the given schema. When this is true and no schema_name is provided apply this grant on all future tables in the given database. The table_name and shares fields must be unset in order to use on_future.", diff --git a/pkg/resources/task.go b/pkg/resources/task.go index 2c48395838..483518dc8b 100644 --- a/pkg/resources/task.go +++ b/pkg/resources/task.go @@ -19,69 +19,69 @@ const ( ) var taskSchema = map[string]*schema.Schema{ - "enabled": &schema.Schema{ + "enabled": { Type: schema.TypeBool, Optional: true, Default: false, Description: "Specifies if the task should be started (enabled) after creation or should remain suspended (default).", }, - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Required: true, Description: "Specifies the identifier for the task; must be unique for the database and schema in which the task is created.", ForceNew: true, }, - "database": &schema.Schema{ + "database": { Type: schema.TypeString, Required: true, Description: "The database in which to create the task.", ForceNew: true, }, - "schema": &schema.Schema{ + "schema": { Type: schema.TypeString, Required: true, Description: "The schema in which to create the task.", ForceNew: true, }, - "warehouse": &schema.Schema{ + "warehouse": { Type: schema.TypeString, Required: true, Description: "The warehouse the task will use.", ForceNew: false, }, - "schedule": &schema.Schema{ + "schedule": { Type: schema.TypeString, Optional: true, Description: "The schedule for periodically running the task. This can be a cron or interval in minutes.", }, - "session_parameters": &schema.Schema{ + "session_parameters": { Type: schema.TypeMap, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, Description: "Specifies session parameters to set for the session when the task runs. A task supports all session parameters.", }, - "user_task_timeout_ms": &schema.Schema{ + "user_task_timeout_ms": { Type: schema.TypeInt, Optional: true, ValidateFunc: validation.IntBetween(0, 86400000), Description: "Specifies the time limit on a single run of the task before it times out (in milliseconds).", }, - "comment": &schema.Schema{ + "comment": { Type: schema.TypeString, Optional: true, Description: "Specifies a comment for the task.", }, - "after": &schema.Schema{ + "after": { Type: schema.TypeString, Optional: true, Description: "Specifies the predecessor task in the same database and schema of the current task. When a run of the predecessor task finishes successfully, it triggers this task (after a brief lag).", }, - "when": &schema.Schema{ + "when": { Type: schema.TypeString, Optional: true, Description: "Specifies a Boolean SQL expression; multiple conditions joined with AND/OR are supported.", }, - "sql_statement": &schema.Schema{ + "sql_statement": { Type: schema.TypeString, Required: true, Description: "Any single SQL statement, or a call to a stored procedure, executed when the task runs.", diff --git a/pkg/resources/user.go b/pkg/resources/user.go index 08339f3e4c..5e43264589 100644 --- a/pkg/resources/user.go +++ b/pkg/resources/user.go @@ -26,11 +26,11 @@ var diffCaseInsensitive = func(k, old, new string, d *schema.ResourceData) bool } var userSchema = map[string]*schema.Schema{ - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Required: true, Description: "Name of the user. Note that if you do not supply login_name this will be used as login_name. [doc](https://docs.snowflake.net/manuals/sql-reference/sql/create-user.html#required-parameters)"}, - "login_name": &schema.Schema{ + "login_name": { Type: schema.TypeString, Optional: true, Computed: true, @@ -38,56 +38,56 @@ var userSchema = map[string]*schema.Schema{ // login_name is case-insensitive DiffSuppressFunc: diffCaseInsensitive, }, - "comment": &schema.Schema{ + "comment": { Type: schema.TypeString, Optional: true, // TODO validation }, - "password": &schema.Schema{ + "password": { Type: schema.TypeString, Optional: true, Sensitive: true, Description: "**WARNING:** this will put the password in the terraform state file. Use carefully.", // TODO validation https://docs.snowflake.net/manuals/sql-reference/sql/create-user.html#optional-parameters }, - "disabled": &schema.Schema{ + "disabled": { Type: schema.TypeBool, Optional: true, Computed: true, }, - "default_warehouse": &schema.Schema{ + "default_warehouse": { Type: schema.TypeString, Optional: true, Description: "Specifies the virtual warehouse that is active by default for the user’s session upon login.", }, - "default_namespace": &schema.Schema{ + "default_namespace": { Type: schema.TypeString, Optional: true, DiffSuppressFunc: diffCaseInsensitive, Description: "Specifies the namespace (database only or database and schema) that is active by default for the user’s session upon login.", }, - "default_role": &schema.Schema{ + "default_role": { Type: schema.TypeString, Optional: true, Computed: true, Description: "Specifies the role that is active by default for the user’s session upon login.", }, - "rsa_public_key": &schema.Schema{ + "rsa_public_key": { Type: schema.TypeString, Optional: true, Description: "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": &schema.Schema{ + "rsa_public_key_2": { Type: schema.TypeString, Optional: true, Description: "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.", }, - "has_rsa_public_key": &schema.Schema{ + "has_rsa_public_key": { Type: schema.TypeBool, Computed: true, Description: "Will be true if user as an RSA key set.", }, - "must_change_password": &schema.Schema{ + "must_change_password": { Type: schema.TypeBool, Optional: true, Description: "Specifies whether the user is forced to change their password on next login (including their first/initial login) into the system.", diff --git a/pkg/resources/view.go b/pkg/resources/view.go index f4bc5bddcb..ff11eee8d0 100644 --- a/pkg/resources/view.go +++ b/pkg/resources/view.go @@ -15,36 +15,42 @@ import ( var space = regexp.MustCompile(`\s+`) var viewSchema = map[string]*schema.Schema{ - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Required: true, Description: "Specifies the identifier for the view; must be unique for the schema in which the view is created. Don't use the | character.", }, - "database": &schema.Schema{ + "database": { Type: schema.TypeString, Required: true, Description: "The database in which to create the view. Don't use the | character.", ForceNew: true, }, - "schema": &schema.Schema{ + "schema": { Type: schema.TypeString, Optional: true, Default: "PUBLIC", Description: "The schema in which to create the view. Don't use the | character.", ForceNew: true, }, - "is_secure": &schema.Schema{ + "or_replace": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Overwrites the View if it exists.", + }, + "is_secure": { Type: schema.TypeBool, Optional: true, Default: false, Description: "Specifies that the view is secure.", }, - "comment": &schema.Schema{ + "comment": { Type: schema.TypeString, Optional: true, Description: "Specifies a comment for the view.", }, - "statement": &schema.Schema{ + "statement": { Type: schema.TypeString, Required: true, Description: "Specifies the query used to create the view.", @@ -98,6 +104,10 @@ func CreateView(data *schema.ResourceData, meta interface{}) error { builder := snowflake.View(name).WithDB(database).WithSchema(schema).WithStatement(s) // Set optionals + if v, ok := data.GetOk("or_replace"); ok && v.(bool) { + builder.WithReplace() + } + if v, ok := data.GetOk("is_secure"); ok && v.(bool) { builder.WithSecure() } @@ -106,10 +116,6 @@ func CreateView(data *schema.ResourceData, meta interface{}) error { builder.WithComment(v.(string)) } - if v, ok := data.GetOk("schema"); ok { - builder.WithSchema(v.(string)) - } - q := builder.Create() log.Print("[DEBUG] xxx ", q) err := snowflake.Exec(db, q) diff --git a/pkg/resources/view_acceptance_test.go b/pkg/resources/view_acceptance_test.go index 42f56961cb..a35578051c 100644 --- a/pkg/resources/view_acceptance_test.go +++ b/pkg/resources/view_acceptance_test.go @@ -57,6 +57,7 @@ resource "snowflake_view" "test" { comment = "Terraform test resource" database = snowflake_database.test.name is_secure = true + or_replace = false statement = "%s" } `, n, n, q) diff --git a/pkg/resources/view_grant.go b/pkg/resources/view_grant.go index ed3aae2e79..c44020865f 100644 --- a/pkg/resources/view_grant.go +++ b/pkg/resources/view_grant.go @@ -13,25 +13,25 @@ var ValidViewPrivileges = newPrivilegeSet( ) var viewGrantSchema = map[string]*schema.Schema{ - "view_name": &schema.Schema{ + "view_name": { Type: schema.TypeString, Optional: true, Description: "The name of the view on which to grant privileges immediately (only valid if on_future is unset).", ForceNew: true, }, - "schema_name": &schema.Schema{ + "schema_name": { Type: schema.TypeString, Optional: true, Description: "The name of the schema containing the current or future views on which to grant privileges.", ForceNew: true, }, - "database_name": &schema.Schema{ + "database_name": { Type: schema.TypeString, Required: true, Description: "The name of the database containing the current or future views on which to grant privileges.", ForceNew: true, }, - "privilege": &schema.Schema{ + "privilege": { Type: schema.TypeString, Optional: true, Description: "The privilege to grant on the current or future view.", @@ -39,21 +39,21 @@ var viewGrantSchema = map[string]*schema.Schema{ ValidateFunc: validation.StringInSlice(ValidViewPrivileges.toList(), true), ForceNew: true, }, - "roles": &schema.Schema{ + "roles": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, Description: "Grants privilege to these roles.", ForceNew: true, }, - "shares": &schema.Schema{ + "shares": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, Description: "Grants privilege to these shares (only valid if on_future is unset).", ForceNew: true, }, - "on_future": &schema.Schema{ + "on_future": { Type: schema.TypeBool, Optional: true, Description: "When this is set to true and a schema_name is provided, apply this grant on all future views in the given schema. When this is true and no schema_name is provided apply this grant on all future views in the given database. The view_name and shares fields must be unset in order to use on_future.", diff --git a/pkg/resources/view_test.go b/pkg/resources/view_test.go index fb36746959..c339d2ae05 100644 --- a/pkg/resources/view_test.go +++ b/pkg/resources/view_test.go @@ -42,6 +42,30 @@ func TestViewCreate(t *testing.T) { r.NoError(err) }) } +func TestViewCreateOrReplace(t *testing.T) { + r := require.New(t) + + in := map[string]interface{}{ + "name": "good_name", + "database": "test_db", + "comment": "great comment", + "statement": "SELECT * FROM test_db.PUBLIC.GREAT_TABLE WHERE account_id = 'bobs-account-id'", + "is_secure": true, + "or_replace": true, + } + d := schema.TestResourceDataRaw(t, resources.View().Schema, in) + r.NotNil(d) + + WithMockDb(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectExec( + `^CREATE OR REPLACE SECURE VIEW "test_db"."PUBLIC"."good_name" COMMENT = 'great comment' AS SELECT \* FROM test_db.PUBLIC.GREAT_TABLE WHERE account_id = 'bobs-account-id'$`, + ).WillReturnResult(sqlmock.NewResult(1, 1)) + + expectReadView(mock) + err := resources.CreateView(d, db) + r.NoError(err) + }) +} func TestViewCreateAmpersand(t *testing.T) { r := require.New(t) diff --git a/pkg/resources/warehouse.go b/pkg/resources/warehouse.go index d37ff48486..1da0fd21d8 100644 --- a/pkg/resources/warehouse.go +++ b/pkg/resources/warehouse.go @@ -19,16 +19,16 @@ var warehouseProperties = []string{ } var warehouseSchema = map[string]*schema.Schema{ - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Required: true, }, - "comment": &schema.Schema{ + "comment": { Type: schema.TypeString, Optional: true, Default: "", }, - "warehouse_size": &schema.Schema{ + "warehouse_size": { Type: schema.TypeString, Optional: true, Computed: true, @@ -44,28 +44,28 @@ var warehouseSchema = map[string]*schema.Schema{ return normalize(old) == normalize(new) }, }, - "max_cluster_count": &schema.Schema{ + "max_cluster_count": { Type: schema.TypeInt, Description: "Specifies the maximum number of server clusters for the warehouse.", Optional: true, Computed: true, ValidateFunc: validation.IntBetween(1, 10), }, - "min_cluster_count": &schema.Schema{ + "min_cluster_count": { Type: schema.TypeInt, Description: "Specifies the minimum number of server clusters for the warehouse (only applies to multi-cluster warehouses).", Optional: true, Computed: true, ValidateFunc: validation.IntBetween(1, 10), }, - "scaling_policy": &schema.Schema{ + "scaling_policy": { Type: schema.TypeString, Description: "Specifies the policy for automatically starting and shutting down clusters in a multi-cluster warehouse running in Auto-scale mode.", Optional: true, Computed: true, ValidateFunc: validation.StringInSlice([]string{"STANDARD", "ECONOMY"}, true), }, - "auto_suspend": &schema.Schema{ + "auto_suspend": { Type: schema.TypeInt, Description: "Specifies the number of seconds of inactivity after which a warehouse is automatically suspended.", Optional: true, @@ -73,29 +73,29 @@ var warehouseSchema = map[string]*schema.Schema{ ValidateFunc: validation.IntAtLeast(60), }, // @TODO add a disable_auto_suspend property that sets the value of auto_suspend to NULL - "auto_resume": &schema.Schema{ + "auto_resume": { Type: schema.TypeBool, Description: "Specifies whether to automatically resume a warehouse when a SQL statement (e.g. query) is submitted to it.", Optional: true, Computed: true, }, - "initially_suspended": &schema.Schema{ + "initially_suspended": { Type: schema.TypeBool, Description: "Specifies whether the warehouse is created initially in the ‘Suspended’ state.", Optional: true, }, - "resource_monitor": &schema.Schema{ + "resource_monitor": { Type: schema.TypeString, Description: "Specifies the name of a resource monitor that is explicitly assigned to the warehouse.", Optional: true, Computed: true, }, - "wait_for_provisioning": &schema.Schema{ + "wait_for_provisioning": { Type: schema.TypeBool, Description: "Specifies whether the warehouse, after being resized, waits for all the servers to provision before executing any queued or new queries.", Optional: true, }, - "statement_timeout_in_seconds": &schema.Schema{ + "statement_timeout_in_seconds": { Type: schema.TypeInt, Optional: true, Default: 0, diff --git a/pkg/resources/warehouse_grant.go b/pkg/resources/warehouse_grant.go index af9218bf1b..32baa79b03 100644 --- a/pkg/resources/warehouse_grant.go +++ b/pkg/resources/warehouse_grant.go @@ -15,13 +15,13 @@ var validWarehousePrivileges = newPrivilegeSet( privilegeUsage, ) var warehouseGrantSchema = map[string]*schema.Schema{ - "warehouse_name": &schema.Schema{ + "warehouse_name": { Type: schema.TypeString, Required: true, Description: "The name of the warehouse on which to grant privileges.", ForceNew: true, }, - "privilege": &schema.Schema{ + "privilege": { Type: schema.TypeString, Optional: true, Description: "The privilege to grant on the warehouse.", @@ -29,7 +29,7 @@ var warehouseGrantSchema = map[string]*schema.Schema{ ValidateFunc: validation.StringInSlice(validWarehousePrivileges.toList(), true), ForceNew: true, }, - "roles": &schema.Schema{ + "roles": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, diff --git a/pkg/snowflake/view.go b/pkg/snowflake/view.go index 7750d3e339..a4635dd616 100644 --- a/pkg/snowflake/view.go +++ b/pkg/snowflake/view.go @@ -14,6 +14,7 @@ type ViewBuilder struct { db string schema string secure bool + replace bool comment string statement string } @@ -51,6 +52,12 @@ func (vb *ViewBuilder) WithDB(db string) *ViewBuilder { return vb } +// WithReplace adds the "OR REPLACE" option to the ViewBuilder +func (vb *ViewBuilder) WithReplace() *ViewBuilder { + vb.replace = true + return vb +} + // WithSchema adds the name of the schema to the ViewBuilder func (vb *ViewBuilder) WithSchema(s string) *ViewBuilder { vb.schema = s @@ -91,6 +98,11 @@ func (vb *ViewBuilder) Create() string { var q strings.Builder q.WriteString("CREATE") + + if vb.replace { + q.WriteString(" OR REPLACE") + } + if vb.secure { q.WriteString(" SECURE") } diff --git a/scripts/update-readme.sh b/scripts/update-readme.sh deleted file mode 100755 index ee3ea4e9c4..0000000000 --- a/scripts/update-readme.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -# Borrowed from fogg. -# I would have written this directly in the Makefile, but that was difficult. - -CMD="$1" - -TMP=`mktemp` -TMP2=`mktemp` -./"$BASE_BINARY_NAME" -doc > "$TMP" -sed '/^$/,//{//!d;}' README.md | sed "/^$/r $TMP" > $TMP2 - -case "$CMD" in - update) - mv $TMP2 README.md - ;; - check) - diff $TMP2 README.md >/dev/null - ;; -esac - -exit $?