diff --git a/docs/resources/stage_grant.md b/docs/resources/stage_grant.md index 0c09db728e..fce0d38779 100644 --- a/docs/resources/stage_grant.md +++ b/docs/resources/stage_grant.md @@ -33,14 +33,14 @@ resource "snowflake_stage_grant" "grant" { ### Required - `database_name` (String) The name of the database containing the current stage on which to grant privileges. -- `schema_name` (String) The name of the schema containing the current stage on which to grant privileges. +- `roles` (Set of String) Grants privilege to these roles. ### Optional - `enable_multiple_grants` (Boolean) When this is set to true, multiple grants of the same type can be created. This will cause Terraform to not revoke grants applied to roles and objects outside Terraform. - `on_future` (Boolean) When this is set to true and a schema_name is provided, apply this grant on all future stages in the given schema. When this is true and no schema_name is provided apply this grant on all future stages in the given database. The stage_name field must be unset in order to use on_future. - `privilege` (String) The privilege to grant on the stage. -- `roles` (Set of String) Grants privilege to these roles. +- `schema_name` (String) The name of the schema containing the current stage on which to grant privileges. - `stage_name` (String) The name of the stage on which to grant privilege (only valid if on_future is false). - `with_grant_option` (Boolean) When this is set to true, allows the recipient role to grant the privileges to other roles. diff --git a/pkg/resources/stage_grant.go b/pkg/resources/stage_grant.go index cf37ce65d3..620220fd3d 100644 --- a/pkg/resources/stage_grant.go +++ b/pkg/resources/stage_grant.go @@ -1,6 +1,8 @@ package resources import ( + "errors" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/snowflake" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -15,25 +17,27 @@ var validStagePrivileges = NewPrivilegeSet( ) var stageGrantSchema = map[string]*schema.Schema{ - "stage_name": { - Type: schema.TypeString, - Optional: true, - Description: "The name of the stage on which to grant privilege (only valid if on_future is false).", - ForceNew: true, - ConflictsWith: []string{"on_future"}, - }, - "schema_name": { - Type: schema.TypeString, - Required: true, - Description: "The name of the schema containing the current stage on which to grant privileges.", - ForceNew: true, - }, "database_name": { Type: schema.TypeString, Required: true, Description: "The name of the database containing the current stage on which to grant privileges.", ForceNew: true, }, + "enable_multiple_grants": { + Type: schema.TypeBool, + Optional: true, + Description: "When this is set to true, multiple grants of the same type can be created. This will cause Terraform to not revoke grants applied to roles and objects outside Terraform.", + Default: false, + ForceNew: true, + }, + "on_future": { + Type: schema.TypeBool, + Optional: true, + Description: "When this is set to true and a schema_name is provided, apply this grant on all future stages in the given schema. When this is true and no schema_name is provided apply this grant on all future stages in the given database. The stage_name field must be unset in order to use on_future.", + Default: false, + ForceNew: true, + ConflictsWith: []string{"stage_name"}, + }, "privilege": { Type: schema.TypeString, Optional: true, @@ -44,17 +48,22 @@ var stageGrantSchema = map[string]*schema.Schema{ }, "roles": { Type: schema.TypeSet, + Required: true, Elem: &schema.Schema{Type: schema.TypeString}, - Optional: true, Description: "Grants privilege to these roles.", }, - "on_future": { - Type: schema.TypeBool, + "schema_name": { + Type: schema.TypeString, + Optional: true, + Description: "The name of the schema containing the current stage on which to grant privileges.", + ForceNew: true, + }, + "stage_name": { + Type: schema.TypeString, Optional: true, - Description: "When this is set to true and a schema_name is provided, apply this grant on all future stages in the given schema. When this is true and no schema_name is provided apply this grant on all future stages in the given database. The stage_name field must be unset in order to use on_future.", - Default: false, + Description: "The name of the stage on which to grant privilege (only valid if on_future is false).", ForceNew: true, - ConflictsWith: []string{"stage_name"}, + ConflictsWith: []string{"on_future"}, }, "with_grant_option": { Type: schema.TypeBool, @@ -63,13 +72,6 @@ var stageGrantSchema = map[string]*schema.Schema{ Default: false, ForceNew: true, }, - "enable_multiple_grants": { - Type: schema.TypeBool, - Optional: true, - Description: "When this is set to true, multiple grants of the same type can be created. This will cause Terraform to not revoke grants applied to roles and objects outside Terraform.", - Default: false, - ForceNew: true, - }, } // StageGrant returns a pointer to the resource representing a stage grant. @@ -92,18 +94,32 @@ func StageGrant() *TerraformGrantResource { // CreateStageGrant implements schema.CreateFunc. func CreateStageGrant(d *schema.ResourceData, meta interface{}) error { - var stageName string - if name, ok := d.GetOk("stage_name"); ok { - stageName = name.(string) - } + var ( + schemaName string + stageName string + ) + dbName := d.Get("database_name").(string) - schemaName := d.Get("schema_name").(string) + onFuture := d.Get("on_future").(bool) priv := d.Get("privilege").(string) - futureStages := d.Get("on_future").(bool) grantOption := d.Get("with_grant_option").(bool) + if name, ok := d.GetOk("schema_name"); ok { + schemaName = name.(string) + } + if name, ok := d.GetOk("stage_name"); ok { + stageName = name.(string) + } + + if (schemaName == "") && !onFuture { + return errors.New("schema_name must be set unless on_future is true") + } + if (stageName == "") && !onFuture { + return errors.New("stage_name must be set unless on_future is true") + } + var builder snowflake.GrantBuilder - if futureStages { + if onFuture { builder = snowflake.FutureStageGrant(dbName, schemaName) } else { builder = snowflake.StageGrant(dbName, schemaName, stageName) @@ -135,28 +151,27 @@ func ReadStageGrant(d *schema.ResourceData, meta interface{}) error { if err != nil { return err } + dbName := grantID.ResourceName schemaName := grantID.SchemaName stageName := grantID.ObjectName priv := grantID.Privilege + onFuture := (stageName == "") + if err := d.Set("database_name", dbName); err != nil { return err } - if err := d.Set("schema_name", schemaName); err != nil { + if err := d.Set("on_future", onFuture); err != nil { return err } - futureStagesEnabled := false - if stageName == "" { - futureStagesEnabled = true - } - if err := d.Set("stage_name", stageName); err != nil { + if err := d.Set("privilege", priv); err != nil { return err } - if err := d.Set("on_future", futureStagesEnabled); err != nil { + if err := d.Set("schema_name", schemaName); err != nil { return err } - if err := d.Set("privilege", priv); err != nil { + if err := d.Set("stage_name", stageName); err != nil { return err } if err := d.Set("with_grant_option", grantID.GrantOption); err != nil { @@ -164,35 +179,13 @@ func ReadStageGrant(d *schema.ResourceData, meta interface{}) error { } var builder snowflake.GrantBuilder - if futureStagesEnabled { + if onFuture { builder = snowflake.FutureStageGrant(dbName, schemaName) } else { builder = snowflake.StageGrant(dbName, schemaName, stageName) } - return readGenericGrant(d, meta, stageGrantSchema, builder, futureStagesEnabled, validStagePrivileges) -} - -// DeleteStageGrant implements schema.DeleteFunc. -func DeleteStageGrant(d *schema.ResourceData, meta interface{}) error { - grantID, err := grantIDFromString(d.Id()) - if err != nil { - return err - } - dbName := grantID.ResourceName - schemaName := grantID.SchemaName - stageName := grantID.ObjectName - - futureStages := (stageName == "") - - var builder snowflake.GrantBuilder - if futureStages { - builder = snowflake.FutureStageGrant(dbName, schemaName) - } else { - builder = snowflake.StageGrant(dbName, schemaName, stageName) - } - - return deleteGenericGrant(d, meta, builder) + return readGenericGrant(d, meta, stageGrantSchema, builder, onFuture, validStagePrivileges) } // UpdateStageGrant implements schema.UpdateFunc. @@ -203,13 +196,6 @@ func UpdateStageGrant(d *schema.ResourceData, meta interface{}) error { return nil } - rolesToAdd := []string{} - rolesToRevoke := []string{} - - if d.HasChange("roles") { - rolesToAdd, rolesToRevoke = changeDiff(d, "roles") - } - grantID, err := grantIDFromString(d.Id()) if err != nil { return err @@ -218,10 +204,18 @@ func UpdateStageGrant(d *schema.ResourceData, meta interface{}) error { dbName := grantID.ResourceName schemaName := grantID.SchemaName stageName := grantID.ObjectName - futureStages := (stageName == "") + + onFuture := (stageName == "") + + rolesToAdd := []string{} + rolesToRevoke := []string{} + + if d.HasChange("roles") { + rolesToAdd, rolesToRevoke = changeDiff(d, "roles") + } var builder snowflake.GrantBuilder - if futureStages { + if onFuture { builder = snowflake.FutureStageGrant(dbName, schemaName) } else { builder = snowflake.StageGrant(dbName, schemaName, stageName) @@ -243,3 +237,26 @@ func UpdateStageGrant(d *schema.ResourceData, meta interface{}) error { // Done, refresh state return ReadStageGrant(d, meta) } + +// DeleteStageGrant implements schema.DeleteFunc. +func DeleteStageGrant(d *schema.ResourceData, meta interface{}) error { + grantID, err := grantIDFromString(d.Id()) + if err != nil { + return err + } + + dbName := grantID.ResourceName + schemaName := grantID.SchemaName + stageName := grantID.ObjectName + + onFuture := (stageName == "") + + var builder snowflake.GrantBuilder + if onFuture { + builder = snowflake.FutureStageGrant(dbName, schemaName) + } else { + builder = snowflake.StageGrant(dbName, schemaName, stageName) + } + + return deleteGenericGrant(d, meta, builder) +}