diff --git a/nomad/resource_job.go b/nomad/resource_job.go index e3ac7c73..7c7bd23c 100644 --- a/nomad/resource_job.go +++ b/nomad/resource_job.go @@ -9,6 +9,7 @@ import ( "fmt" "log" "reflect" + "slices" "sort" "strconv" "strings" @@ -152,6 +153,12 @@ func resourceJob() *schema.Resource { Type: schema.TypeString, }, + "status": { + Description: "The status of the job.", + Computed: true, + Type: schema.TypeString, + }, + "region": { Description: "The target region for the job, as derived from the jobspec.", Computed: true, @@ -604,6 +611,7 @@ func resourceJobRead(d *schema.ResourceData, meta interface{}) error { } else { d.Set("modify_index", "0") } + d.Set("status", job.Status) if d.Get("read_allocation_ids").(bool) { allocStubs, _, err := client.Jobs().Allocations(id, false, opts) @@ -639,9 +647,14 @@ func resourceJobCustomizeDiff(_ context.Context, d *schema.ResourceDiff, meta in d.SetNewComputed("task_groups") d.SetNewComputed("deployment_id") d.SetNewComputed("deployment_status") + d.SetNewComputed("status") return nil } + if !slices.Contains([]string{"running", "pending"}, d.Get("status").(string)) { + d.SetNewComputed("status") + } + oldSpecRaw, newSpecRaw := d.GetChange("jobspec") if jobspecEqual("jobspec", oldSpecRaw.(string), newSpecRaw.(string), d) { @@ -696,6 +709,7 @@ func resourceJobCustomizeDiff(_ context.Context, d *schema.ResourceDiff, meta in d.SetNew("type", job.Type) d.SetNew("region", job.Region) d.SetNew("datacenters", job.Datacenters) + d.SetNew("status", job.Status) // If the identity has changed and the config asks us to deregister on identity // change then the id field "forces new resource". diff --git a/nomad/resource_job_test.go b/nomad/resource_job_test.go index 179bba10..9bd4b2ab 100644 --- a/nomad/resource_job_test.go +++ b/nomad/resource_job_test.go @@ -3457,3 +3457,48 @@ job "example" { }) } } + +func testResourceJob_externalStopCheck(t *testing.T) r.TestCheckFunc { + return func(s *terraform.State) error { + resourceState := s.Modules[0].Resources["nomad_job.test"] + if resourceState == nil { + return errors.New("resource not found in state") + } + + instanceState := resourceState.Primary + if instanceState == nil { + return errors.New("resource has no primary instance") + } + + jobID := instanceState.ID + providerConfig := testProvider.Meta().(ProviderConfig) + client := providerConfig.client + _, _, err := client.Jobs().Deregister(jobID, false, &api.WriteOptions{ + Namespace: instanceState.Attributes["namespace"], + }) + if err != nil { + return fmt.Errorf("error reading back job: %s", err) + } + + return nil + } +} + +func TestResourceJob_externalStop(t *testing.T) { + r.Test(t, r.TestCase{ + Providers: testProviders, + PreCheck: func() { testAccPreCheck(t) }, + Steps: []r.TestStep{ + { + Config: testResourceJob_initialConfig, + Check: testResourceJob_initialCheck(t), + }, + { + Config: testResourceJob_initialConfig, + Check: testResourceJob_externalStopCheck(t), + ExpectNonEmptyPlan: true, + }, + }, + CheckDestroy: testResourceJob_checkDestroy("foo"), + }) +}