fix app store apps display names in gitops (#36913)

<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #36700 

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)

## Testing

- [x] Added/updated automated tests
- [x] Where appropriate, [automated tests simulate multiple hosts and
test for host
isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing)
(updates to one hosts's records do not affect another)
- [x] QA'd all new/changed functionality manually

For unreleased bug fixes in a release candidate, one of:

- [x] Confirmed that the fix is not expected to adversely impact load
test results

## New Fleet configuration settings

- [x] Verified that the setting is exported via `fleetctl
generate-gitops`
- [x] Verified that the setting is cleared on the server if it is not
supplied in a YAML file (or that it is documented as being optional)
This commit is contained in:
Jahziel Villasana-Espinoza
2025-12-09 10:42:04 -05:00
committed by GitHub
parent 2a0a3fed64
commit 4ce4828ba0
9 changed files with 110 additions and 31 deletions
+7 -7
View File
@@ -350,7 +350,7 @@ func TestGitOpsBasicGlobalPremium(t *testing.T) {
) (teamPolicies []*fleet.Policy, inheritedPolicies []*fleet.Policy, err error) {
return nil, nil, nil
}
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam) error {
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam, _ map[string]uint) error {
return nil
}
@@ -575,7 +575,7 @@ func TestGitOpsBasicTeam(t *testing.T) {
const secret = "TestSecret"
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam) error {
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam, _ map[string]uint) error {
return nil
}
ds.BatchInsertVPPAppsFunc = func(ctx context.Context, apps []*fleet.VPPApp) error {
@@ -1325,7 +1325,7 @@ func TestGitOpsFullTeam(t *testing.T) {
ds.GetSoftwareInstallersFunc = func(ctx context.Context, tmID uint) ([]fleet.SoftwarePackageResponse, error) {
return nil, nil
}
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam) error {
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam, _ map[string]uint) error {
return nil
}
ds.BatchInsertVPPAppsFunc = func(ctx context.Context, apps []*fleet.VPPApp) error {
@@ -1529,7 +1529,7 @@ func TestGitOpsBasicGlobalAndTeam(t *testing.T) {
return nil
}
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam) error {
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam, _ map[string]uint) error {
return nil
}
ds.BatchInsertVPPAppsFunc = func(ctx context.Context, apps []*fleet.VPPApp) error {
@@ -1922,7 +1922,7 @@ func TestGitOpsBasicGlobalAndNoTeam(t *testing.T) {
savedAppConfig = config
return nil
}
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam) error {
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam, _ map[string]uint) error {
return nil
}
ds.BatchInsertVPPAppsFunc = func(ctx context.Context, apps []*fleet.VPPApp) error {
@@ -2466,7 +2466,7 @@ func TestGitOpsFullGlobalAndTeam(t *testing.T) {
}, nil
}
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam) error {
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam, _ map[string]uint) error {
return nil
}
ds.BatchInsertVPPAppsFunc = func(ctx context.Context, apps []*fleet.VPPApp) error {
@@ -2676,7 +2676,7 @@ func TestGitOpsCustomSettings(t *testing.T) {
}
return ret, nil
}
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam) error {
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam, _ map[string]uint) error {
return nil
}
ds.BatchInsertVPPAppsFunc = func(ctx context.Context, apps []*fleet.VPPApp) error {
@@ -270,7 +270,7 @@ func SetupFullGitOpsPremiumServer(t *testing.T) (*mock.Store, **fleet.AppConfig,
savedAppConfig = &appConfigCopy
return nil
}
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam) error {
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam, _ map[string]uint) error {
return nil
}
ds.BatchInsertVPPAppsFunc = func(ctx context.Context, apps []*fleet.VPPApp) error {
@@ -86,7 +86,7 @@ func TestGitOpsTeamSoftwareInstallers(t *testing.T) {
token, err := test.CreateVPPTokenEncoded(tokExpire, "fleet", "ca")
require.NoError(t, err)
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam) error {
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam, _ map[string]uint) error {
return nil
}
ds.GetVPPAppsFunc = func(ctx context.Context, teamID *uint) ([]fleet.VPPAppResponse, error) {
@@ -248,7 +248,7 @@ func TestGitOpsNoTeamVPPPolicies(t *testing.T) {
token, err := test.CreateVPPTokenEncoded(tokExpire, "fleet", "ca")
require.NoError(t, err)
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam) error {
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam, _ map[string]uint) error {
return nil
}
ds.BatchInsertVPPAppsFunc = func(ctx context.Context, apps []*fleet.VPPApp) error {
@@ -368,7 +368,7 @@ func TestGitOpsNoTeamSoftwareInstallers(t *testing.T) {
token, err := test.CreateVPPTokenEncoded(tokExpire, "fleet", "ca")
require.NoError(t, err)
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam) error {
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam, _ map[string]uint) error {
return nil
}
ds.BatchInsertVPPAppsFunc = func(ctx context.Context, apps []*fleet.VPPApp) error {
@@ -501,7 +501,7 @@ func TestGitOpsTeamVPPApps(t *testing.T) {
token, err := test.CreateVPPTokenEncoded(c.tokenExpiration, "fleet", "ca")
require.NoError(t, err)
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam) error {
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam, _ map[string]uint) error {
return nil
}
ds.BatchInsertVPPAppsFunc = func(ctx context.Context, apps []*fleet.VPPApp) error {
+15 -1
View File
@@ -90,6 +90,7 @@ func (svc *Service) BatchAssociateVPPApps(ctx context.Context, teamName string,
LabelsExcludeAny: payload.LabelsExcludeAny,
LabelsIncludeAny: payload.LabelsIncludeAny,
Categories: payload.Categories,
DisplayName: payload.DisplayName,
}, {
AppStoreID: payload.AppStoreID,
SelfService: payload.SelfService,
@@ -98,6 +99,7 @@ func (svc *Service) BatchAssociateVPPApps(ctx context.Context, teamName string,
LabelsExcludeAny: payload.LabelsExcludeAny,
LabelsIncludeAny: payload.LabelsIncludeAny,
Categories: payload.Categories,
DisplayName: payload.DisplayName,
}, {
AppStoreID: payload.AppStoreID,
SelfService: payload.SelfService,
@@ -106,6 +108,7 @@ func (svc *Service) BatchAssociateVPPApps(ctx context.Context, teamName string,
LabelsExcludeAny: payload.LabelsExcludeAny,
LabelsIncludeAny: payload.LabelsIncludeAny,
Categories: payload.Categories,
DisplayName: payload.DisplayName,
}}...)
} else {
payloadsWithPlatform = append(payloadsWithPlatform, fleet.VPPBatchPayloadWithPlatform{
@@ -116,6 +119,7 @@ func (svc *Service) BatchAssociateVPPApps(ctx context.Context, teamName string,
LabelsExcludeAny: payload.LabelsExcludeAny,
LabelsIncludeAny: payload.LabelsIncludeAny,
Categories: payload.Categories,
DisplayName: payload.DisplayName,
})
}
@@ -169,6 +173,7 @@ func (svc *Service) BatchAssociateVPPApps(ctx context.Context, teamName string,
InstallDuringSetup: payload.InstallDuringSetup,
ValidatedLabels: validatedLabels,
CategoryIDs: catIDs,
DisplayName: ptr.String(payload.DisplayName),
}
switch payload.Platform {
case fleet.AndroidPlatform:
@@ -268,6 +273,12 @@ func (svc *Service) BatchAssociateVPPApps(ctx context.Context, teamName string,
return nil, ctxerr.Wrap(ctx, err, "inserting vpp app metadata")
}
}
appStoreIDToTitleID := make(map[string]uint, len(appStoreApps))
for _, a := range appStoreApps {
appStoreIDToTitleID[a.AdamID] = a.TitleID
}
// Filter out the apps with invalid platforms
if len(appStoreApps) != len(allPlatformApps) {
allPlatformApps = make([]fleet.VPPAppTeam, 0, len(appStoreApps))
@@ -276,7 +287,7 @@ func (svc *Service) BatchAssociateVPPApps(ctx context.Context, teamName string,
}
}
if err := svc.ds.SetTeamVPPApps(ctx, teamID, allPlatformApps); err != nil {
if err := svc.ds.SetTeamVPPApps(ctx, teamID, allPlatformApps, appStoreIDToTitleID); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, fleet.NewUserMessageError(ctxerr.Wrap(ctx, err, "no vpp token to set team vpp assets"), http.StatusUnprocessableEntity)
}
@@ -671,6 +682,7 @@ func getVPPAppsMetadata(ctx context.Context, ids []fleet.VPPAppTeam) ([]*fleet.V
AppTeamID: id.AppTeamID,
Categories: id.Categories,
CategoryIDs: id.CategoryIDs,
DisplayName: id.DisplayName,
}
} else {
adamIDMap[id.AdamID][id.Platform] = fleet.VPPAppTeam{
@@ -680,6 +692,7 @@ func getVPPAppsMetadata(ctx context.Context, ids []fleet.VPPAppTeam) ([]*fleet.V
AppTeamID: id.AppTeamID,
Categories: id.Categories,
CategoryIDs: id.CategoryIDs,
DisplayName: id.DisplayName,
}
}
}
@@ -709,6 +722,7 @@ func getVPPAppsMetadata(ctx context.Context, ids []fleet.VPPAppTeam) ([]*fleet.V
AppTeamID: props.AppTeamID,
Categories: props.Categories,
CategoryIDs: props.CategoryIDs,
DisplayName: props.DisplayName,
},
BundleIdentifier: metadata.BundleID,
IconURL: metadata.ArtworkURL,
+13 -2
View File
@@ -389,7 +389,7 @@ func (ds *Datastore) getVPPAppTeamCategoryIDs(ctx context.Context, vppAppTeamID
return ids, nil
}
func (ds *Datastore) SetTeamVPPApps(ctx context.Context, teamID *uint, incomingApps []fleet.VPPAppTeam) error {
func (ds *Datastore) SetTeamVPPApps(ctx context.Context, teamID *uint, incomingApps []fleet.VPPAppTeam, appStoreAppIDsToTitleIDs map[string]uint) error {
existingApps, err := ds.GetAssignedVPPApps(ctx, teamID)
if err != nil {
return ctxerr.Wrap(ctx, err, "SetTeamVPPApps getting list of existing apps")
@@ -433,7 +433,7 @@ func (ds *Datastore) SetTeamVPPApps(ctx context.Context, teamID *uint, incomingA
// upsert it if it does not exist or labels or SelfService or InstallDuringSetup flags are changed
existingApp, isExistingApp := existingApps[incomingApp.VPPAppID]
incomingApp.AppTeamID = existingApp.AppTeamID
var labelsChanged, categoriesChanged bool
var labelsChanged, categoriesChanged, displayNameChanged bool
if isExistingApp {
existingLabels, err := ds.getExistingLabels(ctx, incomingApp.AppTeamID)
if err != nil {
@@ -449,6 +449,10 @@ func (ds *Datastore) SetTeamVPPApps(ctx context.Context, teamID *uint, incomingA
categoriesChanged = !slices.Equal(existingCatIDs, incomingApp.CategoryIDs)
existingDisplayName := ptr.ValOrZero(existingApp.DisplayName)
incomingDisplayName := ptr.ValOrZero(incomingApp.DisplayName)
displayNameChanged = existingDisplayName != incomingDisplayName
}
// Get the hosts that are NOT in label scope currently (before the update happens)
@@ -465,6 +469,7 @@ func (ds *Datastore) SetTeamVPPApps(ctx context.Context, teamID *uint, incomingA
existingApp.SelfService != incomingApp.SelfService ||
labelsChanged ||
categoriesChanged ||
displayNameChanged ||
incomingApp.InstallDuringSetup != nil &&
existingApp.InstallDuringSetup != nil &&
*incomingApp.InstallDuringSetup != *existingApp.InstallDuringSetup {
@@ -530,6 +535,12 @@ func (ds *Datastore) SetTeamVPPApps(ctx context.Context, teamID *uint, incomingA
}
}
if toAdd.DisplayName != nil {
if err := updateSoftwareTitleDisplayName(ctx, tx, teamID, appStoreAppIDsToTitleIDs[toAdd.AdamID], *toAdd.DisplayName); err != nil {
return ctxerr.Wrap(ctx, err, "setting software title display name for vpp app")
}
}
if hostsNotInScope, ok := appsWithChangedLabels[toAdd.AppTeamID]; ok {
hostsInScope, err := ds.GetIncludedHostIDMapForVPPAppTx(ctx, tx, toAdd.AppTeamID)
if err != nil {
+10 -10
View File
@@ -777,7 +777,7 @@ func testSetTeamVPPApps(t *testing.T, ds *Datastore) {
err = ds.SetTeamVPPApps(ctx, &team.ID, []fleet.VPPAppTeam{
{VPPAppID: app1.VPPAppID, InstallDuringSetup: ptr.Bool(true)},
{VPPAppID: app2.VPPAppID, SelfService: true},
})
}, map[string]uint{})
require.NoError(t, err)
// create policies using two of the apps
@@ -818,7 +818,7 @@ func testSetTeamVPPApps(t *testing.T, ds *Datastore) {
{VPPAppID: app1.VPPAppID, InstallDuringSetup: ptr.Bool(true)},
{VPPAppID: app2.VPPAppID},
{VPPAppID: app3.VPPAppID},
})
}, nil)
require.NoError(t, err)
policy1, err = ds.Policy(ctx, policy1.ID)
@@ -839,7 +839,7 @@ func testSetTeamVPPApps(t *testing.T, ds *Datastore) {
{VPPAppID: app1.VPPAppID, InstallDuringSetup: ptr.Bool(true)},
{VPPAppID: app2.VPPAppID, SelfService: true},
{VPPAppID: app4.VPPAppID},
})
}, nil)
require.NoError(t, err)
policy1, err = ds.Policy(ctx, policy1.ID)
@@ -859,7 +859,7 @@ func testSetTeamVPPApps(t *testing.T, ds *Datastore) {
err = ds.SetTeamVPPApps(ctx, &team.ID, []fleet.VPPAppTeam{
{VPPAppID: app2.VPPAppID, SelfService: true},
{VPPAppID: app4.VPPAppID},
})
}, nil)
require.Error(t, err)
require.ErrorIs(t, err, errDeleteInstallerInstalledDuringSetup)
@@ -868,14 +868,14 @@ func testSetTeamVPPApps(t *testing.T, ds *Datastore) {
{VPPAppID: app1.VPPAppID, InstallDuringSetup: ptr.Bool(false)},
{VPPAppID: app2.VPPAppID, SelfService: true},
{VPPAppID: app4.VPPAppID},
})
}, nil)
require.NoError(t, err)
// Remove app1 now works
err = ds.SetTeamVPPApps(ctx, &team.ID, []fleet.VPPAppTeam{
{VPPAppID: app2.VPPAppID, SelfService: true},
{VPPAppID: app4.VPPAppID},
})
}, nil)
require.NoError(t, err)
policy1, err = ds.Policy(ctx, policy1.ID)
@@ -887,7 +887,7 @@ func testSetTeamVPPApps(t *testing.T, ds *Datastore) {
require.Equal(t, app2Meta.VPPAppsTeamsID, *policy2.VPPAppsTeamsID)
// Remove all apps
err = ds.SetTeamVPPApps(ctx, &team.ID, []fleet.VPPAppTeam{})
err = ds.SetTeamVPPApps(ctx, &team.ID, []fleet.VPPAppTeam{}, nil)
require.NoError(t, err)
assigned, err = ds.GetAssignedVPPApps(ctx, &team.ID)
@@ -1806,7 +1806,7 @@ func testVPPTokenTeamAssignment(t *testing.T, ds *Datastore) {
err = ds.SetTeamVPPApps(ctx, &team1.ID, []fleet.VPPAppTeam{
{VPPAppID: app1.VPPAppID, InstallDuringSetup: ptr.Bool(true)},
{VPPAppID: app2.VPPAppID, SelfService: true},
})
}, nil)
require.NoError(t, err)
assigned, err = ds.GetAssignedVPPApps(ctx, &team1.ID)
@@ -1913,7 +1913,7 @@ func testSetTeamVPPAppsWithLabels(t *testing.T, ds *Datastore) {
err = ds.SetTeamVPPApps(ctx, &team.ID, []fleet.VPPAppTeam{
app1.VPPAppTeam,
app2.VPPAppTeam,
})
}, nil)
require.NoError(t, err)
assigned, err = ds.GetAssignedVPPApps(ctx, &team.ID)
@@ -1972,7 +1972,7 @@ func testSetTeamVPPAppsWithLabels(t *testing.T, ds *Datastore) {
err = ds.SetTeamVPPApps(ctx, &team.ID, []fleet.VPPAppTeam{
app1.VPPAppTeam,
app2.VPPAppTeam,
})
}, nil)
require.NoError(t, err)
assigned, err = ds.GetAssignedVPPApps(ctx, &team.ID)
+1 -1
View File
@@ -2127,7 +2127,7 @@ type Datastore interface {
BatchInsertVPPApps(ctx context.Context, apps []*VPPApp) error
GetAssignedVPPApps(ctx context.Context, teamID *uint) (map[VPPAppID]VPPAppTeam, error)
GetVPPApps(ctx context.Context, teamID *uint) ([]VPPAppResponse, error)
SetTeamVPPApps(ctx context.Context, teamID *uint, appIDs []VPPAppTeam) error
SetTeamVPPApps(ctx context.Context, teamID *uint, appIDs []VPPAppTeam, appStoreAppIDsToTitleIDs map[string]uint) error
InsertVPPAppWithTeam(ctx context.Context, app *VPPApp, teamID *uint) (*VPPApp, error)
GetVPPAppsToInstallDuringSetupExperience(ctx context.Context, teamID *uint, platform string) ([]string, error)
+3 -3
View File
@@ -1363,7 +1363,7 @@ type GetAssignedVPPAppsFunc func(ctx context.Context, teamID *uint) (map[fleet.V
type GetVPPAppsFunc func(ctx context.Context, teamID *uint) ([]fleet.VPPAppResponse, error)
type SetTeamVPPAppsFunc func(ctx context.Context, teamID *uint, appIDs []fleet.VPPAppTeam) error
type SetTeamVPPAppsFunc func(ctx context.Context, teamID *uint, appIDs []fleet.VPPAppTeam, appStoreAppIDsToTitleIDs map[string]uint) error
type InsertVPPAppWithTeamFunc func(ctx context.Context, app *fleet.VPPApp, teamID *uint) (*fleet.VPPApp, error)
@@ -8822,11 +8822,11 @@ func (s *DataStore) GetVPPApps(ctx context.Context, teamID *uint) ([]fleet.VPPAp
return s.GetVPPAppsFunc(ctx, teamID)
}
func (s *DataStore) SetTeamVPPApps(ctx context.Context, teamID *uint, appIDs []fleet.VPPAppTeam) error {
func (s *DataStore) SetTeamVPPApps(ctx context.Context, teamID *uint, appIDs []fleet.VPPAppTeam, appStoreAppIDsToTitleIDs map[string]uint) error {
s.mu.Lock()
s.SetTeamVPPAppsFuncInvoked = true
s.mu.Unlock()
return s.SetTeamVPPAppsFunc(ctx, teamID, appIDs)
return s.SetTeamVPPAppsFunc(ctx, teamID, appIDs, appStoreAppIDsToTitleIDs)
}
func (s *DataStore) InsertVPPAppWithTeam(ctx context.Context, app *fleet.VPPApp, teamID *uint) (*fleet.VPPApp, error) {
+56 -2
View File
@@ -11722,8 +11722,8 @@ func (s *integrationMDMTestSuite) TestBatchAssociateAppStoreApps() {
// Remove an app
s.DoJSON("POST", batchURL, batchAssociateAppStoreAppsRequest{Apps: []fleet.VPPBatchPayload{
{AppStoreID: s.appleVPPConfigSrvConfig.Assets[0].AdamID},
{AppStoreID: driveAppID, Platform: fleet.AndroidPlatform},
{AppStoreID: s.appleVPPConfigSrvConfig.Assets[0].AdamID, DisplayName: "VPPAppUpdatedName"},
{AppStoreID: driveAppID, Platform: fleet.AndroidPlatform, DisplayName: "DriveUpdatedName"},
}}, http.StatusOK, &batchAssociateResponse, "team_name", tmGood.Name)
require.Len(t, batchAssociateResponse.Apps, 2)
@@ -11742,6 +11742,60 @@ func (s *integrationMDMTestSuite) TestBatchAssociateAppStoreApps() {
s.runWorker()
s.Assert().True(s.androidAPIClient.EnterprisesPoliciesPatchFuncInvoked)
checkJobs([]string{driveAppID})
var listSwTitles listSoftwareTitlesResponse
s.DoJSON("GET", "/api/latest/fleet/software/titles", nil, http.StatusOK, &listSwTitles, "team_id", fmt.Sprint(tmGood.ID))
s.Assert().Len(listSwTitles.SoftwareTitles, 2)
for _, sw := range listSwTitles.SoftwareTitles {
switch sw.AppStoreApp.AppStoreID {
case driveAppID:
s.Assert().Equal("DriveUpdatedName", sw.DisplayName)
case s.appleVPPConfigSrvConfig.Assets[0].AdamID:
s.Assert().Equal("VPPAppUpdatedName", sw.DisplayName)
}
}
// change display names
setDisplayNames := func(androidAppName, vppAppName string) {
s.DoJSON("POST", batchURL, batchAssociateAppStoreAppsRequest{Apps: []fleet.VPPBatchPayload{
{AppStoreID: s.appleVPPConfigSrvConfig.Assets[0].AdamID, DisplayName: vppAppName},
{AppStoreID: driveAppID, Platform: fleet.AndroidPlatform, DisplayName: androidAppName},
}}, http.StatusOK, &batchAssociateResponse, "team_name", tmGood.Name)
require.Len(t, batchAssociateResponse.Apps, 2)
assoc, err = s.ds.GetAssignedVPPApps(ctx, &tmGood.ID)
require.NoError(t, err)
require.Len(t, assoc, 2)
for _, a := range []fleet.VPPAppID{
{AdamID: s.appleVPPConfigSrvConfig.Assets[0].AdamID, Platform: fleet.MacOSPlatform},
{AdamID: driveAppID, Platform: fleet.AndroidPlatform},
} {
assert.Contains(t, assoc, a)
}
time.Sleep(time.Second)
s.runWorker()
s.Assert().True(s.androidAPIClient.EnterprisesPoliciesPatchFuncInvoked)
checkJobs([]string{driveAppID})
s.DoJSON("GET", "/api/latest/fleet/software/titles", nil, http.StatusOK, &listSwTitles, "team_id", fmt.Sprint(tmGood.ID))
s.Assert().Len(listSwTitles.SoftwareTitles, 2)
for _, sw := range listSwTitles.SoftwareTitles {
switch sw.AppStoreApp.AppStoreID {
case driveAppID:
s.Assert().Equal(androidAppName, sw.DisplayName)
case s.appleVPPConfigSrvConfig.Assets[0].AdamID:
s.Assert().Equal(vppAppName, sw.DisplayName)
}
}
}
setDisplayNames("VPPAppUpdatedName2", "DriveUpdatedName2")
setDisplayNames("", "")
}
func (s *integrationMDMTestSuite) TestInvalidCommandUUID() {