mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 08:55:24 +00:00
Remove aggregate host counts from GET /hosts
responses (#7510)
This commit is contained in:
parent
d98a53f945
commit
aa0102d6b6
1
changes/issue-7489-remove-hosts-count-aggregate-stats
Normal file
1
changes/issue-7489-remove-hosts-count-aggregate-stats
Normal file
@ -0,0 +1 @@
|
|||||||
|
* Removed the `hosts_count` field from the `mobile_device_management_solution` and `munki_issue` top-level objects in the `GET /hosts` API endpoint response, as it was a pre-computed count that is updated at intervals, not a live count, and it could be confusing when it did not match the number of hosts returned.
|
@ -1743,9 +1743,9 @@ If `additional_info_filters` is not specified, no `additional` information will
|
|||||||
|
|
||||||
If `software_id` is specified, an additional top-level key `"software"` is returned with the software object corresponding to the `software_id`. See [List all software](#list-all-software) response payload for details about this object.
|
If `software_id` is specified, an additional top-level key `"software"` is returned with the software object corresponding to the `software_id`. See [List all software](#list-all-software) response payload for details about this object.
|
||||||
|
|
||||||
If `mdm_id` is specified, an additional top-level key `"mobile_device_management_solution"` is returned with the aggregated statistics corresponding to the `mdm_id` (and, if provided, `team_id`). See [Get aggregated host's mobile device management (MDM) and Munki information](#get-aggregated-hosts-mobile-device-management-mdm-and-munki-information) response payload for details about this object. Note that the statistics are for the corresponding `mdm_id` (and `team_id` if provided) only, and do not take into account other potential filters such as `mdm_enrollment_status`.
|
If `mdm_id` is specified, an additional top-level key `"mobile_device_management_solution"` is returned with the information corresponding to the `mdm_id`.
|
||||||
|
|
||||||
If `munki_issue_id` is specified, an additional top-level key `"munki_issue"` is returned with the aggregated statistics corresponding to the `munki_issue_id` (and, if provided, `team_id`). See [Get aggregated host's mobile device management (MDM) and Munki information](#get-aggregated-hosts-mobile-device-management-mdm-and-munki-information) response payload for details about this object.
|
If `munki_issue_id` is specified, an additional top-level key `"munki_issue"` is returned with the information corresponding to the `munki_issue_id`.
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
|
|
||||||
@ -1826,6 +1826,32 @@ If `munki_issue_id` is specified, an additional top-level key `"munki_issue"` is
|
|||||||
|
|
||||||
> Note: the response above assumes a [GeoIP database is configured](https://fleetdm.com/docs/deploying/configuration#geo-ip), otherwise the `geolocation` object won't be included.
|
> Note: the response above assumes a [GeoIP database is configured](https://fleetdm.com/docs/deploying/configuration#geo-ip), otherwise the `geolocation` object won't be included.
|
||||||
|
|
||||||
|
Response payload with the `mdm_id` filter provided:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"hosts": [...],
|
||||||
|
"mobile_device_management_solution": {
|
||||||
|
"server_url": "http://some.url/mdm",
|
||||||
|
"name": "MDM Vendor Name",
|
||||||
|
"id": 999
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Response payload with the `munki_issue_id` filter provided:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"hosts": [...],
|
||||||
|
"munki_issue": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "Could not retrieve managed install primary manifest",
|
||||||
|
"type": "error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Count hosts
|
### Count hosts
|
||||||
|
|
||||||
`GET /api/v1/fleet/hosts/count`
|
`GET /api/v1/fleet/hosts/count`
|
||||||
|
@ -1670,7 +1670,7 @@ func (ds *Datastore) getOrInsertMDMSolution(ctx context.Context, serverURL strin
|
|||||||
return ds.optimisticGetOrInsert(ctx, readStmt, insStmt)
|
return ds.optimisticGetOrInsert(ctx, readStmt, insStmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ds *Datastore) GetMunkiVersion(ctx context.Context, hostID uint) (string, error) {
|
func (ds *Datastore) GetHostMunkiVersion(ctx context.Context, hostID uint) (string, error) {
|
||||||
var version string
|
var version string
|
||||||
err := sqlx.GetContext(ctx, ds.reader, &version, `SELECT version FROM host_munki_info WHERE deleted_at is NULL AND host_id = ?`, hostID)
|
err := sqlx.GetContext(ctx, ds.reader, &version, `SELECT version FROM host_munki_info WHERE deleted_at is NULL AND host_id = ?`, hostID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1683,7 +1683,7 @@ func (ds *Datastore) GetMunkiVersion(ctx context.Context, hostID uint) (string,
|
|||||||
return version, nil
|
return version, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ds *Datastore) GetMDM(ctx context.Context, hostID uint) (*fleet.HostMDM, error) {
|
func (ds *Datastore) GetHostMDM(ctx context.Context, hostID uint) (*fleet.HostMDM, error) {
|
||||||
var hmdm fleet.HostMDM
|
var hmdm fleet.HostMDM
|
||||||
err := sqlx.GetContext(ctx, ds.reader, &hmdm, `
|
err := sqlx.GetContext(ctx, ds.reader, &hmdm, `
|
||||||
SELECT
|
SELECT
|
||||||
@ -1703,7 +1703,26 @@ func (ds *Datastore) GetMDM(ctx context.Context, hostID uint) (*fleet.HostMDM, e
|
|||||||
return &hmdm, nil
|
return &hmdm, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ds *Datastore) GetMunkiIssues(ctx context.Context, hostID uint) ([]*fleet.HostMunkiIssue, error) {
|
func (ds *Datastore) GetMDMSolution(ctx context.Context, mdmID uint) (*fleet.MDMSolution, error) {
|
||||||
|
var solution fleet.MDMSolution
|
||||||
|
err := sqlx.GetContext(ctx, ds.reader, &solution, `
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
server_url
|
||||||
|
FROM
|
||||||
|
mobile_device_management_solutions
|
||||||
|
WHERE id = ?`, mdmID)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, ctxerr.Wrap(ctx, notFound("MDMSolution").WithID(mdmID))
|
||||||
|
}
|
||||||
|
return nil, ctxerr.Wrapf(ctx, err, "select mobile_device_management_solutions for id %d", mdmID)
|
||||||
|
}
|
||||||
|
return &solution, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *Datastore) GetHostMunkiIssues(ctx context.Context, hostID uint) ([]*fleet.HostMunkiIssue, error) {
|
||||||
var issues []*fleet.HostMunkiIssue
|
var issues []*fleet.HostMunkiIssue
|
||||||
err := sqlx.SelectContext(ctx, ds.reader, &issues, `
|
err := sqlx.SelectContext(ctx, ds.reader, &issues, `
|
||||||
SELECT
|
SELECT
|
||||||
@ -1725,6 +1744,25 @@ func (ds *Datastore) GetMunkiIssues(ctx context.Context, hostID uint) ([]*fleet.
|
|||||||
return issues, nil
|
return issues, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ds *Datastore) GetMunkiIssue(ctx context.Context, munkiIssueID uint) (*fleet.MunkiIssue, error) {
|
||||||
|
var issue fleet.MunkiIssue
|
||||||
|
err := sqlx.GetContext(ctx, ds.reader, &issue, `
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
issue_type
|
||||||
|
FROM
|
||||||
|
munki_issues
|
||||||
|
WHERE id = ?`, munkiIssueID)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, ctxerr.Wrap(ctx, notFound("MunkiIssue").WithID(munkiIssueID))
|
||||||
|
}
|
||||||
|
return nil, ctxerr.Wrapf(ctx, err, "select munki_issues for id %d", munkiIssueID)
|
||||||
|
}
|
||||||
|
return &issue, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ds *Datastore) AggregatedMunkiVersion(ctx context.Context, teamID *uint) ([]fleet.AggregatedMunkiVersion, time.Time, error) {
|
func (ds *Datastore) AggregatedMunkiVersion(ctx context.Context, teamID *uint) ([]fleet.AggregatedMunkiVersion, time.Time, error) {
|
||||||
id := uint(0)
|
id := uint(0)
|
||||||
|
|
||||||
|
@ -948,7 +948,7 @@ func testHostsListMunkiIssueID(t *testing.T, ds *Datastore) {
|
|||||||
err = ds.SetOrUpdateMunkiInfo(ctx, hostIDs[0], "1.0.0", []string{strings.Repeat("Z", maxMunkiIssueNameLen)}, []string{strings.Repeat("💞", maxMunkiIssueNameLen)})
|
err = ds.SetOrUpdateMunkiInfo(ctx, hostIDs[0], "1.0.0", []string{strings.Repeat("Z", maxMunkiIssueNameLen)}, []string{strings.Repeat("💞", maxMunkiIssueNameLen)})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
issues, err := ds.GetMunkiIssues(ctx, hostIDs[0])
|
issues, err := ds.GetHostMunkiIssues(ctx, hostIDs[0])
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, issues, 2)
|
require.Len(t, issues, 2)
|
||||||
names := []string{issues[0].Name, issues[1].Name}
|
names := []string{issues[0].Name, issues[1].Name}
|
||||||
@ -961,7 +961,7 @@ func testHostsListMunkiIssueID(t *testing.T, ds *Datastore) {
|
|||||||
err = ds.SetOrUpdateMunkiInfo(ctx, hostIDs[0], "1.0.0", []string{strings.Repeat("A", maxMunkiIssueNameLen+1)}, []string{strings.Repeat("☺", maxMunkiIssueNameLen+1)})
|
err = ds.SetOrUpdateMunkiInfo(ctx, hostIDs[0], "1.0.0", []string{strings.Repeat("A", maxMunkiIssueNameLen+1)}, []string{strings.Repeat("☺", maxMunkiIssueNameLen+1)})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
issues, err = ds.GetMunkiIssues(ctx, hostIDs[0])
|
issues, err = ds.GetHostMunkiIssues(ctx, hostIDs[0])
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, issues, 2)
|
require.Len(t, issues, 2)
|
||||||
names = []string{issues[0].Name, issues[1].Name}
|
names = []string{issues[0].Name, issues[1].Name}
|
||||||
@ -3795,26 +3795,40 @@ func assertHostDeviceMapping(t *testing.T, got, want []*fleet.HostDeviceMapping)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testHostMDMAndMunki(t *testing.T, ds *Datastore) {
|
func testHostMDMAndMunki(t *testing.T, ds *Datastore) {
|
||||||
_, err := ds.GetMunkiVersion(context.Background(), 123)
|
_, err := ds.GetHostMunkiVersion(context.Background(), 123)
|
||||||
require.True(t, fleet.IsNotFound(err))
|
require.True(t, fleet.IsNotFound(err))
|
||||||
|
|
||||||
require.NoError(t, ds.SetOrUpdateMunkiInfo(context.Background(), 123, "1.2.3", nil, nil))
|
require.NoError(t, ds.SetOrUpdateMunkiInfo(context.Background(), 123, "1.2.3", nil, nil))
|
||||||
require.NoError(t, ds.SetOrUpdateMunkiInfo(context.Background(), 999, "9.0", nil, nil))
|
require.NoError(t, ds.SetOrUpdateMunkiInfo(context.Background(), 999, "9.0", nil, nil))
|
||||||
require.NoError(t, ds.SetOrUpdateMunkiInfo(context.Background(), 123, "1.3.0", []string{"a", "b"}, []string{"c"}))
|
require.NoError(t, ds.SetOrUpdateMunkiInfo(context.Background(), 123, "1.3.0", []string{"a", "b"}, []string{"c"}))
|
||||||
|
|
||||||
version, err := ds.GetMunkiVersion(context.Background(), 123)
|
version, err := ds.GetHostMunkiVersion(context.Background(), 123)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, "1.3.0", version)
|
require.Equal(t, "1.3.0", version)
|
||||||
|
|
||||||
issues, err := ds.GetMunkiIssues(context.Background(), 123)
|
issues, err := ds.GetHostMunkiIssues(context.Background(), 123)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, issues, 3)
|
require.Len(t, issues, 3)
|
||||||
|
|
||||||
|
var aMunkiIssueID uint
|
||||||
for _, iss := range issues {
|
for _, iss := range issues {
|
||||||
assert.NotZero(t, iss.MunkiIssueID)
|
assert.NotZero(t, iss.MunkiIssueID)
|
||||||
|
if iss.Name == "a" {
|
||||||
|
aMunkiIssueID = iss.MunkiIssueID
|
||||||
|
}
|
||||||
assert.False(t, iss.HostIssueCreatedAt.IsZero())
|
assert.False(t, iss.HostIssueCreatedAt.IsZero())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get a Munki Issue
|
||||||
|
miss, err := ds.GetMunkiIssue(context.Background(), aMunkiIssueID)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "a", miss.Name)
|
||||||
|
|
||||||
|
// get an invalid munki issue
|
||||||
|
_, err = ds.GetMunkiIssue(context.Background(), aMunkiIssueID+1000)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.ErrorIs(t, err, sql.ErrNoRows)
|
||||||
|
|
||||||
// ignore IDs and timestamps in slice comparison
|
// ignore IDs and timestamps in slice comparison
|
||||||
issues[0].MunkiIssueID, issues[0].HostIssueCreatedAt = 0, time.Time{}
|
issues[0].MunkiIssueID, issues[0].HostIssueCreatedAt = 0, time.Time{}
|
||||||
issues[1].MunkiIssueID, issues[1].HostIssueCreatedAt = 0, time.Time{}
|
issues[1].MunkiIssueID, issues[1].HostIssueCreatedAt = 0, time.Time{}
|
||||||
@ -3825,29 +3839,29 @@ func testHostMDMAndMunki(t *testing.T, ds *Datastore) {
|
|||||||
{Name: "c", IssueType: "warning"},
|
{Name: "c", IssueType: "warning"},
|
||||||
}, issues)
|
}, issues)
|
||||||
|
|
||||||
version, err = ds.GetMunkiVersion(context.Background(), 999)
|
version, err = ds.GetHostMunkiVersion(context.Background(), 999)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, "9.0", version)
|
require.Equal(t, "9.0", version)
|
||||||
|
|
||||||
issues, err = ds.GetMunkiIssues(context.Background(), 999)
|
issues, err = ds.GetHostMunkiIssues(context.Background(), 999)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, issues, 0)
|
require.Len(t, issues, 0)
|
||||||
|
|
||||||
// simulate uninstall
|
// simulate uninstall
|
||||||
require.NoError(t, ds.SetOrUpdateMunkiInfo(context.Background(), 123, "", nil, nil))
|
require.NoError(t, ds.SetOrUpdateMunkiInfo(context.Background(), 123, "", nil, nil))
|
||||||
|
|
||||||
_, err = ds.GetMunkiVersion(context.Background(), 123)
|
_, err = ds.GetHostMunkiVersion(context.Background(), 123)
|
||||||
require.True(t, fleet.IsNotFound(err))
|
require.True(t, fleet.IsNotFound(err))
|
||||||
issues, err = ds.GetMunkiIssues(context.Background(), 123)
|
issues, err = ds.GetHostMunkiIssues(context.Background(), 123)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, issues, 0)
|
require.Len(t, issues, 0)
|
||||||
|
|
||||||
_, err = ds.GetMDM(context.Background(), 432)
|
_, err = ds.GetHostMDM(context.Background(), 432)
|
||||||
require.True(t, fleet.IsNotFound(err), err)
|
require.True(t, fleet.IsNotFound(err), err)
|
||||||
|
|
||||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 432, true, "url", false))
|
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 432, true, "url", false))
|
||||||
|
|
||||||
hmdm, err := ds.GetMDM(context.Background(), 432)
|
hmdm, err := ds.GetHostMDM(context.Background(), 432)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, hmdm.Enrolled)
|
assert.True(t, hmdm.Enrolled)
|
||||||
assert.Equal(t, "url", hmdm.ServerURL)
|
assert.Equal(t, "url", hmdm.ServerURL)
|
||||||
@ -3860,7 +3874,7 @@ func testHostMDMAndMunki(t *testing.T, ds *Datastore) {
|
|||||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 455, true, "https://kandji.io", true)) // kandji mdm name
|
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 455, true, "https://kandji.io", true)) // kandji mdm name
|
||||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 432, false, "url3", true))
|
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 432, false, "url3", true))
|
||||||
|
|
||||||
hmdm, err = ds.GetMDM(context.Background(), 432)
|
hmdm, err = ds.GetHostMDM(context.Background(), 432)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.False(t, hmdm.Enrolled)
|
assert.False(t, hmdm.Enrolled)
|
||||||
assert.Equal(t, "url3", hmdm.ServerURL)
|
assert.Equal(t, "url3", hmdm.ServerURL)
|
||||||
@ -3870,7 +3884,7 @@ func testHostMDMAndMunki(t *testing.T, ds *Datastore) {
|
|||||||
assert.NotEqual(t, urlMDMID, *hmdm.MDMID)
|
assert.NotEqual(t, urlMDMID, *hmdm.MDMID)
|
||||||
assert.Equal(t, fleet.UnknownMDMName, hmdm.Name)
|
assert.Equal(t, fleet.UnknownMDMName, hmdm.Name)
|
||||||
|
|
||||||
hmdm, err = ds.GetMDM(context.Background(), 455)
|
hmdm, err = ds.GetHostMDM(context.Background(), 455)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, hmdm.Enrolled)
|
assert.True(t, hmdm.Enrolled)
|
||||||
assert.Equal(t, "https://kandji.io", hmdm.ServerURL)
|
assert.Equal(t, "https://kandji.io", hmdm.ServerURL)
|
||||||
@ -3880,10 +3894,21 @@ func testHostMDMAndMunki(t *testing.T, ds *Datastore) {
|
|||||||
kandjiID1 := *hmdm.MDMID
|
kandjiID1 := *hmdm.MDMID
|
||||||
assert.Equal(t, fleet.WellKnownMDMKandji, hmdm.Name)
|
assert.Equal(t, fleet.WellKnownMDMKandji, hmdm.Name)
|
||||||
|
|
||||||
|
// get mdm solution
|
||||||
|
mdmSol, err := ds.GetMDMSolution(context.Background(), kandjiID1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "https://kandji.io", mdmSol.ServerURL)
|
||||||
|
require.Equal(t, fleet.WellKnownMDMKandji, mdmSol.Name)
|
||||||
|
|
||||||
|
// get unknown mdm solution
|
||||||
|
_, err = ds.GetMDMSolution(context.Background(), kandjiID1+1000)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.ErrorIs(t, err, sql.ErrNoRows)
|
||||||
|
|
||||||
// switch to simplemdm in an update
|
// switch to simplemdm in an update
|
||||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 455, true, "https://simplemdm.com", false)) // now simplemdm name
|
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 455, true, "https://simplemdm.com", false)) // now simplemdm name
|
||||||
|
|
||||||
hmdm, err = ds.GetMDM(context.Background(), 455)
|
hmdm, err = ds.GetHostMDM(context.Background(), 455)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, hmdm.Enrolled)
|
assert.True(t, hmdm.Enrolled)
|
||||||
assert.Equal(t, "https://simplemdm.com", hmdm.ServerURL)
|
assert.Equal(t, "https://simplemdm.com", hmdm.ServerURL)
|
||||||
@ -3895,7 +3920,7 @@ func testHostMDMAndMunki(t *testing.T, ds *Datastore) {
|
|||||||
// switch back to "url"
|
// switch back to "url"
|
||||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 455, false, "url", false))
|
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 455, false, "url", false))
|
||||||
|
|
||||||
hmdm, err = ds.GetMDM(context.Background(), 455)
|
hmdm, err = ds.GetHostMDM(context.Background(), 455)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.False(t, hmdm.Enrolled)
|
assert.False(t, hmdm.Enrolled)
|
||||||
assert.Equal(t, "url", hmdm.ServerURL)
|
assert.Equal(t, "url", hmdm.ServerURL)
|
||||||
@ -3908,7 +3933,7 @@ func testHostMDMAndMunki(t *testing.T, ds *Datastore) {
|
|||||||
// even though this is another Kandji, the URL is different.
|
// even though this is another Kandji, the URL is different.
|
||||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 455, true, "https://kandji.io/2", false))
|
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 455, true, "https://kandji.io/2", false))
|
||||||
|
|
||||||
hmdm, err = ds.GetMDM(context.Background(), 455)
|
hmdm, err = ds.GetHostMDM(context.Background(), 455)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, hmdm.Enrolled)
|
assert.True(t, hmdm.Enrolled)
|
||||||
assert.Equal(t, "https://kandji.io/2", hmdm.ServerURL)
|
assert.Equal(t, "https://kandji.io/2", hmdm.ServerURL)
|
||||||
@ -3961,7 +3986,7 @@ func testMunkiIssuesBatchSize(t *testing.T, ds *Datastore) {
|
|||||||
|
|
||||||
// try those errors/warning with some hosts
|
// try those errors/warning with some hosts
|
||||||
require.NoError(t, ds.SetOrUpdateMunkiInfo(context.Background(), 123, "1.2.3", []string{"a", "b"}, []string{"C"}))
|
require.NoError(t, ds.SetOrUpdateMunkiInfo(context.Background(), 123, "1.2.3", []string{"a", "b"}, []string{"C"}))
|
||||||
issues, err := ds.GetMunkiIssues(ctx, 123)
|
issues, err := ds.GetHostMunkiIssues(ctx, 123)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, issues, 3)
|
require.Len(t, issues, 3)
|
||||||
for _, iss := range issues {
|
for _, iss := range issues {
|
||||||
@ -3969,7 +3994,7 @@ func testMunkiIssuesBatchSize(t *testing.T, ds *Datastore) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
require.NoError(t, ds.SetOrUpdateMunkiInfo(context.Background(), 123, "1.2.3", []string{"c", "z"}, []string{"D", "E", "Z"}))
|
require.NoError(t, ds.SetOrUpdateMunkiInfo(context.Background(), 123, "1.2.3", []string{"c", "z"}, []string{"D", "E", "Z"}))
|
||||||
issues, err = ds.GetMunkiIssues(ctx, 123)
|
issues, err = ds.GetHostMunkiIssues(ctx, 123)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, issues, 5)
|
require.Len(t, issues, 5)
|
||||||
for _, iss := range issues {
|
for _, iss := range issues {
|
||||||
@ -4054,18 +4079,24 @@ func testAggregatedHostMDMAndMunki(t *testing.T, ds *Datastore) {
|
|||||||
issues[2].ID = 0
|
issues[2].ID = 0
|
||||||
assert.ElementsMatch(t, issues, []fleet.AggregatedMunkiIssue{
|
assert.ElementsMatch(t, issues, []fleet.AggregatedMunkiIssue{
|
||||||
{
|
{
|
||||||
Name: "a",
|
MunkiIssue: fleet.MunkiIssue{
|
||||||
IssueType: "error",
|
Name: "a",
|
||||||
|
IssueType: "error",
|
||||||
|
},
|
||||||
HostsCount: 2,
|
HostsCount: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "b",
|
MunkiIssue: fleet.MunkiIssue{
|
||||||
IssueType: "error",
|
Name: "b",
|
||||||
|
IssueType: "error",
|
||||||
|
},
|
||||||
HostsCount: 1,
|
HostsCount: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "c",
|
MunkiIssue: fleet.MunkiIssue{
|
||||||
IssueType: "warning",
|
Name: "c",
|
||||||
|
IssueType: "warning",
|
||||||
|
},
|
||||||
HostsCount: 2,
|
HostsCount: 2,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -4157,13 +4188,17 @@ func testAggregatedHostMDMAndMunki(t *testing.T, ds *Datastore) {
|
|||||||
issues[1].ID = 0
|
issues[1].ID = 0
|
||||||
assert.ElementsMatch(t, issues, []fleet.AggregatedMunkiIssue{
|
assert.ElementsMatch(t, issues, []fleet.AggregatedMunkiIssue{
|
||||||
{
|
{
|
||||||
Name: "d",
|
MunkiIssue: fleet.MunkiIssue{
|
||||||
IssueType: "error",
|
Name: "d",
|
||||||
|
IssueType: "error",
|
||||||
|
},
|
||||||
HostsCount: 2,
|
HostsCount: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "f",
|
MunkiIssue: fleet.MunkiIssue{
|
||||||
IssueType: "warning",
|
Name: "f",
|
||||||
|
IssueType: "warning",
|
||||||
|
},
|
||||||
HostsCount: 1,
|
HostsCount: 1,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -240,9 +240,9 @@ type Datastore interface {
|
|||||||
// ListPoliciesForHost lists the policies that a host will check and whether they are passing
|
// ListPoliciesForHost lists the policies that a host will check and whether they are passing
|
||||||
ListPoliciesForHost(ctx context.Context, host *Host) ([]*HostPolicy, error)
|
ListPoliciesForHost(ctx context.Context, host *Host) ([]*HostPolicy, error)
|
||||||
|
|
||||||
GetMunkiVersion(ctx context.Context, hostID uint) (string, error)
|
GetHostMunkiVersion(ctx context.Context, hostID uint) (string, error)
|
||||||
GetMunkiIssues(ctx context.Context, hostID uint) ([]*HostMunkiIssue, error)
|
GetHostMunkiIssues(ctx context.Context, hostID uint) ([]*HostMunkiIssue, error)
|
||||||
GetMDM(ctx context.Context, hostID uint) (*HostMDM, error)
|
GetHostMDM(ctx context.Context, hostID uint) (*HostMDM, error)
|
||||||
|
|
||||||
AggregatedMunkiVersion(ctx context.Context, teamID *uint) ([]AggregatedMunkiVersion, time.Time, error)
|
AggregatedMunkiVersion(ctx context.Context, teamID *uint) ([]AggregatedMunkiVersion, time.Time, error)
|
||||||
AggregatedMunkiIssues(ctx context.Context, teamID *uint) ([]AggregatedMunkiIssue, time.Time, error)
|
AggregatedMunkiIssues(ctx context.Context, teamID *uint) ([]AggregatedMunkiIssue, time.Time, error)
|
||||||
@ -250,6 +250,9 @@ type Datastore interface {
|
|||||||
AggregatedMDMSolutions(ctx context.Context, teamID *uint) ([]AggregatedMDMSolutions, time.Time, error)
|
AggregatedMDMSolutions(ctx context.Context, teamID *uint) ([]AggregatedMDMSolutions, time.Time, error)
|
||||||
GenerateAggregatedMunkiAndMDM(ctx context.Context) error
|
GenerateAggregatedMunkiAndMDM(ctx context.Context) error
|
||||||
|
|
||||||
|
GetMunkiIssue(ctx context.Context, munkiIssueID uint) (*MunkiIssue, error)
|
||||||
|
GetMDMSolution(ctx context.Context, mdmID uint) (*MDMSolution, error)
|
||||||
|
|
||||||
OSVersions(ctx context.Context, teamID *uint, platform *string, name *string, version *string) (*OSVersions, error)
|
OSVersions(ctx context.Context, teamID *uint, platform *string, name *string, version *string) (*OSVersions, error)
|
||||||
UpdateOSVersions(ctx context.Context) error
|
UpdateOSVersions(ctx context.Context) error
|
||||||
|
|
||||||
|
@ -422,11 +422,17 @@ type AggregatedMunkiVersion struct {
|
|||||||
HostsCount int `json:"hosts_count" db:"hosts_count"`
|
HostsCount int `json:"hosts_count" db:"hosts_count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MunkiIssue represents a single munki issue, as returned by the list hosts
|
||||||
|
// endpoint when a muniki issue ID is provided as filter.
|
||||||
|
type MunkiIssue struct {
|
||||||
|
ID uint `json:"id" db:"id"`
|
||||||
|
Name string `json:"name" db:"name"`
|
||||||
|
IssueType string `json:"type" db:"issue_type"`
|
||||||
|
}
|
||||||
|
|
||||||
type AggregatedMunkiIssue struct {
|
type AggregatedMunkiIssue struct {
|
||||||
ID uint `json:"id" db:"id"`
|
MunkiIssue
|
||||||
Name string `json:"name" db:"name"`
|
HostsCount int `json:"hosts_count" db:"hosts_count"`
|
||||||
IssueType string `json:"type" db:"issue_type"`
|
|
||||||
HostsCount int `json:"hosts_count" db:"hosts_count"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type AggregatedMDMStatus struct {
|
type AggregatedMDMStatus struct {
|
||||||
@ -436,11 +442,17 @@ type AggregatedMDMStatus struct {
|
|||||||
HostsCount int `json:"hosts_count" db:"hosts_count"`
|
HostsCount int `json:"hosts_count" db:"hosts_count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MDMSolution represents a single MDM solution, as returned by the list hosts
|
||||||
|
// endpoint when an MDM Solution ID is provided as filter.
|
||||||
|
type MDMSolution struct {
|
||||||
|
ID uint `json:"id" db:"id"`
|
||||||
|
Name string `json:"name" db:"name"`
|
||||||
|
ServerURL string `json:"server_url" db:"server_url"`
|
||||||
|
}
|
||||||
|
|
||||||
type AggregatedMDMSolutions struct {
|
type AggregatedMDMSolutions struct {
|
||||||
ID uint `json:"id,omitempty" db:"id"`
|
MDMSolution
|
||||||
Name string `json:"name,omitempty" db:"name"`
|
HostsCount int `json:"hosts_count" db:"hosts_count"`
|
||||||
HostsCount int `json:"hosts_count" db:"hosts_count"`
|
|
||||||
ServerURL string `json:"server_url" db:"server_url"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type AggregatedMacadminsData struct {
|
type AggregatedMacadminsData struct {
|
||||||
|
@ -298,8 +298,8 @@ type Service interface {
|
|||||||
|
|
||||||
MacadminsData(ctx context.Context, id uint) (*MacadminsData, error)
|
MacadminsData(ctx context.Context, id uint) (*MacadminsData, error)
|
||||||
AggregatedMacadminsData(ctx context.Context, teamID *uint) (*AggregatedMacadminsData, error)
|
AggregatedMacadminsData(ctx context.Context, teamID *uint) (*AggregatedMacadminsData, error)
|
||||||
AggregatedMDMSolutions(ctx context.Context, teamID *uint, mdmID uint) (*AggregatedMDMSolutions, error)
|
GetMDMSolution(ctx context.Context, mdmID uint) (*MDMSolution, error)
|
||||||
AggregatedMunkiIssue(ctx context.Context, teamID *uint, munkiIssueID uint) (*AggregatedMunkiIssue, error)
|
GetMunkiIssue(ctx context.Context, munkiIssueID uint) (*MunkiIssue, error)
|
||||||
|
|
||||||
// OSVersions returns a list of operating systems and associated host counts, which may be
|
// OSVersions returns a list of operating systems and associated host counts, which may be
|
||||||
// filtered using the following optional criteria: team id, platform, or name and version.
|
// filtered using the following optional criteria: team id, platform, or name and version.
|
||||||
|
@ -189,11 +189,11 @@ type SetOrUpdateDeviceAuthTokenFunc func(ctx context.Context, hostID uint, authT
|
|||||||
|
|
||||||
type ListPoliciesForHostFunc func(ctx context.Context, host *fleet.Host) ([]*fleet.HostPolicy, error)
|
type ListPoliciesForHostFunc func(ctx context.Context, host *fleet.Host) ([]*fleet.HostPolicy, error)
|
||||||
|
|
||||||
type GetMunkiVersionFunc func(ctx context.Context, hostID uint) (string, error)
|
type GetHostMunkiVersionFunc func(ctx context.Context, hostID uint) (string, error)
|
||||||
|
|
||||||
type GetMunkiIssuesFunc func(ctx context.Context, hostID uint) ([]*fleet.HostMunkiIssue, error)
|
type GetHostMunkiIssuesFunc func(ctx context.Context, hostID uint) ([]*fleet.HostMunkiIssue, error)
|
||||||
|
|
||||||
type GetMDMFunc func(ctx context.Context, hostID uint) (*fleet.HostMDM, error)
|
type GetHostMDMFunc func(ctx context.Context, hostID uint) (*fleet.HostMDM, error)
|
||||||
|
|
||||||
type AggregatedMunkiVersionFunc func(ctx context.Context, teamID *uint) ([]fleet.AggregatedMunkiVersion, time.Time, error)
|
type AggregatedMunkiVersionFunc func(ctx context.Context, teamID *uint) ([]fleet.AggregatedMunkiVersion, time.Time, error)
|
||||||
|
|
||||||
@ -205,6 +205,10 @@ type AggregatedMDMSolutionsFunc func(ctx context.Context, teamID *uint) ([]fleet
|
|||||||
|
|
||||||
type GenerateAggregatedMunkiAndMDMFunc func(ctx context.Context) error
|
type GenerateAggregatedMunkiAndMDMFunc func(ctx context.Context) error
|
||||||
|
|
||||||
|
type GetMunkiIssueFunc func(ctx context.Context, munkiIssueID uint) (*fleet.MunkiIssue, error)
|
||||||
|
|
||||||
|
type GetMDMSolutionFunc func(ctx context.Context, mdmID uint) (*fleet.MDMSolution, error)
|
||||||
|
|
||||||
type OSVersionsFunc func(ctx context.Context, teamID *uint, platform *string, name *string, version *string) (*fleet.OSVersions, error)
|
type OSVersionsFunc func(ctx context.Context, teamID *uint, platform *string, name *string, version *string) (*fleet.OSVersions, error)
|
||||||
|
|
||||||
type UpdateOSVersionsFunc func(ctx context.Context) error
|
type UpdateOSVersionsFunc func(ctx context.Context) error
|
||||||
@ -708,14 +712,14 @@ type DataStore struct {
|
|||||||
ListPoliciesForHostFunc ListPoliciesForHostFunc
|
ListPoliciesForHostFunc ListPoliciesForHostFunc
|
||||||
ListPoliciesForHostFuncInvoked bool
|
ListPoliciesForHostFuncInvoked bool
|
||||||
|
|
||||||
GetMunkiVersionFunc GetMunkiVersionFunc
|
GetHostMunkiVersionFunc GetHostMunkiVersionFunc
|
||||||
GetMunkiVersionFuncInvoked bool
|
GetHostMunkiVersionFuncInvoked bool
|
||||||
|
|
||||||
GetMunkiIssuesFunc GetMunkiIssuesFunc
|
GetHostMunkiIssuesFunc GetHostMunkiIssuesFunc
|
||||||
GetMunkiIssuesFuncInvoked bool
|
GetHostMunkiIssuesFuncInvoked bool
|
||||||
|
|
||||||
GetMDMFunc GetMDMFunc
|
GetHostMDMFunc GetHostMDMFunc
|
||||||
GetMDMFuncInvoked bool
|
GetHostMDMFuncInvoked bool
|
||||||
|
|
||||||
AggregatedMunkiVersionFunc AggregatedMunkiVersionFunc
|
AggregatedMunkiVersionFunc AggregatedMunkiVersionFunc
|
||||||
AggregatedMunkiVersionFuncInvoked bool
|
AggregatedMunkiVersionFuncInvoked bool
|
||||||
@ -732,6 +736,12 @@ type DataStore struct {
|
|||||||
GenerateAggregatedMunkiAndMDMFunc GenerateAggregatedMunkiAndMDMFunc
|
GenerateAggregatedMunkiAndMDMFunc GenerateAggregatedMunkiAndMDMFunc
|
||||||
GenerateAggregatedMunkiAndMDMFuncInvoked bool
|
GenerateAggregatedMunkiAndMDMFuncInvoked bool
|
||||||
|
|
||||||
|
GetMunkiIssueFunc GetMunkiIssueFunc
|
||||||
|
GetMunkiIssueFuncInvoked bool
|
||||||
|
|
||||||
|
GetMDMSolutionFunc GetMDMSolutionFunc
|
||||||
|
GetMDMSolutionFuncInvoked bool
|
||||||
|
|
||||||
OSVersionsFunc OSVersionsFunc
|
OSVersionsFunc OSVersionsFunc
|
||||||
OSVersionsFuncInvoked bool
|
OSVersionsFuncInvoked bool
|
||||||
|
|
||||||
@ -1530,19 +1540,19 @@ func (s *DataStore) ListPoliciesForHost(ctx context.Context, host *fleet.Host) (
|
|||||||
return s.ListPoliciesForHostFunc(ctx, host)
|
return s.ListPoliciesForHostFunc(ctx, host)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DataStore) GetMunkiVersion(ctx context.Context, hostID uint) (string, error) {
|
func (s *DataStore) GetHostMunkiVersion(ctx context.Context, hostID uint) (string, error) {
|
||||||
s.GetMunkiVersionFuncInvoked = true
|
s.GetHostMunkiVersionFuncInvoked = true
|
||||||
return s.GetMunkiVersionFunc(ctx, hostID)
|
return s.GetHostMunkiVersionFunc(ctx, hostID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DataStore) GetMunkiIssues(ctx context.Context, hostID uint) ([]*fleet.HostMunkiIssue, error) {
|
func (s *DataStore) GetHostMunkiIssues(ctx context.Context, hostID uint) ([]*fleet.HostMunkiIssue, error) {
|
||||||
s.GetMunkiIssuesFuncInvoked = true
|
s.GetHostMunkiIssuesFuncInvoked = true
|
||||||
return s.GetMunkiIssuesFunc(ctx, hostID)
|
return s.GetHostMunkiIssuesFunc(ctx, hostID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DataStore) GetMDM(ctx context.Context, hostID uint) (*fleet.HostMDM, error) {
|
func (s *DataStore) GetHostMDM(ctx context.Context, hostID uint) (*fleet.HostMDM, error) {
|
||||||
s.GetMDMFuncInvoked = true
|
s.GetHostMDMFuncInvoked = true
|
||||||
return s.GetMDMFunc(ctx, hostID)
|
return s.GetHostMDMFunc(ctx, hostID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DataStore) AggregatedMunkiVersion(ctx context.Context, teamID *uint) ([]fleet.AggregatedMunkiVersion, time.Time, error) {
|
func (s *DataStore) AggregatedMunkiVersion(ctx context.Context, teamID *uint) ([]fleet.AggregatedMunkiVersion, time.Time, error) {
|
||||||
@ -1570,6 +1580,16 @@ func (s *DataStore) GenerateAggregatedMunkiAndMDM(ctx context.Context) error {
|
|||||||
return s.GenerateAggregatedMunkiAndMDMFunc(ctx)
|
return s.GenerateAggregatedMunkiAndMDMFunc(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *DataStore) GetMunkiIssue(ctx context.Context, munkiIssueID uint) (*fleet.MunkiIssue, error) {
|
||||||
|
s.GetMunkiIssueFuncInvoked = true
|
||||||
|
return s.GetMunkiIssueFunc(ctx, munkiIssueID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DataStore) GetMDMSolution(ctx context.Context, mdmID uint) (*fleet.MDMSolution, error) {
|
||||||
|
s.GetMDMSolutionFuncInvoked = true
|
||||||
|
return s.GetMDMSolutionFunc(ctx, mdmID)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *DataStore) OSVersions(ctx context.Context, teamID *uint, platform *string, name *string, version *string) (*fleet.OSVersions, error) {
|
func (s *DataStore) OSVersions(ctx context.Context, teamID *uint, platform *string, name *string, version *string) (*fleet.OSVersions, error) {
|
||||||
s.OSVersionsFuncInvoked = true
|
s.OSVersionsFuncInvoked = true
|
||||||
return s.OSVersionsFunc(ctx, teamID, platform, name, version)
|
return s.OSVersionsFunc(ctx, teamID, platform, name, version)
|
||||||
|
@ -72,12 +72,12 @@ type listHostsResponse struct {
|
|||||||
// MDMSolution is populated with the MDM solution corresponding to the mdm_id
|
// MDMSolution is populated with the MDM solution corresponding to the mdm_id
|
||||||
// filter if one is provided with the request (and it exists in the
|
// filter if one is provided with the request (and it exists in the
|
||||||
// database). It is nil otherwise and absent of the JSON response payload.
|
// database). It is nil otherwise and absent of the JSON response payload.
|
||||||
MDMSolution *fleet.AggregatedMDMSolutions `json:"mobile_device_management_solution,omitempty"`
|
MDMSolution *fleet.MDMSolution `json:"mobile_device_management_solution,omitempty"`
|
||||||
// MunkiIssue is populated with the munki issue corresponding to the
|
// MunkiIssue is populated with the munki issue corresponding to the
|
||||||
// munki_issue_id filter if one is provided with the request (and it exists
|
// munki_issue_id filter if one is provided with the request (and it exists
|
||||||
// in the database). It is nil otherwise and absent of the JSON response
|
// in the database). It is nil otherwise and absent of the JSON response
|
||||||
// payload.
|
// payload.
|
||||||
MunkiIssue *fleet.AggregatedMunkiIssue `json:"munki_issue,omitempty"`
|
MunkiIssue *fleet.MunkiIssue `json:"munki_issue,omitempty"`
|
||||||
|
|
||||||
Err error `json:"error,omitempty"`
|
Err error `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
@ -96,20 +96,20 @@ func listHostsEndpoint(ctx context.Context, request interface{}, svc fleet.Servi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var mdmSolution *fleet.AggregatedMDMSolutions
|
var mdmSolution *fleet.MDMSolution
|
||||||
if req.Opts.MDMIDFilter != nil {
|
if req.Opts.MDMIDFilter != nil {
|
||||||
var err error
|
var err error
|
||||||
mdmSolution, err = svc.AggregatedMDMSolutions(ctx, req.Opts.TeamFilter, *req.Opts.MDMIDFilter)
|
mdmSolution, err = svc.GetMDMSolution(ctx, *req.Opts.MDMIDFilter)
|
||||||
if err != nil {
|
if err != nil && !fleet.IsNotFound(err) { // ignore not found, just return nil for the MDM solution in that case
|
||||||
return listHostsResponse{Err: err}, nil
|
return listHostsResponse{Err: err}, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var munkiIssue *fleet.AggregatedMunkiIssue
|
var munkiIssue *fleet.MunkiIssue
|
||||||
if req.Opts.MunkiIssueIDFilter != nil {
|
if req.Opts.MunkiIssueIDFilter != nil {
|
||||||
var err error
|
var err error
|
||||||
munkiIssue, err = svc.AggregatedMunkiIssue(ctx, req.Opts.TeamFilter, *req.Opts.MunkiIssueIDFilter)
|
munkiIssue, err = svc.GetMunkiIssue(ctx, *req.Opts.MunkiIssueIDFilter)
|
||||||
if err != nil {
|
if err != nil && !fleet.IsNotFound(err) { // ignore not found, just return nil for the munki issue in that case
|
||||||
return listHostsResponse{Err: err}, nil
|
return listHostsResponse{Err: err}, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,67 +136,20 @@ func listHostsEndpoint(ctx context.Context, request interface{}, svc fleet.Servi
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (svc *Service) AggregatedMDMSolutions(ctx context.Context, teamID *uint, mdmID uint) (*fleet.AggregatedMDMSolutions, error) {
|
func (svc *Service) GetMDMSolution(ctx context.Context, mdmID uint) (*fleet.MDMSolution, error) {
|
||||||
if err := svc.authz.Authorize(ctx, &fleet.Host{TeamID: teamID}, fleet.ActionList); err != nil {
|
// require list hosts permission to view this information
|
||||||
|
if err := svc.authz.Authorize(ctx, &fleet.Host{}, fleet.ActionList); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return svc.ds.GetMDMSolution(ctx, mdmID)
|
||||||
if teamID != nil {
|
|
||||||
_, err := svc.ds.Team(ctx, *teamID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// it is expected that there will be relatively few MDM solutions. This
|
|
||||||
// returns the slice of all aggregated stats (one entry per mdm_id), and we
|
|
||||||
// then iterate to return only the one that was requested (the slice is
|
|
||||||
// stored as-is in a JSON field in the database).
|
|
||||||
sols, _, err := svc.ds.AggregatedMDMSolutions(ctx, teamID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, sol := range sols {
|
|
||||||
// don't take the address of the loop variable (although it could be ok
|
|
||||||
// here, but just bad practice)
|
|
||||||
sol := sol
|
|
||||||
if sol.ID == mdmID {
|
|
||||||
return &sol, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (svc *Service) AggregatedMunkiIssue(ctx context.Context, teamID *uint, munkiIssueID uint) (*fleet.AggregatedMunkiIssue, error) {
|
func (svc *Service) GetMunkiIssue(ctx context.Context, munkiIssueID uint) (*fleet.MunkiIssue, error) {
|
||||||
if err := svc.authz.Authorize(ctx, &fleet.Host{TeamID: teamID}, fleet.ActionList); err != nil {
|
// require list hosts permission to view this information
|
||||||
|
if err := svc.authz.Authorize(ctx, &fleet.Host{}, fleet.ActionList); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return svc.ds.GetMunkiIssue(ctx, munkiIssueID)
|
||||||
if teamID != nil {
|
|
||||||
_, err := svc.ds.Team(ctx, *teamID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This returns the slice of all aggregated stats (one entry per
|
|
||||||
// munki_issue_id), and we then iterate to return only the one that was
|
|
||||||
// requested (the slice is stored as-is in a JSON field in the database).
|
|
||||||
issues, _, err := svc.ds.AggregatedMunkiIssues(ctx, teamID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, iss := range issues {
|
|
||||||
// don't take the address of the loop variable (although it could be ok
|
|
||||||
// here, but just bad practice)
|
|
||||||
iss := iss
|
|
||||||
if iss.ID == munkiIssueID {
|
|
||||||
return &iss, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (svc *Service) ListHosts(ctx context.Context, opt fleet.HostListOptions) ([]*fleet.Host, error) {
|
func (svc *Service) ListHosts(ctx context.Context, opt fleet.HostListOptions) ([]*fleet.Host, error) {
|
||||||
@ -982,7 +935,7 @@ func (svc *Service) MacadminsData(ctx context.Context, id uint) (*fleet.Macadmin
|
|||||||
}
|
}
|
||||||
|
|
||||||
var munkiInfo *fleet.HostMunkiInfo
|
var munkiInfo *fleet.HostMunkiInfo
|
||||||
switch version, err := svc.ds.GetMunkiVersion(ctx, id); {
|
switch version, err := svc.ds.GetHostMunkiVersion(ctx, id); {
|
||||||
case err != nil && !fleet.IsNotFound(err):
|
case err != nil && !fleet.IsNotFound(err):
|
||||||
return nil, err
|
return nil, err
|
||||||
case err == nil:
|
case err == nil:
|
||||||
@ -990,7 +943,7 @@ func (svc *Service) MacadminsData(ctx context.Context, id uint) (*fleet.Macadmin
|
|||||||
}
|
}
|
||||||
|
|
||||||
var mdm *fleet.HostMDM
|
var mdm *fleet.HostMDM
|
||||||
switch hmdm, err := svc.ds.GetMDM(ctx, id); {
|
switch hmdm, err := svc.ds.GetHostMDM(ctx, id); {
|
||||||
case err != nil && !fleet.IsNotFound(err):
|
case err != nil && !fleet.IsNotFound(err):
|
||||||
return nil, err
|
return nil, err
|
||||||
case err == nil:
|
case err == nil:
|
||||||
@ -998,7 +951,7 @@ func (svc *Service) MacadminsData(ctx context.Context, id uint) (*fleet.Macadmin
|
|||||||
}
|
}
|
||||||
|
|
||||||
var munkiIssues []*fleet.HostMunkiIssue
|
var munkiIssues []*fleet.HostMunkiIssue
|
||||||
switch issues, err := svc.ds.GetMunkiIssues(ctx, id); {
|
switch issues, err := svc.ds.GetHostMunkiIssues(ctx, id); {
|
||||||
case err != nil:
|
case err != nil:
|
||||||
return nil, err
|
return nil, err
|
||||||
case err == nil:
|
case err == nil:
|
||||||
|
@ -1120,7 +1120,6 @@ func (s *integrationTestSuite) TestListHosts() {
|
|||||||
assert.Nil(t, resp.MunkiIssue)
|
assert.Nil(t, resp.MunkiIssue)
|
||||||
require.NotNil(t, resp.MDMSolution)
|
require.NotNil(t, resp.MDMSolution)
|
||||||
assert.Equal(t, mdmID, resp.MDMSolution.ID)
|
assert.Equal(t, mdmID, resp.MDMSolution.ID)
|
||||||
assert.Equal(t, 1, resp.MDMSolution.HostsCount)
|
|
||||||
assert.Equal(t, fleet.WellKnownMDMSimpleMDM, resp.MDMSolution.Name)
|
assert.Equal(t, fleet.WellKnownMDMSimpleMDM, resp.MDMSolution.Name)
|
||||||
assert.Equal(t, "https://simplemdm.com", resp.MDMSolution.ServerURL)
|
assert.Equal(t, "https://simplemdm.com", resp.MDMSolution.ServerURL)
|
||||||
|
|
||||||
@ -1151,11 +1150,10 @@ func (s *integrationTestSuite) TestListHosts() {
|
|||||||
assert.Nil(t, resp.Software)
|
assert.Nil(t, resp.Software)
|
||||||
assert.Nil(t, resp.MDMSolution)
|
assert.Nil(t, resp.MDMSolution)
|
||||||
require.NotNil(t, resp.MunkiIssue)
|
require.NotNil(t, resp.MunkiIssue)
|
||||||
assert.Equal(t, fleet.AggregatedMunkiIssue{
|
assert.Equal(t, fleet.MunkiIssue{
|
||||||
ID: errMunkiID,
|
ID: errMunkiID,
|
||||||
Name: "err",
|
Name: "err",
|
||||||
IssueType: "error",
|
IssueType: "error",
|
||||||
HostsCount: 1,
|
|
||||||
}, *resp.MunkiIssue)
|
}, *resp.MunkiIssue)
|
||||||
|
|
||||||
// filters can be combined, no problem
|
// filters can be combined, no problem
|
||||||
@ -2683,13 +2681,17 @@ func (s *integrationTestSuite) TestGetMacadminsData() {
|
|||||||
agg.Macadmins.MunkiIssues[1].ID = 0
|
agg.Macadmins.MunkiIssues[1].ID = 0
|
||||||
assert.ElementsMatch(t, agg.Macadmins.MunkiIssues, []fleet.AggregatedMunkiIssue{
|
assert.ElementsMatch(t, agg.Macadmins.MunkiIssues, []fleet.AggregatedMunkiIssue{
|
||||||
{
|
{
|
||||||
Name: "error1",
|
MunkiIssue: fleet.MunkiIssue{
|
||||||
IssueType: "error",
|
Name: "error1",
|
||||||
|
IssueType: "error",
|
||||||
|
},
|
||||||
HostsCount: 1,
|
HostsCount: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "warning1",
|
MunkiIssue: fleet.MunkiIssue{
|
||||||
IssueType: "warning",
|
Name: "warning1",
|
||||||
|
IssueType: "warning",
|
||||||
|
},
|
||||||
HostsCount: 1,
|
HostsCount: 1,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user