Skip to content

Commit

Permalink
feat: Connection resource (#3162)
Browse files Browse the repository at this point in the history
<!-- Feel free to delete comments as you fill this in -->

<!-- summary of changes -->
## Changes
* connection resource
* connection documentation
* added connection to migration guide  
## Test Plan
<!-- detail ways in which this PR has been tested or needs to be tested
-->
* [x] acceptance tests
<!-- add more below if you think they are relevant -->

## TODO
* [Uncomment acceptance tests for
failover](https://snowflakecomputing.atlassian.net/browse/SNOW-1763442)
* [Unskip integration
tests](https://snowflakecomputing.atlassian.net/browse/SNOW-1002023)
* Datasource

## References
<!-- issues documentation links, etc  -->
* https://docs.snowflake.com/en/sql-reference/sql/create-connection
*
#3155
  • Loading branch information
sfc-gh-fbudzynski authored Nov 7, 2024
1 parent 721ee40 commit 5aef117
Show file tree
Hide file tree
Showing 42 changed files with 2,026 additions and 200 deletions.
16 changes: 16 additions & 0 deletions MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,22 @@ across different versions.
## v0.97.0 ➞ v0.98.0

### *(new feature)* connection resources

Added a new resources for managing connections. We decided to split connection into two separate resources based on whether the connection is primary or a replica (secondary). i.e.:

- `snowflake_connection` is used as primary connection, with ability to enable failover to other accounts.
- `snowflake_secondary_connection` is used as replica (secondary) connection.

In order to promote secondary_connection to primary, resources need to be migrated (check [resource migration](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/resource_migration.md)) or re-created and imported using the following SQL statements on Snowflake Worksheet:

```
CREATE CONNECTION <name> AS REPLICA OF <organization_name>.<account_name>.<connection_name>;
ALTER CONNECTION <name> PRIMARY;
```

See reference [docs](https://docs.snowflake.com/en/sql-reference/sql/create-connection).

### snowflake_streams data source changes
New filtering options:
- `like`
Expand Down
76 changes: 76 additions & 0 deletions docs/resources/primary_connection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
page_title: "snowflake_primary_connection Resource - terraform-provider-snowflake"
subcategory: ""
description: |-
Resource used to manage primary (not replicated) connections. For more information, check connection documentation https://docs.snowflake.com/en/sql-reference/sql/create-connection.html.
---

!> **V1 release candidate** This resource is a release candidate for the V1. It is on the list of remaining GA objects for V1. We do not expect significant changes in it before the V1. We will welcome any feedback and adjust the resource if needed. Any errors reported will be resolved with a higher priority. We encourage checking this resource out before the V1 release. Please follow the [migration guide](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/MIGRATION_GUIDE.md#v0970--v0980) to use it.

# snowflake_primary_connection (Resource)

Resource used to manage primary (not replicated) connections. For more information, check [connection documentation](https://docs.snowflake.com/en/sql-reference/sql/create-connection.html).

## Example Usage

```terraform
## Minimal
resource "snowflake_primary_connection" "basic" {
name = "connection_name"
}
## Complete (with every optional set)
resource "snowflake_primary_connection" "complete" {
name = "connection_name"
comment = "my complete connection"
enable_failover_to_accounts = [
"<secondary_account_organization_name>.<secondary_account_name>"
]
}
```
-> **Note** Instead of using fully_qualified_name, you can reference objects managed outside Terraform by constructing a correct ID, consult [identifiers guide](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/guides/identifiers#new-computed-fully-qualified-name-field-in-resources).
<!-- TODO(SNOW-1634854): include an example showing both methods-->

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `name` (String) String that specifies the identifier (i.e. name) for the connection. Must start with an alphabetic character and may only contain letters, decimal digits (0-9), and underscores (_). For a primary connection, the name must be unique across connection names and account names in the organization. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"`

### Optional

- `comment` (String) Specifies a comment for the connection.
- `enable_failover_to_accounts` (List of String) Enables failover for given connection to provided accounts. Specifies a list of accounts in your organization where a secondary connection for this primary connection can be promoted to serve as the primary connection. Include your organization name for each account in the list.

### Read-Only

- `fully_qualified_name` (String) Fully qualified name of the resource. For more information, see [object name resolution](https://docs.snowflake.com/en/sql-reference/name-resolution).
- `id` (String) The ID of this resource.
- `show_output` (List of Object) Outputs the result of `SHOW CONNECTIONS` for the given connection. (see [below for nested schema](#nestedatt--show_output))

<a id="nestedatt--show_output"></a>
### Nested Schema for `show_output`

Read-Only:

- `account_locator` (String)
- `account_name` (String)
- `comment` (String)
- `connection_url` (String)
- `created_on` (String)
- `failover_allowed_to_accounts` (List of String)
- `is_primary` (Boolean)
- `name` (String)
- `organization_name` (String)
- `primary` (String)
- `region_group` (String)
- `snowflake_region` (String)

## Import

Import is supported using the following syntax:

```shell
terraform import snowflake_primary_connection.example 'connection_name'
```
76 changes: 76 additions & 0 deletions docs/resources/secondary_connection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
page_title: "snowflake_secondary_connection Resource - terraform-provider-snowflake"
subcategory: ""
description: |-
Resource used to manage secondary connections. To promote secondary connection to primary check migraton guide https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/MIGRATION_GUIDE.md#connection-resources. For more information, check connection documentation https://docs.snowflake.com/en/sql-reference/sql/create-connection.html.
---

!> **V1 release candidate** This resource is a release candidate for the V1. It is on the list of remaining GA objects for V1. We do not expect significant changes in it before the V1. We will welcome any feedback and adjust the resource if needed. Any errors reported will be resolved with a higher priority. We encourage checking this resource out before the V1 release. Please follow the [migration guide](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/MIGRATION_GUIDE.md#v0970--v0980) to use it.

# snowflake_secondary_connection (Resource)

Resource used to manage secondary connections. To promote secondary connection to primary check [migraton guide](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/MIGRATION_GUIDE.md#connection-resources). For more information, check [connection documentation](https://docs.snowflake.com/en/sql-reference/sql/create-connection.html).

## Example Usage

```terraform
## Minimal
resource "snowflake_secondary_connection" "basic" {
name = "connection_name"
as_replica_of = "<organization_name>.<account_name>.<connection_name>"
}
## Complete (with every optional set)
resource "snowflake_secondary_connection" "complete" {
name = "connection_name"
as_replica_of = "<organization_name>.<account_name>.<connection_name>"
comment = "my complete secondary connection"
}
```
-> **Note** Instead of using fully_qualified_name, you can reference objects managed outside Terraform by constructing a correct ID, consult [identifiers guide](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/guides/identifiers#new-computed-fully-qualified-name-field-in-resources).
<!-- TODO(SNOW-1634854): include an example showing both methods-->

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `as_replica_of` (String) Specifies the identifier for a primary connection from which to create a replica (i.e. a secondary connection).
- `name` (String) String that specifies the identifier (i.e. name) for the connection. Must start with an alphabetic character and may only contain letters, decimal digits (0-9), and underscores (_). For a secondary connection, the name must match the name of its primary connection. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"`

### Optional

- `comment` (String) Specifies a comment for the secondary connection.

### Read-Only

- `fully_qualified_name` (String) Fully qualified name of the resource. For more information, see [object name resolution](https://docs.snowflake.com/en/sql-reference/name-resolution).
- `id` (String) The ID of this resource.
- `is_primary` (Boolean) Indicates if the connection has been changed to primary. If change is detected, the secondary connection will be recreated.
- `show_output` (List of Object) Outputs the result of `SHOW CONNECTIONS` for the given connection. (see [below for nested schema](#nestedatt--show_output))

<a id="nestedatt--show_output"></a>
### Nested Schema for `show_output`

Read-Only:

- `account_locator` (String)
- `account_name` (String)
- `comment` (String)
- `connection_url` (String)
- `created_on` (String)
- `failover_allowed_to_accounts` (List of String)
- `is_primary` (Boolean)
- `name` (String)
- `organization_name` (String)
- `primary` (String)
- `region_group` (String)
- `snowflake_region` (String)

## Import

Import is supported using the following syntax:

```shell
terraform import snowflake_secondary_connection.example 'secondary_connection_name'
```
1 change: 1 addition & 0 deletions examples/resources/snowflake_primary_connection/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
terraform import snowflake_primary_connection.example 'connection_name'
13 changes: 13 additions & 0 deletions examples/resources/snowflake_primary_connection/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Minimal
resource "snowflake_primary_connection" "basic" {
name = "connection_name"
}

## Complete (with every optional set)
resource "snowflake_primary_connection" "complete" {
name = "connection_name"
comment = "my complete connection"
enable_failover_to_accounts = [
"<secondary_account_organization_name>.<secondary_account_name>"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
terraform import snowflake_secondary_connection.example 'secondary_connection_name'
12 changes: 12 additions & 0 deletions examples/resources/snowflake_secondary_connection/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## Minimal
resource "snowflake_secondary_connection" "basic" {
name = "connection_name"
as_replica_of = "<organization_name>.<account_name>.<connection_name>"
}

## Complete (with every optional set)
resource "snowflake_secondary_connection" "complete" {
name = "connection_name"
as_replica_of = "<organization_name>.<account_name>.<connection_name>"
comment = "my complete secondary connection"
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ package objectassert
import (
"fmt"
"slices"
"strings"
"testing"

"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk"
)

func (c *ConnectionAssert) HasFailoverAllowedToAccounts(expected []string) *ConnectionAssert {
func (c *ConnectionAssert) HasFailoverAllowedToAccounts(expected ...sdk.AccountIdentifier) *ConnectionAssert {
c.AddAssertion(func(t *testing.T, o *sdk.Connection) error {
t.Helper()
if !slices.Equal(expected, o.FailoverAllowedToAccounts) {
Expand Down Expand Up @@ -46,9 +45,8 @@ func (c *ConnectionAssert) HasConnectionUrlNotEmpty() *ConnectionAssert {
func (c *ConnectionAssert) HasPrimaryIdentifier(expected sdk.ExternalObjectIdentifier) *ConnectionAssert {
c.AddAssertion(func(t *testing.T, o *sdk.Connection) error {
t.Helper()
expectedString := strings.ReplaceAll(expected.FullyQualifiedName(), `"`, "")
if o.Primary != expectedString {
return fmt.Errorf("expected primary identifier: %v; got: %v", expectedString, o.Primary)
if o.Primary != expected {
return fmt.Errorf("expected primary identifier: %v; got: %v", expected.FullyQualifiedName(), o.Primary)
}
return nil
})
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,12 @@ var allResourceSchemaDefs = []ResourceSchemaDef{
name: "StreamOnView",
schema: resources.StreamOnView().Schema,
},
{
name: "PrimaryConnection",
schema: resources.PrimaryConnection().Schema,
},
{
name: "SecondaryConnection",
schema: resources.SecondaryConnection().Schema,
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package resourceassert

import (
"fmt"

"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert"
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk"
)

func (c *PrimaryConnectionResourceAssert) HasExactlyFailoverToAccountsInOrder(expected ...sdk.AccountIdentifier) *PrimaryConnectionResourceAssert {
c.AddAssertion(assert.ValueSet("enable_failover_to_accounts.#", fmt.Sprintf("%d", len(expected))))
for i, v := range expected {
c.AddAssertion(assert.ValueSet(fmt.Sprintf("enable_failover_to_accounts.%d", i), v.Name()))
}
return c
}

func (c *PrimaryConnectionResourceAssert) HasNoEnableFailoverToAccounts() *PrimaryConnectionResourceAssert {
c.AddAssertion(assert.ValueSet("enable_failover_to_accounts.#", "0"))
return c
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 5aef117

Please sign in to comment.