@@ -685,6 +685,20 @@ func (s *integrationMDMTestSuite) TestVPPAppInstallVerification() {
|
||||
commandResultsResp.Results[0].ResultsMetadata["vpp_verify_timeout_seconds"],
|
||||
)
|
||||
|
||||
// Verify the device/self-service endpoint also returns VPP metadata (#43957)
|
||||
var deviceCmdResultsResp getMDMCommandResultsResponse
|
||||
res := s.DoRawNoAuth("GET", fmt.Sprintf("/api/latest/fleet/device/%s/software/commands/%s/results", "foobar", installCmdUUID), nil, http.StatusOK)
|
||||
err := json.NewDecoder(res.Body).Decode(&deviceCmdResultsResp)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, deviceCmdResultsResp.Results, 1)
|
||||
require.Equal(t, false, deviceCmdResultsResp.Results[0].ResultsMetadata["software_installed"])
|
||||
require.InEpsilon(
|
||||
t,
|
||||
float64(int(fleet.DefaultVPPInstallVerifyTimeout.Seconds())),
|
||||
deviceCmdResultsResp.Results[0].ResultsMetadata["vpp_verify_timeout_seconds"],
|
||||
0.01,
|
||||
)
|
||||
|
||||
// ========================================================
|
||||
// Mark installs as failed when MDM turned off on host
|
||||
// ========================================================
|
||||
|
||||
@@ -929,6 +929,25 @@ func (svc *Service) getDeviceSoftwareMDMCommandResults(ctx context.Context, comm
|
||||
res.Hostname = host.Hostname
|
||||
}
|
||||
|
||||
// Enrich VPP command results with install status and verify timeout metadata,
|
||||
// matching what the admin path does in GetMDMCommandResults.
|
||||
if len(results) > 0 {
|
||||
installed, err := svc.ds.GetVPPAppInstallStatusByCommandUUID(ctx, commandUUID)
|
||||
if err != nil {
|
||||
svc.logger.DebugContext(ctx, "failed to check if VPP app is installed", "err", err, "command_uuid", commandUUID)
|
||||
} else {
|
||||
for _, res := range results {
|
||||
if res.RequestType == "InstallApplication" {
|
||||
if res.ResultsMetadata == nil {
|
||||
res.ResultsMetadata = make(map[string]any)
|
||||
}
|
||||
res.ResultsMetadata["software_installed"] = installed
|
||||
res.ResultsMetadata["vpp_verify_timeout_seconds"] = int(svc.config.Server.VPPVerifyTimeout.Seconds())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -2859,3 +2859,73 @@ func TestNewMDMProfilePremiumOnlyAndroid(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDeviceSoftwareMDMCommandResultsVPPMetadata(t *testing.T) {
|
||||
ds := new(mock.Store)
|
||||
cfg := config.TestConfig()
|
||||
cfg.Server.VPPVerifyTimeout = 30 * time.Second // non-default to distinguish from frontend fallback of 600s
|
||||
svc, ctx := newTestServiceWithConfig(t, ds, cfg, nil, nil, &TestServerOpts{SkipCreateTestUsers: true})
|
||||
|
||||
testHost := &fleet.Host{ID: 1, UUID: "host-uuid-1", Hostname: "test-host"}
|
||||
const testCommandUUID = "cmd-uuid-1"
|
||||
|
||||
t.Run("populates metadata with timeout and install status", func(t *testing.T) {
|
||||
ds.GetVPPCommandResultsFunc = func(ctx context.Context, commandUUID string, hostUUID string) ([]*fleet.MDMCommandResult, error) {
|
||||
return []*fleet.MDMCommandResult{
|
||||
{HostUUID: hostUUID, CommandUUID: commandUUID, RequestType: "InstallApplication"},
|
||||
}, nil
|
||||
}
|
||||
ds.GetVPPAppInstallStatusByCommandUUIDFunc = func(ctx context.Context, commandUUID string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
deviceCtx := test.HostContext(ctx, testHost)
|
||||
results, err := svc.GetMDMCommandResults(deviceCtx, testCommandUUID, "")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, results, 1)
|
||||
require.NotNil(t, results[0].ResultsMetadata)
|
||||
require.Equal(t, true, results[0].ResultsMetadata["software_installed"])
|
||||
require.Equal(t, 30, results[0].ResultsMetadata["vpp_verify_timeout_seconds"])
|
||||
require.Equal(t, testHost.Hostname, results[0].Hostname)
|
||||
require.True(t, ds.GetVPPCommandResultsFuncInvoked)
|
||||
require.True(t, ds.GetVPPAppInstallStatusByCommandUUIDFuncInvoked)
|
||||
})
|
||||
|
||||
t.Run("returns results without metadata on install status error", func(t *testing.T) {
|
||||
ds.GetVPPCommandResultsFuncInvoked = false
|
||||
ds.GetVPPAppInstallStatusByCommandUUIDFuncInvoked = false
|
||||
|
||||
ds.GetVPPCommandResultsFunc = func(ctx context.Context, commandUUID string, hostUUID string) ([]*fleet.MDMCommandResult, error) {
|
||||
return []*fleet.MDMCommandResult{
|
||||
{HostUUID: hostUUID, CommandUUID: commandUUID, RequestType: "InstallApplication"},
|
||||
}, nil
|
||||
}
|
||||
ds.GetVPPAppInstallStatusByCommandUUIDFunc = func(ctx context.Context, commandUUID string) (bool, error) {
|
||||
return false, errors.New("db error")
|
||||
}
|
||||
|
||||
deviceCtx := test.HostContext(ctx, testHost)
|
||||
results, err := svc.GetMDMCommandResults(deviceCtx, testCommandUUID, "")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, results, 1)
|
||||
require.Nil(t, results[0].ResultsMetadata)
|
||||
require.True(t, ds.GetVPPCommandResultsFuncInvoked)
|
||||
require.True(t, ds.GetVPPAppInstallStatusByCommandUUIDFuncInvoked)
|
||||
})
|
||||
|
||||
t.Run("skips install status check on empty results", func(t *testing.T) {
|
||||
ds.GetVPPCommandResultsFuncInvoked = false
|
||||
ds.GetVPPAppInstallStatusByCommandUUIDFuncInvoked = false
|
||||
|
||||
ds.GetVPPCommandResultsFunc = func(ctx context.Context, commandUUID string, hostUUID string) ([]*fleet.MDMCommandResult, error) {
|
||||
return []*fleet.MDMCommandResult{}, nil
|
||||
}
|
||||
|
||||
deviceCtx := test.HostContext(ctx, testHost)
|
||||
results, err := svc.GetMDMCommandResults(deviceCtx, testCommandUUID, "")
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, results)
|
||||
require.True(t, ds.GetVPPCommandResultsFuncInvoked)
|
||||
require.False(t, ds.GetVPPAppInstallStatusByCommandUUIDFuncInvoked)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user