Skip to content

Commit

Permalink
feat: Support DIRECTORY option on stage create (#872)
Browse files Browse the repository at this point in the history
  • Loading branch information
zapo committed Feb 23, 2022
1 parent 9cb863c commit 0ea9a1e
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 3 deletions.
1 change: 1 addition & 0 deletions docs/resources/stage.md
Expand Up @@ -45,6 +45,7 @@ resource "snowflake_stage_grant" "grant_example_stage" {
- **comment** (String) Specifies a comment for the stage.
- **copy_options** (String) Specifies the copy options for the stage.
- **credentials** (String, Sensitive) Specifies the credentials for the stage.
- **directory** (String) Specifies the directory settings for the stage.
- **encryption** (String) Specifies the encryption settings for the stage.
- **file_format** (String) Specifies the file format for the stage.
- **id** (String) The ID of this resource.
Expand Down
15 changes: 15 additions & 0 deletions pkg/resources/stage.go
Expand Up @@ -72,6 +72,12 @@ var stageSchema = map[string]*schema.Schema{
Optional: true,
Description: "Specifies a comment for the stage.",
},
"directory": {
Type: schema.TypeString,
ForceNew: true,
Optional: true,
Description: "Specifies the directory settings for the stage.",
},
"aws_external_id": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -176,6 +182,10 @@ func CreateStage(d *schema.ResourceData, meta interface{}) error {
builder.WithCopyOptions(v.(string))
}

if v, ok := d.GetOk("directory"); ok {
builder.WithDirectory(v.(string))
}

if v, ok := d.GetOk("encryption"); ok {
builder.WithEncryption(v.(string))
}
Expand Down Expand Up @@ -273,6 +283,11 @@ func ReadStage(d *schema.ResourceData, meta interface{}) error {
return err
}

err = d.Set("directory", stageDesc.Directory)
if err != nil {
return err
}

err = d.Set("storage_integration", s.StorageIntegration)
if err != nil {
return err
Expand Down
3 changes: 2 additions & 1 deletion pkg/resources/stage_test.go
Expand Up @@ -73,7 +73,8 @@ func expectReadStage(mock sqlmock.Sqlmock) {
"parent_property", "property", "property_type", "property_value", "property_default"},
).AddRow("STAGE_LOCATION", "URL", "string", `["s3://load/test/"]`, "").
AddRow("STAGE_CREDENTIALS", "AWS_EXTERNAL_ID", "string", "test", "").
AddRow("STAGE_FILE_FORMAT", "FORMAT_NAME", "string", "CSV", "")
AddRow("STAGE_FILE_FORMAT", "FORMAT_NAME", "string", "CSV", "").
AddRow("DIRECTORY", "ENABLED", "Boolean", true, false)
mock.ExpectQuery(`^DESCRIBE STAGE "test_db"."test_schema"."test_stage"$`).WillReturnRows(rows)
}

Expand Down
18 changes: 18 additions & 0 deletions pkg/snowflake/stage.go
Expand Up @@ -21,6 +21,7 @@ type StageBuilder struct {
schema string
url string
credentials string
directory string
storageIntegration string
encryption string
fileFormat string
Expand Down Expand Up @@ -74,6 +75,12 @@ func (sb *StageBuilder) WithCopyOptions(c string) *StageBuilder {
return sb
}

// WithDirectory adds directory option to the StageBuilder
func (sb *StageBuilder) WithDirectory(d string) *StageBuilder {
sb.directory = d
return sb
}

// WithComment adds a comment to the StageBuilder
func (sb *StageBuilder) WithComment(c string) *StageBuilder {
sb.comment = c
Expand Down Expand Up @@ -150,6 +157,10 @@ func (sb *StageBuilder) Create() string {
q.WriteString(fmt.Sprintf(` COPY_OPTIONS = (%v)`, sb.copyOptions))
}

if sb.directory != "" {
q.WriteString(fmt.Sprintf(` DIRECTORY = (%v)`, sb.directory))
}

if sb.comment != "" {
q.WriteString(fmt.Sprintf(` COMMENT = '%v'`, EscapeString(sb.comment)))
}
Expand Down Expand Up @@ -242,6 +253,7 @@ type descStageResult struct {
SnowflakeIamUser string
FileFormat string
CopyOptions string
Directory string
}

type descStageRow struct {
Expand All @@ -255,6 +267,7 @@ func DescStage(db *sql.DB, query string) (*descStageResult, error) {
r := &descStageResult{}
var ff []string
var co []string
var dir []string
rows, err := Query(db, query)
if err != nil {
return r, err
Expand Down Expand Up @@ -286,11 +299,16 @@ func DescStage(db *sql.DB, query string) (*descStageResult, error) {
if row.PropertyValue != row.PropertyDefault {
co = append(co, fmt.Sprintf("%s = %s", row.Property, row.PropertyValue))
}
case "DIRECTORY":
if row.PropertyValue != row.PropertyDefault {
dir = append(dir, fmt.Sprintf("%s = %s", row.Property, row.PropertyValue))
}
}
}

r.FileFormat = strings.Join(ff, " ")
r.CopyOptions = strings.Join(co, " ")
r.Directory = strings.Join(dir, " ")
return r, nil
}

Expand Down
7 changes: 5 additions & 2 deletions pkg/snowflake/stage_test.go
Expand Up @@ -28,11 +28,14 @@ func TestStageCreate(t *testing.T) {
s.WithCopyOptions("on_error='skip_file'")
r.Equal(s.Create(), `CREATE STAGE "test_db"."test_schema"."test_stage" URL = 's3://load/encrypted_files/' CREDENTIALS = (aws_role='arn:aws:iam::001234567890:role/mysnowflakerole') ENCRYPTION = (type='AWS_SSE_KMS' kms_key_id = 'aws/key') FILE_FORMAT = (format_name=my_csv_format) COPY_OPTIONS = (on_error='skip_file')`)

s.WithDirectory("ENABLE=TRUE")
r.Equal(s.Create(), `CREATE STAGE "test_db"."test_schema"."test_stage" URL = 's3://load/encrypted_files/' CREDENTIALS = (aws_role='arn:aws:iam::001234567890:role/mysnowflakerole') ENCRYPTION = (type='AWS_SSE_KMS' kms_key_id = 'aws/key') FILE_FORMAT = (format_name=my_csv_format) COPY_OPTIONS = (on_error='skip_file') DIRECTORY = (ENABLE=TRUE)`)

s.WithComment("Yee'haw")
r.Equal(`CREATE STAGE "test_db"."test_schema"."test_stage" URL = 's3://load/encrypted_files/' CREDENTIALS = (aws_role='arn:aws:iam::001234567890:role/mysnowflakerole') ENCRYPTION = (type='AWS_SSE_KMS' kms_key_id = 'aws/key') FILE_FORMAT = (format_name=my_csv_format) COPY_OPTIONS = (on_error='skip_file') COMMENT = 'Yee\'haw'`, s.Create())
r.Equal(`CREATE STAGE "test_db"."test_schema"."test_stage" URL = 's3://load/encrypted_files/' CREDENTIALS = (aws_role='arn:aws:iam::001234567890:role/mysnowflakerole') ENCRYPTION = (type='AWS_SSE_KMS' kms_key_id = 'aws/key') FILE_FORMAT = (format_name=my_csv_format) COPY_OPTIONS = (on_error='skip_file') DIRECTORY = (ENABLE=TRUE) COMMENT = 'Yee\'haw'`, s.Create())

s.WithStorageIntegration("MY_INTEGRATION")
r.Equal(`CREATE STAGE "test_db"."test_schema"."test_stage" URL = 's3://load/encrypted_files/' CREDENTIALS = (aws_role='arn:aws:iam::001234567890:role/mysnowflakerole') STORAGE_INTEGRATION = MY_INTEGRATION ENCRYPTION = (type='AWS_SSE_KMS' kms_key_id = 'aws/key') FILE_FORMAT = (format_name=my_csv_format) COPY_OPTIONS = (on_error='skip_file') COMMENT = 'Yee\'haw'`, s.Create())
r.Equal(`CREATE STAGE "test_db"."test_schema"."test_stage" URL = 's3://load/encrypted_files/' CREDENTIALS = (aws_role='arn:aws:iam::001234567890:role/mysnowflakerole') STORAGE_INTEGRATION = MY_INTEGRATION ENCRYPTION = (type='AWS_SSE_KMS' kms_key_id = 'aws/key') FILE_FORMAT = (format_name=my_csv_format) COPY_OPTIONS = (on_error='skip_file') DIRECTORY = (ENABLE=TRUE) COMMENT = 'Yee\'haw'`, s.Create())
}

func TestStageRename(t *testing.T) {
Expand Down

0 comments on commit 0ea9a1e

Please sign in to comment.