diff --git a/docs/resources/user_password_policy_attachment.md b/docs/resources/user_password_policy_attachment.md index 28d19855b6..6edcb557e9 100644 --- a/docs/resources/user_password_policy_attachment.md +++ b/docs/resources/user_password_policy_attachment.md @@ -14,19 +14,19 @@ Specifies the password policy to use for a certain user. ```terraform resource "snowflake_user" "user" { - name = "USER_NAME" + name = "USER_NAME" } resource "snowflake_password_policy" "pp" { - database = "prod" - schema = "security" - name = "default_policy" + database = "prod" + schema = "security" + name = "default_policy" } resource "snowflake_user_password_policy_attachment" "ppa" { - password_policy_database = snowflake_password_policy.pp.database - password_policy_schema = snowflake_password_policy.pp.schema - password_policy_name = snowflake_password_policy.pp.name - user_name = snowflake_user.user.name + password_policy_database = snowflake_password_policy.pp.database + password_policy_schema = snowflake_password_policy.pp.schema + password_policy_name = snowflake_password_policy.pp.name + user_name = snowflake_user.user.name } ``` diff --git a/examples/resources/snowflake_user_password_policy_attachment/resource.tf b/examples/resources/snowflake_user_password_policy_attachment/resource.tf index b718dcc5da..656b60580d 100644 --- a/examples/resources/snowflake_user_password_policy_attachment/resource.tf +++ b/examples/resources/snowflake_user_password_policy_attachment/resource.tf @@ -1,15 +1,15 @@ resource "snowflake_user" "user" { - name = "USER_NAME" + name = "USER_NAME" } resource "snowflake_password_policy" "pp" { - database = "prod" - schema = "security" - name = "default_policy" + database = "prod" + schema = "security" + name = "default_policy" } resource "snowflake_user_password_policy_attachment" "ppa" { - password_policy_database = snowflake_password_policy.pp.database - password_policy_schema = snowflake_password_policy.pp.schema - password_policy_name = snowflake_password_policy.pp.name - user_name = snowflake_user.user.name + password_policy_database = snowflake_password_policy.pp.database + password_policy_schema = snowflake_password_policy.pp.schema + password_policy_name = snowflake_password_policy.pp.name + user_name = snowflake_user.user.name } diff --git a/pkg/resources/task.go b/pkg/resources/task.go index d6eed48516..44d72c9705 100644 --- a/pkg/resources/task.go +++ b/pkg/resources/task.go @@ -11,6 +11,7 @@ import ( "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) @@ -149,6 +150,9 @@ func Task() *schema.Resource { Read: ReadTask, Update: UpdateTask, Delete: DeleteTask, + CustomizeDiff: customdiff.ForceNewIfChange("when", func(ctx context.Context, old, new, meta any) bool { + return old.(string) != "" && new.(string) == "" + }), Schema: taskSchema, Importer: &schema.ResourceImporter{ diff --git a/pkg/resources/task_acceptance_test.go b/pkg/resources/task_acceptance_test.go index 91f32876ec..01d7d74a46 100644 --- a/pkg/resources/task_acceptance_test.go +++ b/pkg/resources/task_acceptance_test.go @@ -8,10 +8,14 @@ import ( "text/template" acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + "github.com/hashicorp/terraform-plugin-testing/config" "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-plugin-testing/tfversion" ) type ( @@ -668,3 +672,106 @@ func checkInt64(name, key string, value int64) func(*terraform.State) error { return resource.TestCheckResourceAttr(name, key, fmt.Sprintf("%v", value))(state) } } + +func TestAcc_Task_issue2207(t *testing.T) { + prefix := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha) + rootName := prefix + "_root_task" + childName := prefix + "_child_task" + + m := func() map[string]config.Variable { + return map[string]config.Variable{ + "root_name": config.StringVariable(rootName), + "database": config.StringVariable(acc.TestDatabaseName), + "schema": config.StringVariable(acc.TestSchemaName), + "warehouse": config.StringVariable(acc.TestWarehouseName), + "child_name": config.StringVariable(childName), + "comment": config.StringVariable("abc"), + } + } + m2 := m() + m2["comment"] = config.StringVariable("def") + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + PreCheck: func() { acc.TestAccPreCheck(t) }, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + CheckDestroy: nil, + Steps: []resource.TestStep{ + { + ConfigDirectory: config.TestStepDirectory(), + ConfigVariables: m(), + Check: resource.ComposeTestCheckFunc( + checkBool("snowflake_task.root_task", "enabled", true), + checkBool("snowflake_task.child_task", "enabled", true), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PostApplyPostRefresh: []plancheck.PlanCheck{ + plancheck.ExpectEmptyPlan(), + }, + }, + }, + // change comment + { + ConfigDirectory: acc.ConfigurationSameAsStepN(1), + ConfigVariables: m2, + Check: resource.ComposeTestCheckFunc( + checkBool("snowflake_task.root_task", "enabled", true), + checkBool("snowflake_task.child_task", "enabled", true), + ), + }, + }, + }) +} + +func TestAcc_Task_issue2036(t *testing.T) { + name := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha) + + m := func() map[string]config.Variable { + return map[string]config.Variable{ + "name": config.StringVariable(name), + "database": config.StringVariable(acc.TestDatabaseName), + "schema": config.StringVariable(acc.TestSchemaName), + "warehouse": config.StringVariable(acc.TestWarehouseName), + } + } + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + PreCheck: func() { acc.TestAccPreCheck(t) }, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + CheckDestroy: nil, + Steps: []resource.TestStep{ + // create without when + { + ConfigDirectory: config.TestStepDirectory(), + ConfigVariables: m(), + Check: resource.ComposeTestCheckFunc( + checkBool("snowflake_task.test_task", "enabled", true), + resource.TestCheckResourceAttr("snowflake_task.test_task", "when", ""), + ), + }, + // add when + { + ConfigDirectory: config.TestStepDirectory(), + ConfigVariables: m(), + Check: resource.ComposeTestCheckFunc( + checkBool("snowflake_task.test_task", "enabled", true), + resource.TestCheckResourceAttr("snowflake_task.test_task", "when", "TRUE"), + ), + }, + // remove when + { + ConfigDirectory: acc.ConfigurationSameAsStepN(1), + ConfigVariables: m(), + Check: resource.ComposeTestCheckFunc( + checkBool("snowflake_task.test_task", "enabled", true), + resource.TestCheckResourceAttr("snowflake_task.test_task", "when", ""), + ), + }, + }, + }) +} diff --git a/pkg/resources/testdata/TestAcc_Task_issue2036/1/test.tf b/pkg/resources/testdata/TestAcc_Task_issue2036/1/test.tf new file mode 100644 index 0000000000..d095e18684 --- /dev/null +++ b/pkg/resources/testdata/TestAcc_Task_issue2036/1/test.tf @@ -0,0 +1,9 @@ +resource "snowflake_task" "test_task" { + name = var.name + database = var.database + schema = var.schema + warehouse = var.warehouse + sql_statement = "SELECT 1" + enabled = true + schedule = "5 MINUTE" +} \ No newline at end of file diff --git a/pkg/resources/testdata/TestAcc_Task_issue2036/1/variables.tf b/pkg/resources/testdata/TestAcc_Task_issue2036/1/variables.tf new file mode 100644 index 0000000000..01e8e1a797 --- /dev/null +++ b/pkg/resources/testdata/TestAcc_Task_issue2036/1/variables.tf @@ -0,0 +1,15 @@ +variable "database" { + type = string +} + +variable "schema" { + type = string +} + +variable "warehouse" { + type = string +} + +variable "name" { + type = string +} diff --git a/pkg/resources/testdata/TestAcc_Task_issue2036/2/test.tf b/pkg/resources/testdata/TestAcc_Task_issue2036/2/test.tf new file mode 100644 index 0000000000..4c6e9d5521 --- /dev/null +++ b/pkg/resources/testdata/TestAcc_Task_issue2036/2/test.tf @@ -0,0 +1,10 @@ +resource "snowflake_task" "test_task" { + name = var.name + database = var.database + schema = var.schema + warehouse = var.warehouse + sql_statement = "SELECT 1" + enabled = true + schedule = "5 MINUTE" + when = "TRUE" +} diff --git a/pkg/resources/testdata/TestAcc_Task_issue2036/2/variables.tf b/pkg/resources/testdata/TestAcc_Task_issue2036/2/variables.tf new file mode 100644 index 0000000000..01e8e1a797 --- /dev/null +++ b/pkg/resources/testdata/TestAcc_Task_issue2036/2/variables.tf @@ -0,0 +1,15 @@ +variable "database" { + type = string +} + +variable "schema" { + type = string +} + +variable "warehouse" { + type = string +} + +variable "name" { + type = string +} diff --git a/pkg/resources/testdata/TestAcc_Task_issue2207/1/test.tf b/pkg/resources/testdata/TestAcc_Task_issue2207/1/test.tf new file mode 100644 index 0000000000..0d57ab1811 --- /dev/null +++ b/pkg/resources/testdata/TestAcc_Task_issue2207/1/test.tf @@ -0,0 +1,20 @@ +resource "snowflake_task" "root_task" { + name = var.root_name + database = var.database + schema = var.schema + warehouse = var.warehouse + sql_statement = "SELECT 1" + enabled = true + schedule = "5 MINUTE" +} + +resource "snowflake_task" "child_task" { + name = var.child_name + database = snowflake_task.root_task.database + schema = snowflake_task.root_task.schema + warehouse = snowflake_task.root_task.warehouse + sql_statement = "SELECT 1" + enabled = true + after = [snowflake_task.root_task.name] + comment = var.comment +} diff --git a/pkg/resources/testdata/TestAcc_Task_issue2207/1/variables.tf b/pkg/resources/testdata/TestAcc_Task_issue2207/1/variables.tf new file mode 100644 index 0000000000..fe59da5d99 --- /dev/null +++ b/pkg/resources/testdata/TestAcc_Task_issue2207/1/variables.tf @@ -0,0 +1,23 @@ +variable "database" { + type = string +} + +variable "schema" { + type = string +} + +variable "warehouse" { + type = string +} + +variable "root_name" { + type = string +} + +variable "child_name" { + type = string +} + +variable "comment" { + type = string +} diff --git a/pkg/sdk/tasks_impl_gen.go b/pkg/sdk/tasks_impl_gen.go index 7a2ad0887d..8eb45f5706 100644 --- a/pkg/sdk/tasks_impl_gen.go +++ b/pkg/sdk/tasks_impl_gen.go @@ -284,7 +284,10 @@ func getPredecessors(predecessors string) ([]string, error) { for i, predecessorName := range predecessorNames { formattedName := strings.Trim(predecessorName, "\\\"") idx := strings.LastIndex(formattedName, "\"") + 1 - if strings.LastIndex(formattedName, ".\"")+2 < idx { + // -1 because of not found +1 is 0 + if idx == 0 { + idx = strings.LastIndex(formattedName, ".") + 1 + } else if strings.LastIndex(formattedName, ".\"")+2 < idx { idx++ } formattedName = formattedName[idx:] diff --git a/pkg/sdk/tasks_test.go b/pkg/sdk/tasks_test.go index 0faf8bf20e..775bf3e91c 100644 --- a/pkg/sdk/tasks_test.go +++ b/pkg/sdk/tasks_test.go @@ -97,7 +97,9 @@ func Test_getPredecessors(t *testing.T) { {predecessorsRaw: "[\n \"\\\"qgb)Z1KcNWJ(\\\".\\\"glN@JtR=7dzP$7\\\".Ls.T7-(bt{.lWd@DRWkyA6<6hNdh\"\n]", expectedPredecessors: []string{"Ls.T7-(bt{.lWd@DRWkyA6<6hNdh"}}, {predecessorsRaw: fmt.Sprintf("[\n \"\\\"a\\\".\\\"b\\\".\\\"%s\\\"\"\n]", special), expectedPredecessors: []string{special}}, {predecessorsRaw: "[\n \"\\\"a\\\".\\\"b\\\".\\\"c\\\"\",\"\\\"a\\\".\\\"b\\\".\\\"d\\\"\",\"\\\"a\\\".\\\"b\\\".\\\"e\\\"\"\n]", expectedPredecessors: []string{"c", "d", "e"}}, - {predecessorsRaw: "[\"\\\"a\\\".\\\"b\\\".\\\".PHo,k:%Sz8tdx,9?23xTsgHLYxe\\\"\"]", expectedPredecessors: []string{".PHo,k:%Sz8tdx,9?23xTsgHLYxe"}}, + {predecessorsRaw: `["\"a\".\"b\".\".PHo,k:%Sz8tdx,9?23xTsgHLYxe\""]`, expectedPredecessors: []string{".PHo,k:%Sz8tdx,9?23xTsgHLYxe"}}, + {predecessorsRaw: `["MY_DB.MY_SCH.MY_PARENT_TASK"]`, expectedPredecessors: []string{"MY_PARENT_TASK"}}, + {predecessorsRaw: `["CTG_DEV_PLK.INGESTION.COPY_FROM_KINESIS_S3_DELIVERY"]`, expectedPredecessors: []string{"COPY_FROM_KINESIS_S3_DELIVERY"}}, } for i, tt := range tests { t.Run(fmt.Sprintf("test number %d for input: [%s]", i, tt.predecessorsRaw), func(t *testing.T) {