Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 2 additions & 0 deletions NEXT_CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@
### Exporter

### Internal Changes

* Rewrite `databricks_job` data source to use Go SDK ([#5078](https://github.com/databricks/terraform-provider-databricks/pull/5078))
72 changes: 45 additions & 27 deletions jobs/data_job.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,23 @@ package jobs
import (
"context"
"fmt"
"strconv"

"github.com/databricks/databricks-sdk-go"
sdk_jobs "github.com/databricks/databricks-sdk-go/service/jobs"
"github.com/databricks/terraform-provider-databricks/common"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func DataSourceJob() common.Resource {
type queryableJobData struct {
Id string `json:"id,omitempty" tf:"computed"`
JobId string `json:"job_id,omitempty" tf:"computed"`
Name string `json:"name,omitempty" tf:"computed"`
JobName string `json:"job_name,omitempty" tf:"computed"`
Job *Job `json:"job_settings,omitempty" tf:"computed"`
Id string `json:"id,omitempty" tf:"computed"`
JobId string `json:"job_id,omitempty" tf:"computed"`
Name string `json:"name,omitempty" tf:"computed"`
JobName string `json:"job_name,omitempty" tf:"computed"`
Job *sdk_jobs.Job `json:"job_settings,omitempty" tf:"computed"`
}
return common.DataResource(queryableJobData{}, func(ctx context.Context, e any, c *common.DatabricksClient) error {
data := e.(*queryableJobData)
jobsAPI := NewJobsAPI(ctx, c)
var list []Job
return common.WorkspaceDataWithCustomizeFunc(func(ctx context.Context, data *queryableJobData, w *databricks.WorkspaceClient) error {
var err error
if data.Id == "" {
data.Id = data.JobId
Expand All @@ -28,35 +29,52 @@ func DataSourceJob() common.Resource {
}
if data.Name != "" {
// if name is provided, need to list all jobs ny name
list, err = jobsAPI.ListByName(data.Name, true)
} else {
// otherwise, just read the job
var job Job
job, err = jobsAPI.Read(data.Id)
// find only job ID, then use `GetByJobId` to get the job with all fields
list, err := w.Jobs.ListAll(ctx, sdk_jobs.ListJobsRequest{ExpandTasks: false, Name: data.Name, Limit: 100})
if err != nil {
return err
}
data.Job = &job
data.Name = job.Settings.Name
found := false
for _, job := range list {
currentJob := job // De-referencing the temp variable used by the loop
currentJobName := currentJob.Settings.Name
jobIdString := strconv.FormatInt(currentJob.JobId, 10)
if currentJobName == data.Name || jobIdString == data.Id {
data.Name = currentJobName
data.Id = jobIdString
found = true
break // break the loop after we found the job
}
}
if !found {
return fmt.Errorf("no job found with specified name")
}
}
// read the job by ID
jobId, err := strconv.ParseInt(data.Id, 10, 64)
if err != nil {
return err
}
for _, job := range list {
currentJob := job // De-referencing the temp variable used by the loop
currentJobId := currentJob.ID()
currentJobName := currentJob.Settings.Name
if currentJobName == data.Name || currentJobId == data.Id {
data.Job = &currentJob
data.Name = currentJobName
data.Id = currentJobId
data.JobId = currentJobId
return nil // break the loop after we found the job
}
job, err := w.Jobs.Get(ctx, sdk_jobs.GetJobRequest{JobId: jobId})
if err != nil {
return err
}
data.Job = job
data.Name = job.Settings.Name
data.JobName = job.Settings.Name
data.JobId = data.Id
if data.Job == nil {
return fmt.Errorf("no job found with specified name")
}

return nil
}, func(s map[string]*schema.Schema) map[string]*schema.Schema {
// Customize the git_source schema to fix ConflictsWith paths
if gitSource, err := common.SchemaPath(s, "job_settings", "settings", "git_source"); err == nil {
if gitSourceResource, ok := gitSource.Elem.(*schema.Resource); ok {
gitSourceSchema(gitSourceResource.Schema, "job_settings.0.settings.0.")
}
}
return s
})
}
193 changes: 79 additions & 114 deletions jobs/data_job_test.go
Original file line number Diff line number Diff line change
@@ -1,75 +1,24 @@
package jobs

import (
"fmt"
"testing"

"github.com/databricks/databricks-sdk-go/apierr"
"github.com/databricks/databricks-sdk-go/experimental/mocks"
"github.com/databricks/databricks-sdk-go/service/jobs"
"github.com/databricks/terraform-provider-databricks/qa"
"github.com/stretchr/testify/mock"
)

func commonFixtures(name string) []qa.HTTPFixture {
resource := "/api/2.1/jobs/list?expand_tasks=false&limit=25"
if name != "" {
resource = fmt.Sprintf("/api/2.1/jobs/list?expand_tasks=true&limit=25&name=%s", name)
}
return []qa.HTTPFixture{
{
Method: "GET",
Resource: resource,
Response: JobListResponse{
Jobs: []Job{
{
JobID: 123,
Settings: &JobSettings{
Name: "First",
},
},
{
JobID: 234,
Settings: &JobSettings{
Name: "Second",
},
},
},
},
},
{
Method: "GET",
Resource: resource,
Response: JobListResponse{
Jobs: []Job{
{
JobID: 123,
Settings: &JobSettings{
Name: "First",
},
},
{
JobID: 234,
Settings: &JobSettings{
Name: "Second",
},
},
},
},
},
}

}
func TestDataSourceQueryableJobMatchesId(t *testing.T) {
qa.ResourceFixture{
Fixtures: []qa.HTTPFixture{
{
Method: "GET",
Resource: "/api/2.0/jobs/get?job_id=234",
Response: Job{
JobID: 234,
Settings: &JobSettings{
Name: "Second",
},
MockWorkspaceClientFunc: func(w *mocks.MockWorkspaceClient) {
w.GetMockJobsAPI().EXPECT().Get(mock.Anything, jobs.GetJobRequest{JobId: 234}).Return(&jobs.Job{
JobId: 234,
Settings: &jobs.JobSettings{
Name: "Second",
},
},
}, nil)
},
Resource: DataSourceJob(),
Read: true,
Expand All @@ -87,19 +36,18 @@ func TestDataSourceQueryableJobMatchesId(t *testing.T) {
func TestDataSourceQueryableJobRunAsSP(t *testing.T) {
spID := "3f670caf-9a4b-4479-8143-1a0878da8f57"
qa.ResourceFixture{
Fixtures: []qa.HTTPFixture{
{
Method: "GET",
Resource: "/api/2.0/jobs/get?job_id=234",
Response: Job{
JobID: 234,
Settings: &JobSettings{
Name: "Second",
MockWorkspaceClientFunc: func(w *mocks.MockWorkspaceClient) {
w.GetMockJobsAPI().EXPECT().Get(mock.Anything, jobs.GetJobRequest{JobId: 234}).Return(&jobs.Job{
JobId: 234,
Settings: &jobs.JobSettings{
Name: "Second",
RunAs: &jobs.JobRunAs{
ServicePrincipalName: spID,
},
CreatorUserName: "[email protected]",
RunAsUserName: spID,
},
},
CreatorUserName: "[email protected]",
RunAsUserName: spID,
}, nil)
},
Resource: DataSourceJob(),
Read: true,
Expand All @@ -117,19 +65,18 @@ func TestDataSourceQueryableJobRunAsSP(t *testing.T) {

func TestDataSourceQueryableJobRunAsSameUser(t *testing.T) {
qa.ResourceFixture{
Fixtures: []qa.HTTPFixture{
{
Method: "GET",
Resource: "/api/2.0/jobs/get?job_id=234",
Response: Job{
JobID: 234,
Settings: &JobSettings{
Name: "Second",
MockWorkspaceClientFunc: func(w *mocks.MockWorkspaceClient) {
w.GetMockJobsAPI().EXPECT().Get(mock.Anything, jobs.GetJobRequest{JobId: 234}).Return(&jobs.Job{
JobId: 234,
Settings: &jobs.JobSettings{
Name: "Second",
RunAs: &jobs.JobRunAs{
UserName: "[email protected]",
},
CreatorUserName: "[email protected]",
RunAsUserName: "[email protected]",
},
},
CreatorUserName: "[email protected]",
RunAsUserName: "[email protected]",
}, nil)
},
Resource: DataSourceJob(),
Read: true,
Expand All @@ -147,19 +94,18 @@ func TestDataSourceQueryableJobRunAsSameUser(t *testing.T) {

func TestDataSourceQueryableJobRunAsAnotherUser(t *testing.T) {
qa.ResourceFixture{
Fixtures: []qa.HTTPFixture{
{
Method: "GET",
Resource: "/api/2.0/jobs/get?job_id=234",
Response: Job{
JobID: 234,
Settings: &JobSettings{
Name: "Second",
MockWorkspaceClientFunc: func(w *mocks.MockWorkspaceClient) {
w.GetMockJobsAPI().EXPECT().Get(mock.Anything, jobs.GetJobRequest{JobId: 234}).Return(&jobs.Job{
JobId: 234,
Settings: &jobs.JobSettings{
Name: "Second",
RunAs: &jobs.JobRunAs{
UserName: "[email protected]",
},
CreatorUserName: "[email protected]",
RunAsUserName: "[email protected]",
},
},
CreatorUserName: "[email protected]",
RunAsUserName: "[email protected]",
}, nil)
},
Resource: DataSourceJob(),
Read: true,
Expand All @@ -177,7 +123,32 @@ func TestDataSourceQueryableJobRunAsAnotherUser(t *testing.T) {

func TestDataSourceQueryableJobMatchesName(t *testing.T) {
qa.ResourceFixture{
Fixtures: commonFixtures("First"),
MockWorkspaceClientFunc: func(w *mocks.MockWorkspaceClient) {
w.GetMockJobsAPI().EXPECT().ListAll(mock.Anything, jobs.ListJobsRequest{
ExpandTasks: false,
Name: "First",
Limit: 100,
}).Return([]jobs.BaseJob{
{
JobId: 123,
Settings: &jobs.JobSettings{
Name: "First",
},
},
{
JobId: 234,
Settings: &jobs.JobSettings{
Name: "Second",
},
},
}, nil)
w.GetMockJobsAPI().EXPECT().Get(mock.Anything, jobs.GetJobRequest{JobId: 123}).Return(&jobs.Job{
JobId: 123,
Settings: &jobs.JobSettings{
Name: "First",
},
}, nil)
},
Resource: DataSourceJob(),
Read: true,
NonWritable: true,
Expand All @@ -192,40 +163,34 @@ func TestDataSourceQueryableJobMatchesName(t *testing.T) {

func TestDataSourceQueryableJobNoMatchName(t *testing.T) {
qa.ResourceFixture{
Fixtures: []qa.HTTPFixture{
{
Method: "GET",
Resource: "/api/2.1/jobs/list?expand_tasks=true&limit=25&name=Third",
Response: JobListResponse{
Jobs: []Job{},
},
},
MockWorkspaceClientFunc: func(w *mocks.MockWorkspaceClient) {
w.GetMockJobsAPI().EXPECT().ListAll(mock.Anything, jobs.ListJobsRequest{
ExpandTasks: false,
Name: "Third",
Limit: 100,
}).Return([]jobs.BaseJob{}, nil)
},
Resource: DataSourceJob(),
Read: true,
NonWritable: true,
HCL: `job_name= "Third"`,
HCL: `job_name = "Third"`,
ID: "_",
}.ExpectError(t, "no job found with specified name")
}

func TestDataSourceQueryableJobNoMatchId(t *testing.T) {
qa.ResourceFixture{
Fixtures: []qa.HTTPFixture{
{
Method: "GET",
Resource: "/api/2.0/jobs/get?job_id=567",
Response: apierr.APIError{
ErrorCode: "RESOURCE_DOES_NOT_EXIST",
Message: "Job 567 does not exist.",
},
Status: 404,
},
MockWorkspaceClientFunc: func(w *mocks.MockWorkspaceClient) {
w.GetMockJobsAPI().EXPECT().Get(mock.Anything, jobs.GetJobRequest{JobId: 567}).Return(nil, &apierr.APIError{
ErrorCode: "RESOURCE_DOES_NOT_EXIST",
Message: "Job 567 does not exist.",
StatusCode: 404,
})
},
Resource: DataSourceJob(),
Read: true,
NonWritable: true,
HCL: `id= "567"`,
HCL: `id = "567"`,
ID: "_",
}.ExpectError(t, "Job 567 does not exist.")
}
Loading
Loading