Skip to content

Commit

Permalink
feat: Add External Volume Resource
Browse files Browse the repository at this point in the history
  • Loading branch information
jdoldis committed Sep 29, 2024
1 parent 810df0d commit 1704a50
Show file tree
Hide file tree
Showing 60 changed files with 7,140 additions and 393 deletions.
74 changes: 74 additions & 0 deletions docs/resources/external_volume.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
page_title: "snowflake_external_volume Resource - terraform-provider-snowflake"
subcategory: ""
description: |-
Resource used to manage external volume objects. For more information, check external volume documentation https://docs.snowflake.com/en/sql-reference/commands-data-loading#external-volume.
---

# snowflake_external_volume (Resource)

Resource used to manage external volume objects. For more information, check [external volume documentation](https://docs.snowflake.com/en/sql-reference/commands-data-loading#external-volume).



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

### Required

- `name` (String) Identifier for the external volume; must be unique for your account. 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: `|`, `.`, `(`, `)`, `"`
- `storage_location` (Block List, Min: 1) List of named cloud storage locations in different regions and, optionally, cloud platforms. Minimum 1 required. Note that not all parameter combinations are valid as they depend on the given storage_provider. Consult [the docs](https://docs.snowflake.com/en/sql-reference/sql/create-external-volume#cloud-provider-parameters-cloudproviderparams) for more details on this. (see [below for nested schema](#nestedblock--storage_location))

### Optional

- `allow_writes` (String) Specifies whether write operations are allowed for the external volume; must be set to TRUE for Iceberg tables that use Snowflake as the catalog. Available options are: "true" or "false". When the value is not set in the configuration the provider will put "default" there which means to use the Snowflake default for this value.
- `comment` (String) Specifies a comment for the external volume.

### Read-Only

- `describe_output` (List of Object) Outputs the result of `DESCRIBE EXTERNAL VOLUME` for the given external volume. (see [below for nested schema](#nestedatt--describe_output))
- `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 EXTERNAL VOLUMES` for the given external volume. (see [below for nested schema](#nestedatt--show_output))

<a id="nestedblock--storage_location"></a>
### Nested Schema for `storage_location`

Required:

- `storage_base_url` (String) Specifies the base URL for your cloud storage location.
- `storage_location_name` (String) Name of the storage location. Must be unique for the external volume.
- `storage_provider` (String) Specifies the cloud storage provider that stores your data files. Valid values are (case-insensitive): `GCS` | `AZURE` | `S3` | `S3GOV`.

Optional:

- `azure_tenant_id` (String) Specifies the ID for your Office 365 tenant that the allowed and blocked storage accounts belong to.
- `encryption_kms_key_id` (String) Specifies the ID for the KMS-managed key used to encrypt files.
- `encryption_type` (String) Specifies the encryption type used.
- `storage_aws_role_arn` (String) Specifies the case-sensitive Amazon Resource Name (ARN) of the AWS identity and access management (IAM) role that grants privileges on the S3 bucket containing your data files.

Read-Only:

- `storage_aws_external_id` (String) External ID that Snowflake uses to establish a trust relationship with AWS.


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

Read-Only:

- `default` (String)
- `name` (String)
- `parent` (String)
- `type` (String)
- `value` (String)


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

Read-Only:

- `allow_writes` (Boolean)
- `comment` (String)
- `name` (String)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package resourceassert

import (
"strconv"

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

func (e *ExternalVolumeResourceAssert) HasStorageLocationLength(len int) *ExternalVolumeResourceAssert {
e.AddAssertion(assert.ValueSet("storage_location.#", strconv.FormatInt(int64(len), 10)))
return e
}

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

3 changes: 3 additions & 0 deletions pkg/acceptance/check_destroy.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ var showByIdFunctions = map[resources.Resource]showByIdFunc{
resources.ExternalTable: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error {
return runShowById(ctx, id, client.ExternalTables.ShowByID)
},
resources.ExternalVolume: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error {
return runShowById(ctx, id, client.ExternalVolumes.ShowByID)
},
resources.FailoverGroup: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error {
return runShowById(ctx, id, client.FailoverGroups.ShowByID)
},
Expand Down
56 changes: 36 additions & 20 deletions pkg/acceptance/helpers/external_volume_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package helpers

import (
"context"
"fmt"
"testing"

"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk"
Expand All @@ -21,39 +20,56 @@ func NewExternalVolumeClient(context *TestClientContext, idsGenerator *IdsGenera
}
}

func (c *ExternalVolumeClient) exec(sql string) error {
ctx := context.Background()
_, err := c.context.client.ExecForTests(ctx, sql)
return err
func (c *ExternalVolumeClient) client() sdk.ExternalVolumes {
return c.context.client.ExternalVolumes
}

// TODO(SNOW-999142): Use SDK implementation for External Volume once it's available
// TODO switch to returning *sdk.ExternalVolume
// need to update existing acceptance tests for this
func (c *ExternalVolumeClient) Create(t *testing.T) (sdk.AccountObjectIdentifier, func()) {
t.Helper()
ctx := context.Background()

id := c.ids.RandomAccountObjectIdentifier()
err := c.exec(fmt.Sprintf(`
create external volume %s
storage_locations =
(
(
name = 'my-s3-us-west-2'
storage_provider = 's3'
storage_base_url = 's3://my_example_bucket/'
storage_aws_role_arn = 'arn:aws:iam::123456789012:role/myrole'
encryption=(type='aws_sse_kms' kms_key_id='1234abcd-12ab-34cd-56ef-1234567890ab')
)
);
`, id.FullyQualifiedName()))
kmsKeyId := "1234abcd-12ab-34cd-56ef-1234567890ab"
storageLocations := []sdk.ExternalVolumeStorageLocation{
{
S3StorageLocationParams: &sdk.S3StorageLocationParams{
Name: "my-s3-us-west-2",
StorageProvider: "S3",
StorageAwsRoleArn: "arn:aws:iam::123456789012:role/myrole",
StorageBaseUrl: "s3://my_example_bucket/",
Encryption: &sdk.ExternalVolumeS3Encryption{
Type: "AWS_SSE_KMS",
KmsKeyId: &kmsKeyId,
},
},
},
}

req := sdk.NewCreateExternalVolumeRequest(id, storageLocations)
err := c.client().Create(ctx, req)
require.NoError(t, err)

_, showErr := c.client().ShowByID(ctx, id)
require.NoError(t, showErr)

return id, c.DropFunc(t, id)
}

func (c *ExternalVolumeClient) Alter(t *testing.T, req *sdk.AlterExternalVolumeRequest) {
t.Helper()
ctx := context.Background()
err := c.client().Alter(ctx, req)
require.NoError(t, err)
}

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

return func() {
err := c.exec(fmt.Sprintf(`drop external volume if exists %s`, id.FullyQualifiedName()))
err := c.client().Drop(ctx, sdk.NewDropExternalVolumeRequest(id).WithIfExists(true))
require.NoError(t, err)
}
}
Loading

0 comments on commit 1704a50

Please sign in to comment.