Skip to content

create new appCfg entry on AB fleet updates if not found - #49559

Merged
MagnusHJensen merged 2 commits into
mainfrom
48653-empty-ab-when-only-updated-via-ui
Jul 21, 2026
Merged

create new appCfg entry on AB fleet updates if not found#49559
MagnusHJensen merged 2 commits into
mainfrom
48653-empty-ab-when-only-updated-via-ui

Conversation

@MagnusHJensen

@MagnusHJensen MagnusHJensen commented Jul 20, 2026

Copy link
Copy Markdown
Member

Related issue: Resolves #48653

Checklist for submitter

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

  • Changes file added for user-visible changes in changes/, orbit/changes/ or ee/fleetd-chrome/changes.
    See Changes files for more information.

  • Input data is properly validated, SELECT * is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters.

  • Timeouts are implemented and retries are limited to avoid infinite loops

  • If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes

Testing

  • Added/updated automated tests
  • QA'd all new/changed functionality manually

Summary by CodeRabbit

  • Bug Fixes
    • Improved Apple Business Manager configuration handling when updating team assignments, including creating the assignment entry when it doesn’t already exist.
    • Removing an Apple Business Manager token now also removes its corresponding assignment details and properly updates configuration status when no tokens remain.
    • Prevented generate-gitops from exporting an empty apple_business section when default fleets are configured only via the UI.
  • Tests
    • Expanded coverage for team assignment updates to validate creation of new configuration entries.

@MagnusHJensen
MagnusHJensen requested a review from a team as a code owner July 20, 2026 12:48
Copilot AI review requested due to automatic review settings July 20, 2026 12:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

  • Copilot's review of this pull request may be incomplete because some of the changed files are excluded by your Copilot content exclusion settings. See Excluding content from Copilot for details.

Pull request overview

This PR fixes GitOps export correctness for Apple Business Manager (ABM) default fleet assignments by ensuring the app config’s apple_business mapping is created/maintained when ABM defaults are updated via the UI, and keeps app config entries in sync on token deletion.

Changes:

  • Update ABM token team update flow to create a new apple_business app-config entry when none exists.
  • Update ABM token deletion flow to remove the corresponding apple_business app-config entry.
  • Add a unit test covering the “entry not present” update scenario.

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 3 comments.

File Description
ee/server/service/mdm.go Syncs ABM token updates/deletes with app config apple_business entries.
ee/server/service/mdm_test.go Adds coverage for creating a missing app-config entry on ABM team updates.
changes/48653-empty-ab-when-only-updated-via-ui Excluded from review by policy (not accessed).
Files excluded by content exclusion policy (1)
  • changes/48653-empty-ab-when-only-updated-via-ui

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ee/server/service/mdm.go
Comment thread ee/server/service/mdm.go
Comment thread ee/server/service/mdm_test.go
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bbdd9900-25b7-4574-8d66-425af4341162

📥 Commits

Reviewing files that changed from the base of the PR and between 32e12f8 and 9059295.

📒 Files selected for processing (1)
  • ee/server/service/mdm.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • ee/server/service/mdm.go

Walkthrough

ABM token deletion now retrieves token metadata, removes the matching Apple Business assignment, saves the app configuration, and disables Apple Business Manager when the last token is deleted. Team updates now create missing assignment entries and persist their fleet names. Tests cover insertion of new assignments, and a changelog entry documents the GitOps export fix for UI-configured default fleets.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main fix: creating a new appCfg entry when Apple Business fleet updates are missing one.
Description check ✅ Passed The description includes the related issue, checklist items, testing, and manual QA, matching the repository template.
Linked Issues check ✅ Passed The code changes and tests address #48653 by adding missing Apple Business app config entries and preserving fleet assignments.
Out of Scope Changes check ✅ Passed The changes stay focused on Apple Business GitOps export behavior and associated tests, with no clear unrelated scope added.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 48653-empty-ab-when-only-updated-via-ui

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
ee/server/service/mdm.go (1)

1785-1823: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Fix "No team" strings leaking into GitOps output and properly set optjson flags.

Two issues exist in the current implementation:

  1. When appending a new entry in the !found path, the "No team" strings (fallback values for unassigned teams) are not cleared. This bypasses the "No team" cleanup logic running in the found branch, which will cause GitOps to incorrectly export macos_team: "No team" instead of an empty string.
  2. If appCfg.MDM.AppleBusinessManager was never configured, appending to its .Value without explicitly toggling .Set = true and .Valid = true will cause optjson to omit the field during JSON serialization, failing to persist the new assignment.

Consolidate the cleanup logic before the condition to ensure newly appended entries are properly formatted and the optjson slice is marked as set.

🛠️ Proposed fix
-	var found bool
-	for i, appCfgToken := range appCfg.MDM.AppleBusinessManager.Value {
-		if appCfgToken.OrganizationName == token.OrganizationName {
-
-			// Clear no team names, so they are presented nicer in gitops.
-			appCfgToken.BYODTeam = token.BYODTeam.Name
-			if token.BYODTeam.Name == fleet.TeamNameNoTeam {
-				appCfgToken.BYODTeam = ""
-			}
-			appCfgToken.MacOSTeam = token.MacOSTeam.Name
-			if token.MacOSTeam.Name == fleet.TeamNameNoTeam {
-				appCfgToken.MacOSTeam = ""
-			}
-			appCfgToken.IOSTeam = token.IOSTeam.Name
-			if token.IOSTeam.Name == fleet.TeamNameNoTeam {
-				appCfgToken.IOSTeam = ""
-			}
-			appCfgToken.IpadOSTeam = token.IPadOSTeam.Name
-			if token.IPadOSTeam.Name == fleet.TeamNameNoTeam {
-				appCfgToken.IpadOSTeam = ""
-			}
-
-			// update the app config with the new team names
-			appCfg.MDM.AppleBusinessManager.Value[i] = appCfgToken
-			found = true
-			break
-		}
-	}
-
-	if !found {
-		// create a new entry if app config doesn't have one.
-		appCfg.MDM.AppleBusinessManager.Value = append(appCfg.MDM.AppleBusinessManager.Value, fleet.MDMAppleABMAssignmentInfo{
-			OrganizationName: token.OrganizationName,
-			BYODTeam:         token.BYODTeam.Name,
-			MacOSTeam:        token.MacOSTeam.Name,
-			IOSTeam:          token.IOSTeam.Name,
-			IpadOSTeam:       token.IPadOSTeam.Name,
-		})
-	}
+	appCfgToken := fleet.MDMAppleABMAssignmentInfo{
+		OrganizationName: token.OrganizationName,
+		BYODTeam:         token.BYODTeam.Name,
+		MacOSTeam:        token.MacOSTeam.Name,
+		IOSTeam:          token.IOSTeam.Name,
+		IpadOSTeam:       token.IPadOSTeam.Name,
+	}
+
+	// Clear no team names, so they are presented nicer in gitops.
+	if appCfgToken.BYODTeam == fleet.TeamNameNoTeam {
+		appCfgToken.BYODTeam = ""
+	}
+	if appCfgToken.MacOSTeam == fleet.TeamNameNoTeam {
+		appCfgToken.MacOSTeam = ""
+	}
+	if appCfgToken.IOSTeam == fleet.TeamNameNoTeam {
+		appCfgToken.IOSTeam = ""
+	}
+	if appCfgToken.IpadOSTeam == fleet.TeamNameNoTeam {
+		appCfgToken.IpadOSTeam = ""
+	}
+
+	var found bool
+	for i, existing := range appCfg.MDM.AppleBusinessManager.Value {
+		if existing.OrganizationName == token.OrganizationName {
+			// update the app config with the new team names
+			appCfg.MDM.AppleBusinessManager.Value[i] = appCfgToken
+			found = true
+			break
+		}
+	}
+
+	if !found {
+		// create a new entry if app config doesn't have one.
+		appCfg.MDM.AppleBusinessManager.Value = append(appCfg.MDM.AppleBusinessManager.Value, appCfgToken)
+	}
+
+	appCfg.MDM.AppleBusinessManager.Set = true
+	appCfg.MDM.AppleBusinessManager.Valid = true
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ee/server/service/mdm.go` around lines 1785 - 1823, Consolidate the team-name
cleanup before the found/not-found branch so BYODTeam, MacOSTeam, IOSTeam, and
IpadOSTeam store empty strings for fleet.TeamNameNoTeam in both update and
append paths. In the !found path, append the cleaned values and explicitly set
appCfg.MDM.AppleBusinessManager.Set and Valid to true so optjson serializes the
new assignment.
🧹 Nitpick comments (2)
ee/server/service/mdm.go (1)

1658-1663: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Set optjson wrapper flags explicitly.

When mutating the underlying .Value of an optjson.Slice, it is a good practice to explicitly flag .Set and .Valid as true to ensure the slice safely marshals to JSON on save, especially if the slice becomes empty.

🛠️ Proposed refactor
 	for i, t := range appCfg.MDM.AppleBusinessManager.Value {
 		if t.OrganizationName == token.OrganizationName {
 			appCfg.MDM.AppleBusinessManager.Value = append(appCfg.MDM.AppleBusinessManager.Value[:i], appCfg.MDM.AppleBusinessManager.Value[i+1:]...)
+			appCfg.MDM.AppleBusinessManager.Set = true
+			appCfg.MDM.AppleBusinessManager.Valid = true
 			break
 		}
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ee/server/service/mdm.go` around lines 1658 - 1663, After removing the
matching entry in the Apple Business Manager slice within the MDM configuration
update flow, explicitly set the enclosing optjson.Slice’s Set and Valid flags to
true so the mutated value, including an empty slice, marshals correctly when
saved.
ee/server/service/mdm_test.go (1)

582-605: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test missing assignment creation with nil team parameters.

To complement the test for valid team IDs, consider adding a subtest verifying that a missing app config entry initialized with nil team IDs successfully scrubs "No team" strings and leaves the fields empty. This prevents future regressions of the issue flagged in mdm.go.

🧪 Proposed test case addition
 		assert.Equal(t, validTeamName, appCfgToken.MacOSTeam)
 		assert.Equal(t, validTeamName, appCfgToken.IOSTeam)
 		assert.Equal(t, validTeamName, appCfgToken.IpadOSTeam)
 	})
+
+	t.Run("updates app config with new entry if not present (nil teams)", func(t *testing.T) {
+		ds.SaveAppConfigFuncInvoked = false
+		appCfg.MDM.AppleBusinessManager = optjson.SetSlice([]fleet.MDMAppleABMAssignmentInfo{})
+
+		token, err := svc.UpdateABMTokenTeams(ctx, tokenID, nil, nil, nil, nil)
+		require.NoError(t, err)
+
+		assert.Nil(t, token.BYODDefaultTeamID)
+		assert.Nil(t, token.MacOSDefaultTeamID)
+		assert.Nil(t, token.IOSDefaultTeamID)
+		assert.Nil(t, token.IPadOSDefaultTeamID)
+		require.True(t, ds.SaveAppConfigFuncInvoked)
+
+		var appCfgToken fleet.MDMAppleABMAssignmentInfo
+		for _, tok := range updatedAppCfg.MDM.AppleBusinessManager.Value {
+			if tok.OrganizationName == orgName {
+				appCfgToken = tok
+				break
+			}
+		}
+		assert.Empty(t, appCfgToken.BYODTeam)
+		assert.Empty(t, appCfgToken.MacOSTeam)
+		assert.Empty(t, appCfgToken.IOSTeam)
+		assert.Empty(t, appCfgToken.IpadOSTeam)
+	})
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ee/server/service/mdm_test.go` around lines 582 - 605, The
UpdateABMTokenTeams tests should also cover creating a missing
AppleBusinessManager assignment when all team parameters are nil. Add a subtest
alongside “updates app config with new entry if not present” that invokes
UpdateABMTokenTeams with nil team IDs, verifies success, and confirms the newly
created assignment has empty team fields rather than “No team” strings.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@ee/server/service/mdm.go`:
- Around line 1785-1823: Consolidate the team-name cleanup before the
found/not-found branch so BYODTeam, MacOSTeam, IOSTeam, and IpadOSTeam store
empty strings for fleet.TeamNameNoTeam in both update and append paths. In the
!found path, append the cleaned values and explicitly set
appCfg.MDM.AppleBusinessManager.Set and Valid to true so optjson serializes the
new assignment.

---

Nitpick comments:
In `@ee/server/service/mdm_test.go`:
- Around line 582-605: The UpdateABMTokenTeams tests should also cover creating
a missing AppleBusinessManager assignment when all team parameters are nil. Add
a subtest alongside “updates app config with new entry if not present” that
invokes UpdateABMTokenTeams with nil team IDs, verifies success, and confirms
the newly created assignment has empty team fields rather than “No team”
strings.

In `@ee/server/service/mdm.go`:
- Around line 1658-1663: After removing the matching entry in the Apple Business
Manager slice within the MDM configuration update flow, explicitly set the
enclosing optjson.Slice’s Set and Valid flags to true so the mutated value,
including an empty slice, marshals correctly when saved.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e342e5a1-dc05-4db1-aad6-bdbd9828f212

📥 Commits

Reviewing files that changed from the base of the PR and between 4762dba and 32e12f8.

📒 Files selected for processing (3)
  • changes/48653-empty-ab-when-only-updated-via-ui
  • ee/server/service/mdm.go
  • ee/server/service/mdm_test.go

@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 68.42105% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.82%. Comparing base (6c5d733) to head (9059295).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
ee/server/service/mdm.go 68.42% 7 Missing and 5 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #49559      +/-   ##
==========================================
- Coverage   67.82%   67.82%   -0.01%     
==========================================
  Files        3890     3890              
  Lines      247624   247661      +37     
  Branches    12981    13138     +157     
==========================================
+ Hits       167951   167964      +13     
- Misses      64516    64529      +13     
- Partials    15157    15168      +11     
Flag Coverage Δ
backend 69.22% <68.42%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@MagnusHJensen
MagnusHJensen merged commit 94d5a7d into main Jul 21, 2026
44 checks passed
@MagnusHJensen
MagnusHJensen deleted the 48653-empty-ab-when-only-updated-via-ui branch July 21, 2026 19:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

generate-gitops exports an empty apple_business section for UI-configured fleet assignments

3 participants