Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add a resource to manage sequences #582

Merged
merged 1 commit into from
Jun 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions docs/resources/sequence.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "snowflake_sequence Resource - terraform-provider-snowflake"
subcategory: ""
description: |-
---

# snowflake_sequence (Resource)



## Example Usage

```terraform
resource "snowflake_database" "database" {
name = "things"
}
resource "snowflake_schema" "test_schema" {
name = "things"
database = snowflake_database.test_database.name
}
resource "snowflake_sequence" "test_sequence" {
database = snowflake_database.test_database.name
schema = snowflake_schema.test_schema.name
name = "thing_counter"
}
```

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

### Required

- **database** (String) The database in which to create the sequence. Don't use the | character.
- **name** (String) Specifies the name for the sequence.
- **schema** (String) The schema in which to create the sequence. Don't use the | character.

### Optional

- **comment** (String) Specifies a comment for the sequence.
- **id** (String) The ID of this resource.
- **increment** (Number) The amount the sequence will increase by each time it is used

### Read-Only

- **next_value** (Number) The next value the sequence will provide.


14 changes: 14 additions & 0 deletions examples/resources/snowflake_sequence/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
resource "snowflake_database" "database" {
name = "things"
}

resource "snowflake_schema" "test_schema" {
name = "things"
database = snowflake_database.test_database.name
}

resource "snowflake_sequence" "test_sequence" {
database = snowflake_database.test_database.name
schema = snowflake_schema.test_schema.name
name = "thing_counter"
}
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1008,10 +1008,6 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.1.1 h1:wGiQel/hW0NnEkJUk8lbzkX2gFJU6PFxf1v5OlCfuOs=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3 h1:L69ShwSZEyCsLKoAxDKeMvLDZkumEe8gXUZAjab0tX8=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down
1 change: 1 addition & 0 deletions pkg/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ func getResources() map[string]*schema.Resource {
"snowflake_role_grants": resources.RoleGrants(),
"snowflake_schema": resources.Schema(),
"snowflake_scim_integration": resources.SCIMIntegration(),
"snowflake_sequence": resources.Sequence(),
"snowflake_share": resources.Share(),
"snowflake_stage": resources.Stage(),
"snowflake_storage_integration": resources.StorageIntegration(),
Expand Down
8 changes: 8 additions & 0 deletions pkg/resources/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,14 @@ func resourceMonitor(t *testing.T, id string, params map[string]interface{}) *sc
return d
}

func sequence(t *testing.T, id string, params map[string]interface{}) *schema.ResourceData {
r := require.New(t)
d := schema.TestResourceDataRaw(t, resources.Sequence().Schema, params)
r.NotNil(d)
d.SetId(id)
return d
}

func share(t *testing.T, id string, params map[string]interface{}) *schema.ResourceData {
r := require.New(t)
d := schema.TestResourceDataRaw(t, resources.Share().Schema, params)
Expand Down
200 changes: 200 additions & 0 deletions pkg/resources/sequence.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
package resources

import (
"database/sql"
"fmt"
"log"
"strconv"

"github.com/chanzuckerberg/terraform-provider-snowflake/pkg/snowflake"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/pkg/errors"
)

var sequenceSchema = map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
Description: "Specifies the name for the sequence.",
},
"comment": {
Type: schema.TypeString,
Optional: true,
Default: "",
Description: "Specifies a comment for the sequence.",
},
"increment": {
Type: schema.TypeInt,
Optional: true,
Default: 1,
Description: "The amount the sequence will increase by each time it is used",
},
"database": {
Type: schema.TypeString,
Required: true,
Description: "The database in which to create the sequence. Don't use the | character.",
},
"schema": {
Type: schema.TypeString,
Required: true,
Description: "The schema in which to create the sequence. Don't use the | character.",
},
"next_value": {
Type: schema.TypeInt,
Description: "The next value the sequence will provide.",
Computed: true,
},
}

var sequenceProperties = []string{"comment", "data_retention_time_in_days"}

// Sequence returns a pointer to the resource representing a sequence
func Sequence() *schema.Resource {
return &schema.Resource{
Create: CreateSequence,
Read: ReadSequence,
Delete: DeleteSequence,
Update: UpdateSequence,

Schema: sequenceSchema,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
}
}

// CreateSequence implements schema.CreateFunc
func CreateSequence(d *schema.ResourceData, meta interface{}) error {
db := meta.(*sql.DB)
database := d.Get("database").(string)
schema := d.Get("schema").(string)
name := d.Get("name").(string)

sq := snowflake.Sequence(name, database, schema)

if i, ok := d.GetOk("increment"); ok {
sq.WithIncrement(i.(int))
}

if v, ok := d.GetOk("comment"); ok {
sq.WithComment(v.(string))
}

err := snowflake.Exec(db, sq.Create())
if err != nil {
return errors.Wrapf(err, "error creating sequence")
}

return ReadSequence(d, meta)
}

// ReadSequence implements schema.ReadFunc
func ReadSequence(d *schema.ResourceData, meta interface{}) error {
db := meta.(*sql.DB)
database := d.Get("database").(string)
schema := d.Get("schema").(string)
name := d.Get("name").(string)

stmt := snowflake.Sequence(name, database, schema).Show()
row := snowflake.QueryRow(db, stmt)

sequence, err := snowflake.ScanSequence(row)

if err != nil {
if err == sql.ErrNoRows {
// If not found, mark resource to be removed from statefile during apply or refresh
log.Printf("[DEBUG] sequence (%s) not found", d.Id())
d.SetId("")
return nil
}
return errors.Wrap(err, "unable to scan row for SHOW SEQUENCES")
}

err = d.Set("schema", sequence.SchemaName.String)
if err != nil {
return err
}

err = d.Set("database", sequence.DBName.String)
if err != nil {
return err
}

err = d.Set("comment", sequence.Comment.String)
if err != nil {
return err
}

i, err := strconv.ParseInt(sequence.Increment.String, 10, 64)
if err != nil {
return err
}

err = d.Set("increment", i)
if err != nil {
return err
}

i, err = strconv.ParseInt(sequence.NextValue.String, 10, 64)
if err != nil {
return err
}

err = d.Set("next_value", i)
if err != nil {
return err
}

d.SetId(fmt.Sprintf(`%v|%v|%v`, sequence.DBName.String, sequence.SchemaName.String, sequence.Name.String))
if err != nil {
return err
}

return err
}

func UpdateSequence(d *schema.ResourceData, meta interface{}) error {
db := meta.(*sql.DB)
database := d.Get("database").(string)
schema := d.Get("schema").(string)
name := d.Get("name").(string)
next := d.Get("next_value").(int)

DeleteSequence(d, meta)

sq := snowflake.Sequence(name, database, schema)

if i, ok := d.GetOk("increment"); ok {
sq.WithIncrement(i.(int))
}

if v, ok := d.GetOk("comment"); ok {
sq.WithComment(v.(string))
}

sq.WithStart(next)

err := snowflake.Exec(db, sq.Create())
if err != nil {
return errors.Wrapf(err, "error creating sequence")
}

return ReadSequence(d, meta)
}

func DeleteSequence(d *schema.ResourceData, meta interface{}) error {
db := meta.(*sql.DB)
database := d.Get("database").(string)
schema := d.Get("schema").(string)
name := d.Get("name").(string)

stmt := snowflake.Sequence(name, database, schema).Drop()

err := snowflake.Exec(db, stmt)
if err != nil {
return errors.Wrapf(err, "error dropping sequence %s", name)
}

d.SetId("")
return nil
}
Loading