Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Device Management: ExportJobs #765

Closed
jkroepke opened this issue Aug 27, 2024 · 5 comments
Closed

Device Management: ExportJobs #765

jkroepke opened this issue Aug 27, 2024 · 5 comments
Labels

Comments

@jkroepke
Copy link

Describe the bug

I'm trying to use the export Job API to get an report via API.

I'm using the document: https://learn.microsoft.com/en-us/mem/intune/fundamentals/reports-export-graph-apis

Based on that information, I also found this Graph API docs: https://learn.microsoft.com/en-us/graph/api/intune-reporting-devicemanagementexportjob-create?view=graph-rest-1.0&tabs=http

Based on the code posted below, the SDK tries to fetch an wrong URL to obtain the status for the export.

	for {
		if exportJob == nil {
			exportJob, err = h.graphServiceClient.DeviceManagement().Reports().ExportJobs().
				Post(r.Context(), upstreamRequestBody, nil)
		} else {
			exportJob, err = h.graphServiceClient.DeviceManagement().Reports().ExportJobs().
				WithUrl(*exportJob.GetUrl()).
				Get(r.Context(), upstreamRequestBody, nil)
            /* MS Graph set the URL to 
                https://graph.microsoft.com/v1.0/deviceManagement/reports/exportJobs/PolicyNonComplianceAgg_a2546aac-ba8d-4928-95e6-64a00e6fc28e
                but according to docs,
                https://graph.microsoft.com/v1.0/deviceManagement/reports/exportJobs('PolicyNonComplianceAgg_a2546aac-ba8d-4928-95e6-64a00e6fc28e')
                is correct.
            */
		}
     }

Expected behavior

I'm able to use Graph SDK the get the data from exportJob

How to reproduce

type Body struct {
	ReportName string   `json:"reportName"`
	Format     string   `json:"format"`
	Filter     string   `json:"filter"`
	Search     string   `json:"search"`
	Select     []string `json:"select"`
}

func main() {
	requestody := Body{
		ReportName: "PolicyNonComplianceAgg",
		Format:     "csv",
		Filter:     "((PolicyBaseTypeName eq 'Microsoft.Management.Services.Api.DeviceConfiguration') or (PolicyBaseTypeName eq 'DeviceManagementConfigurationPolicy') or (PolicyBaseTypeName eq 'Microsoft.Management.Services.Api.DeviceManagementIntent'))",
		Search:     "",
		Select: []string{
			"PolicyName",
			"UnifiedPolicyType",
			"ProfileSource",
			"UnifiedPolicyPlatformType",
			"NumberOfNonCompliantOrErrorDevices",
			"NumberOfConflictDevices",
		},
	}

    upstreamRequestBody := models.NewDeviceManagementExportJob()
	upstreamRequestBody.SetFormat(reportFileFormat.(*models.DeviceManagementReportFileFormat))
	upstreamRequestBody.SetFilter(&requestBody.Filter)
	upstreamRequestBody.SetSelectEscaped(requestBody.Select)
	upstreamRequestBody.SetReportName(&requestBody.ReportName)

	var (
		reportURL *string
		exportJob models.DeviceManagementExportJobable
	)

	for {
		if exportJob == nil {
			exportJob, err = h.graphServiceClient.DeviceManagement().Reports().ExportJobs().
				Post(r.Context(), upstreamRequestBody, nil)
		} else {
			exportJob, err = h.graphServiceClient.DeviceManagement().Reports().ExportJobs().
				WithUrl(*exportJob.GetUrl()).
				Get(r.Context(), upstreamRequestBody, nil)
            /* MS Graph set the URL to 
                https://graph.microsoft.com/v1.0/deviceManagement/reports/exportJobs/PolicyNonComplianceAgg_a2546aac-ba8d-4928-95e6-64a00e6fc28e
                but according to docs,
                https://graph.microsoft.com/beta/deviceManagement/reports/exportJobs('PolicyNonComplianceAgg_a2546aac-ba8d-4928-95e6-64a00e6fc28e')
                is correct.
            */
		}

		if err != nil {
			var oDataErr *odataerrors.ODataError
			if errors.As(err, &oDataErr) {
				h.Logger.Error(fmt.Errorf("failed to get exportJob: %s", oDataErr.Error()).Error())

				w.WriteHeader(oDataErr.ResponseStatusCode)

				if _, err = w.Write([]byte(oDataErr.Error())); err != nil {
					h.Logger.Error(fmt.Errorf("failed to write the error response: %w", err).Error())
				}

				return
			}

			h.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to get exportJob: %w", err))

			return
		}

		status := exportJob.GetStatus()
		if status == nil {
			h.Error(w, http.StatusInternalServerError, errors.New("failed to get the status of the export job"))

			return
		}

		if *status == models.COMPLETED_DEVICEMANAGEMENTREPORTSTATUS {
			if reportURL = exportJob.GetUrl(); reportURL == nil {
				h.Error(w, http.StatusInternalServerError, errors.New("failed to get the URL of the export job"))

				return
			}

			break
		}

		time.Sleep(1 * time.Second)
	}
}

