Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into config-rework
Browse files Browse the repository at this point in the history
  • Loading branch information
sfc-gh-jmichalak committed Nov 8, 2024
2 parents fa78cee + 4127b3f commit 2c4554c
Show file tree
Hide file tree
Showing 36 changed files with 1,112 additions and 154 deletions.
28 changes: 28 additions & 0 deletions MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ across different versions.
## v0.97.0 ➞ v0.98.0

### *(new feature)* snowflake_connections datasource
Added a new datasource enabling querying and filtering connections. Notes:
- all results are stored in `connections` field.
- `like` field enables connections filtering.
- SHOW CONNECTIONS output is enclosed in `show_output` field inside `connections`.
It's important to limit the records and calls to Snowflake to the minimum. That's why we recommend assessing which information you need from the data source and then providing strong filters and turning off additional fields for better plan performance.


### *(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.:
Expand Down Expand Up @@ -159,6 +167,26 @@ This segregation was based on the secret flows in CREATE SECRET. i.e.:

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

### *(bugfix)* Handle BCR Bundle 2024_08 in snowflake_user resource

[bcr 2024_08](https://docs.snowflake.com/en/release-notes/bcr-bundles/2024_08/bcr-1798) changed the "empty" response in the `SHOW USERS` query. This provider version adapts to the new result types; it should be used if you want to have 2024_08 Bundle enabled on your account.

Note: Because [bcr 2024_07](https://docs.snowflake.com/en/release-notes/bcr-bundles/2024_07/bcr-1692) changes the way how the `default_secondary_roles` attribute behaves, drift may be reported when enabling 2024_08 Bundle. Check [Handling default secondary roles](#breaking-change-handling-default-secondary-roles) for more context.

Connected issues: [#3125](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3125)

### *(bugfix)* Handle user import correctly

#### Context before the change

Password is empty after the `snowflake_user` import; we can't read it from the config or from Snowflake.
During the next terraform plan+apply it's updated to the "same" value.
It results in an error on Snowflake side: `New password rejected by current password policy. Reason: 'PRIOR_USE'.`

#### After the change

The error will be ignored on the provider side (after all, it means that the password in state is the same as on Snowflake side). Still, plan+apply is needed after importing user.

## v0.96.0 ➞ v0.97.0

### *(new feature)* snowflake_stream_on_table, snowflake_stream_on_external_table resource
Expand Down
79 changes: 79 additions & 0 deletions docs/data-sources/connections.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
page_title: "snowflake_connections Data Source - terraform-provider-snowflake"
subcategory: ""
description: |-
Datasource used to get details of filtered connections. Filtering is aligned with the current possibilities for SHOW CONNECTIONS https://docs.snowflake.com/en/sql-reference/sql/show-connections query. The results of SHOW is encapsulated in one output collection connections.
---

!> **V1 release candidate** This data source is a release candidate for the V1. We do not expect significant changes in it before the V1. We will welcome any feedback and adjust the data source if needed. Any errors reported will be resolved with a higher priority. We encourage checking this data source 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_connections (Data Source)

Datasource used to get details of filtered connections. Filtering is aligned with the current possibilities for [SHOW CONNECTIONS](https://docs.snowflake.com/en/sql-reference/sql/show-connections) query. The results of SHOW is encapsulated in one output collection `connections`.

## Example Usage

```terraform
# Simple usage
data "snowflake_connections" "simple" {
}
output "simple_output" {
value = data.snowflake_connections.simple.connections
}
# Filtering (like)
data "snowflake_connections" "like" {
like = "connection-name"
}
output "like_output" {
value = data.snowflake_connections.like.connections
}
# Filtering by prefix (like)
data "snowflake_connections" "like_prefix" {
like = "prefix%"
}
output "like_prefix_output" {
value = data.snowflake_connections.like_prefix.connections
}
```

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

### Optional

- `like` (String) Filters the output with **case-insensitive** pattern, with support for SQL wildcard characters (`%` and `_`).

### Read-Only

- `connections` (List of Object) Holds the aggregated output of all connections details queries. (see [below for nested schema](#nestedatt--connections))
- `id` (String) The ID of this resource.

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

Read-Only:

- `show_output` (List of Object) (see [below for nested schema](#nestedobjatt--connections--show_output))

<a id="nestedobjatt--connections--show_output"></a>
### Nested Schema for `connections.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)
2 changes: 2 additions & 0 deletions docs/resources/legacy_service_user.md
Original file line number Diff line number Diff line change
Expand Up @@ -1011,3 +1011,5 @@ Import is supported using the following syntax:
```shell
terraform import snowflake_legacy_service_user.example '"<user_name>"'
```

Note: terraform plan+apply may be needed after successful import to fill out all the missing fields (like `password`) in state.
2 changes: 2 additions & 0 deletions docs/resources/user.md
Original file line number Diff line number Diff line change
Expand Up @@ -1021,3 +1021,5 @@ Import is supported using the following syntax:
```shell
terraform import snowflake_user.example '"<user_name>"'
```

Note: terraform plan+apply may be needed after successful import to fill out all the missing fields (like `password`) in state.
25 changes: 25 additions & 0 deletions examples/data-sources/snowflake_connections/data-source.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Simple usage
data "snowflake_connections" "simple" {
}

output "simple_output" {
value = data.snowflake_connections.simple.connections
}

# Filtering (like)
data "snowflake_connections" "like" {
like = "connection-name"
}

output "like_output" {
value = data.snowflake_connections.like.connections
}

# Filtering by prefix (like)
data "snowflake_connections" "like_prefix" {
like = "prefix%"
}

output "like_prefix_output" {
value = data.snowflake_connections.like_prefix.connections
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package resourceassert
import (
"strconv"

r "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/resources"

"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert"
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk"
)
Expand All @@ -17,6 +19,11 @@ func (u *UserResourceAssert) HasEmptyPassword() *UserResourceAssert {
return u
}

func (u *UserResourceAssert) HasNotEmptyPassword() *UserResourceAssert {
u.AddAssertion(assert.ValuePresent("password"))
return u
}

func (u *UserResourceAssert) HasMustChangePassword(expected bool) *UserResourceAssert {
u.AddAssertion(assert.ValueSet("must_change_password", strconv.FormatBool(expected)))
return u
Expand All @@ -25,3 +32,29 @@ func (u *UserResourceAssert) HasMustChangePassword(expected bool) *UserResourceA
func (u *UserResourceAssert) HasDefaultSecondaryRolesOption(expected sdk.SecondaryRolesOption) *UserResourceAssert {
return u.HasDefaultSecondaryRolesOptionString(string(expected))
}

func (u *UserResourceAssert) HasAllDefaults(userId sdk.AccountObjectIdentifier, expectedDefaultSecondaryRoles sdk.SecondaryRolesOption) *UserResourceAssert {
return u.
HasNameString(userId.Name()).
HasNoPassword().
HasNoLoginName().
HasNoDisplayName().
HasNoFirstName().
HasNoMiddleName().
HasNoLastName().
HasNoEmail().
HasMustChangePasswordString(r.BooleanDefault).
HasDisabledString(r.BooleanDefault).
HasNoDaysToExpiry().
HasMinsToUnlockString(r.IntDefaultString).
HasNoDefaultWarehouse().
HasNoDefaultNamespace().
HasNoDefaultRole().
HasDefaultSecondaryRolesOption(expectedDefaultSecondaryRoles).
HasMinsToBypassMfaString(r.IntDefaultString).
HasNoRsaPublicKey().
HasNoRsaPublicKey2().
HasNoComment().
HasDisableMfaString(r.BooleanDefault).
HasFullyQualifiedNameString(userId.FullyQualifiedName())
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import (
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk"
)

func (c *ConnectionShowOutputAssert) HasCreatedOnNotEmpty() *ConnectionShowOutputAssert {
c.AddAssertion(assert.ResourceShowOutputValuePresent("created_on"))
return c
}

func (c *ConnectionShowOutputAssert) HasPrimaryIdentifier(expected sdk.ExternalObjectIdentifier) *ConnectionShowOutputAssert {
c.AddAssertion(assert.ResourceShowOutputValueSet("primary", expected.FullyQualifiedName()))
return c
Expand Down
47 changes: 47 additions & 0 deletions pkg/acceptance/helpers/compute_pool_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package helpers

import (
"context"
"fmt"
"testing"

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

// TODO [SNOW-1790174]: change raw sqls to proper client
type ComputePoolClient struct {
context *TestClientContext
ids *IdsGenerator
}

func NewComputePoolClient(context *TestClientContext, idsGenerator *IdsGenerator) *ComputePoolClient {
return &ComputePoolClient{
context: context,
ids: idsGenerator,
}
}

func (c *ComputePoolClient) client() *sdk.Client {
return c.context.client
}

func (c *ComputePoolClient) CreateComputePool(t *testing.T) (sdk.AccountObjectIdentifier, func()) {
t.Helper()
ctx := context.Background()

id := c.ids.RandomAccountObjectIdentifier()
_, err := c.client().ExecForTests(ctx, fmt.Sprintf(`CREATE COMPUTE POOL %s MIN_NODES = 1 MAX_NODES = 1 INSTANCE_FAMILY = CPU_X64_XS`, id.FullyQualifiedName()))
require.NoError(t, err)
return id, c.DropComputePoolFunc(t, id)
}

func (c *ComputePoolClient) DropComputePoolFunc(t *testing.T, id sdk.AccountObjectIdentifier) func() {
t.Helper()
ctx := context.Background()

return func() {
_, err := c.client().ExecForTests(ctx, fmt.Sprintf(`DROP COMPUTE POOL IF EXISTS %s`, id.FullyQualifiedName()))
require.NoError(t, err)
}
}
14 changes: 11 additions & 3 deletions pkg/acceptance/helpers/function_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,20 @@ func (c *FunctionClient) CreateWithRequest(t *testing.T, id sdk.SchemaObjectIden
err := c.client().CreateForSQL(ctx, req.WithArguments(argumentRequests))
require.NoError(t, err)

t.Cleanup(func() {
require.NoError(t, c.context.client.Functions.Drop(ctx, sdk.NewDropFunctionRequest(id).WithIfExists(true)))
})
t.Cleanup(c.DropFunctionFunc(t, id))

function, err := c.client().ShowByID(ctx, id)
require.NoError(t, err)

return function
}

func (c *FunctionClient) DropFunctionFunc(t *testing.T, id sdk.SchemaObjectIdentifierWithArguments) func() {
t.Helper()
ctx := context.Background()

return func() {
err := c.client().Drop(ctx, sdk.NewDropFunctionRequest(id).WithIfExists(true))
require.NoError(t, err)
}
}
2 changes: 2 additions & 0 deletions pkg/acceptance/helpers/test_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type TestClient struct {
ApplicationPackage *ApplicationPackageClient
AuthenticationPolicy *AuthenticationPolicyClient
BcrBundles *BcrBundlesClient
ComputePool *ComputePoolClient
Connection *ConnectionClient
Context *ContextClient
CortexSearchService *CortexSearchServiceClient
Expand Down Expand Up @@ -85,6 +86,7 @@ func NewTestClient(c *sdk.Client, database string, schema string, warehouse stri
ApplicationPackage: NewApplicationPackageClient(context, idsGenerator),
AuthenticationPolicy: NewAuthenticationPolicyClient(context, idsGenerator),
BcrBundles: NewBcrBundlesClient(context),
ComputePool: NewComputePoolClient(context, idsGenerator),
Connection: NewConnectionClient(context, idsGenerator),
Context: NewContextClient(context),
CortexSearchService: NewCortexSearchServiceClient(context, idsGenerator),
Expand Down
68 changes: 68 additions & 0 deletions pkg/datasources/connections.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package datasources

import (
"context"

"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider"
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/resources"
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas"
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

var connectionsSchema = map[string]*schema.Schema{
"like": likeSchema,
"connections": {
Type: schema.TypeList,
Computed: true,
Description: "Holds the aggregated output of all connections details queries.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
resources.ShowOutputAttributeName: {
Type: schema.TypeList,
Computed: true,
Description: "Holds the output of SHOW CONNECTIONS.",
Elem: &schema.Resource{
Schema: schemas.ShowConnectionSchema,
},
},
},
},
},
}

func Connections() *schema.Resource {
return &schema.Resource{
ReadContext: ReadConnections,
Schema: connectionsSchema,
Description: "Datasource used to get details of filtered connections. Filtering is aligned with the current possibilities for [SHOW CONNECTIONS](https://docs.snowflake.com/en/sql-reference/sql/show-connections) query. The results of SHOW is encapsulated in one output collection `connections`.",
}
}

func ReadConnections(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics {
client := meta.(*provider.Context).Client
req := sdk.ShowConnectionRequest{}

handleLike(d, &req.Like)

connections, err := client.Connections.Show(ctx, &req)
if err != nil {
return diag.FromErr(err)
}

d.SetId("connections_read")

flattenedConnections := make([]map[string]any, len(connections))
for i, connection := range connections {
connection := connection
flattenedConnections[i] = map[string]any{
resources.ShowOutputAttributeName: []map[string]any{schemas.ConnectionToSchema(&connection)},
}
}
if err := d.Set("connections", flattenedConnections); err != nil {
return diag.FromErr(err)
}

return nil
}
Loading

0 comments on commit 2c4554c

Please sign in to comment.