diff --git a/bundle/deploy/terraform/convert.go b/bundle/deploy/terraform/convert.go index f13c241ce..6992a630d 100644 --- a/bundle/deploy/terraform/convert.go +++ b/bundle/deploy/terraform/convert.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "sort" "github.com/databricks/cli/bundle/config" "github.com/databricks/cli/bundle/config/resources" @@ -82,6 +83,10 @@ func BundleToTerraform(config *config.Root) *schema.Root { conv(src, &dst) if src.JobSettings != nil { + sort.Slice(src.JobSettings.Tasks, func(i, j int) bool { + return src.JobSettings.Tasks[i].TaskKey < src.JobSettings.Tasks[j].TaskKey + }) + for _, v := range src.Tasks { var t schema.ResourceJobTask conv(v, &t) diff --git a/bundle/deploy/terraform/tfdyn/convert_job.go b/bundle/deploy/terraform/tfdyn/convert_job.go index a29c9cc1e..dbf56f84c 100644 --- a/bundle/deploy/terraform/tfdyn/convert_job.go +++ b/bundle/deploy/terraform/tfdyn/convert_job.go @@ -25,15 +25,28 @@ func convertJobResource(ctx context.Context, vin dyn.Value) (dyn.Value, error) { // recreates. For more details see the NOTE at // https://registry.terraform.io/providers/databricks/databricks/latest/docs/resources/job#example-usage // and https://github.com/databricks/terraform-provider-databricks/issues/4011 - tasks := vin.Get("tasks").MustSequence() - sort.Slice(tasks, func(i, j int) bool { - return tasks[i].Get("task_key").MustString() < tasks[j].Get("task_key").MustString() - }) - vout, err := dyn.Map(vin, "tasks", func(_ dyn.Path, _ dyn.Value) (dyn.Value, error) { - return dyn.V(tasks), nil - }) - if err != nil { - return dyn.InvalidValue, err + // TODO: Is this safe for nil values of task key? Empty strings? + vout := vin + var err error + tasks, ok := vin.Get("tasks").AsSequence() + if ok { + sort.Slice(tasks, func(i, j int) bool { + tk1, ok := tasks[i].Get("task_key").AsString() + if !ok { + return true + } + tk2, ok := tasks[j].Get("task_key").AsString() + if !ok { + return false + } + return tk1 < tk2 + }) + vout, err = dyn.Map(vin, "tasks", func(_ dyn.Path, _ dyn.Value) (dyn.Value, error) { + return dyn.V(tasks), nil + }) + if err != nil { + return dyn.InvalidValue, err + } } // Modify top-level keys. diff --git a/bundle/deploy/terraform/tfdyn/convert_job_test.go b/bundle/deploy/terraform/tfdyn/convert_job_test.go index 57da750b7..695b9ba24 100644 --- a/bundle/deploy/terraform/tfdyn/convert_job_test.go +++ b/bundle/deploy/terraform/tfdyn/convert_job_test.go @@ -63,6 +63,9 @@ func TestConvertJob(t *testing.T) { TaskKey: "task_key_c", JobClusterKey: "job_cluster_key_c", }, + { + Description: "missing task key 😱", + }, }, }, Permissions: []resources.Permission{ @@ -107,6 +110,9 @@ func TestConvertJob(t *testing.T) { }, }, "task": []any{ + map[string]any{ + "description": "missing task key 😱", + }, map[string]any{ "task_key": "task_key_a", "job_cluster_key": "job_cluster_key_a",