SDK Version

v1.47.0

Latest version known to work for scenario above?

No response

Known Workarounds

N/A

Debug output

Click to expand log ```
</details>


### Configuration

- OS: mac
- Arch: ARCH

### Other information

_No response_
@jkroepke jkroepke added status:waiting-for-triage An issue that is yet to be reviewed or assigned type:bug A broken experience labels Aug 27, 2024
@andrueastman
Copy link
Member

Thanks for raising this @jkroepke

Any chance you can reshare the link for the docs page? I believe the link you shared is for creating a job and not reading a job.

Do you get different results if you perform

                https://graph.microsoft.com/v1.0/deviceManagement/reports/exportJobs/PolicyNonComplianceAgg_a2546aac-ba8d-4928-95e6-64a00e6fc28e

vs

                https://graph.microsoft.com/v1.0/deviceManagement/reports/exportJobs('PolicyNonComplianceAgg_a2546aac-ba8d-4928-95e6-64a00e6fc28e')

In my head the two are functionally equivalent given the convention supported by Odata.
https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_KeyasSegmentConvention

@andrueastman andrueastman added status:waiting-for-author-feedback Issue that we've responded but needs author feedback to close and removed status:waiting-for-triage An issue that is yet to be reviewed or assigned labels Aug 29, 2024
@jkroepke
Copy link
Author

jkroepke commented Aug 29, 2024

Any chance you can reshare the link for the docs page?

Sure, take a look at the first post: https://learn.microsoft.com/en-us/mem/intune/fundamentals/reports-export-graph-apis

Do a POST on /v1.0/deviceManagement/reports/exportJobs
get the ID
Loop GET https://graph.microsoft.com/beta/deviceManagement/reports/exportJobs('ID') until status is complete.

Do GET on url property. to fetch the report.

I do this manually via Postman and it works.

image
image

Do you get different results if you perform

Hm. No. I test it via Postman and they are equal. I have to check the code. Would it be possible to adjust the docs? If I would do a support request via MS Ticket, I expect that they would blame me, that "my" code does not following the docs.

@microsoft-github-policy-service microsoft-github-policy-service bot added Needs Attention 👋 and removed status:waiting-for-author-feedback Issue that we've responded but needs author feedback to close labels Aug 29, 2024
@andrueastman
Copy link
Member

Would it be possible to adjust the docs? If I would do a support request via MS Ticket, I expect that they would blame me, that "my" code does not following the docs.

Would you be willing to submit a PR? If you click on the edit icon on the page you're interested in, it should redirect you to the file to update. Once you do this, the API owner of the doc page should be able to update and fix this as you request.
image

@jkroepke
Copy link
Author

@microsoft-github-policy-service microsoft-github-policy-service bot added Needs Attention 👋 and removed status:waiting-for-author-feedback Issue that we've responded but needs author feedback to close labels Aug 29, 2024
@jkroepke
Copy link
Author

@andrueastman I will close the issue. I have no clue what my issue initially was. after testing the API with Postman, everything works and now it works with the SDK as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants