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

Cherry-Pick: Updated BatchSetSoftwareInstallers to use bundle_identifier #26268

Merged
merged 2 commits into from
Feb 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 37 additions & 11 deletions server/datastore/mysql/software_installers.go
Original file line number Diff line number Diff line change
Expand Up @@ -1071,21 +1071,22 @@ func (ds *Datastore) CleanupUnusedSoftwareInstallers(ctx context.Context, softwa
func (ds *Datastore) BatchSetSoftwareInstallers(ctx context.Context, tmID *uint, installers []*fleet.UploadSoftwareInstallerPayload) error {
const upsertSoftwareTitles = `
INSERT INTO software_titles
(name, source, browser)
(name, source, browser, bundle_identifier)
VALUES
%s
ON DUPLICATE KEY UPDATE
name = VALUES(name),
source = VALUES(source),
browser = VALUES(browser)
browser = VALUES(browser),
bundle_identifier = VALUES(bundle_identifier)
`

const loadSoftwareTitles = `
SELECT
id
FROM
software_titles
WHERE (name, source, browser) IN (%s)
WHERE (unique_identifier, source, browser) IN (%s)
`

const unsetAllInstallersFromPolicies = `
Expand Down Expand Up @@ -1190,7 +1191,7 @@ COALESCE(post_install_script_content_id != ? OR
(post_install_script_content_id IS NULL AND ? IS NOT NULL) OR
(? IS NULL AND post_install_script_content_id IS NOT NULL)
, FALSE) is_metadata_modified FROM software_installers
WHERE global_or_team_id = ? AND title_id IN (SELECT id FROM software_titles WHERE name = ? AND source = ? AND browser = '')
WHERE global_or_team_id = ? AND title_id IN (SELECT id FROM software_titles WHERE unique_identifier = ? AND source = ? AND browser = '')
`

const insertNewOrEditedInstaller = `
Expand All @@ -1216,7 +1217,7 @@ INSERT INTO software_installers (
install_during_setup
) VALUES (
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
(SELECT id FROM software_titles WHERE name = ? AND source = ? AND browser = ''),
(SELECT id FROM software_titles WHERE unique_identifier = ? AND source = ? AND browser = ''),
?, (SELECT name FROM users WHERE id = ?), (SELECT email FROM users WHERE id = ?), ?, ?, COALESCE(?, false)
)
ON DUPLICATE KEY UPDATE
Expand Down Expand Up @@ -1245,7 +1246,7 @@ FROM
WHERE
global_or_team_id = ? AND
-- this is guaranteed to select a single title_id, due to unique index
title_id IN (SELECT id FROM software_titles WHERE name = ? AND source = ? AND browser = '')
title_id IN (SELECT id FROM software_titles WHERE unique_identifier = ? AND source = ? AND browser = '')
`

const deleteInstallerLabelsNotInList = `
Expand Down Expand Up @@ -1330,18 +1331,43 @@ WHERE

var args []any
for _, installer := range installers {
args = append(args, installer.Title, installer.Source, "")
args = append(
args,
installer.Title,
installer.Source,
"",
func() *string {
if strings.TrimSpace(installer.BundleIdentifier) != "" {
return &installer.BundleIdentifier
}
return nil
}(),
)
}

values := strings.TrimSuffix(
strings.Repeat("(?,?,?),", len(installers)),
strings.Repeat("(?,?,?,?),", len(installers)),
",",
)
if _, err := tx.ExecContext(ctx, fmt.Sprintf(upsertSoftwareTitles, values), args...); err != nil {
return ctxerr.Wrap(ctx, err, "insert new/edited software title")
}

var titleIDs []uint
args = []any{}
for _, installer := range installers {
args = append(
args,
BundleIdentifierOrName(installer.BundleIdentifier, installer.Title),
installer.Source,
"",
)
}
values = strings.TrimSuffix(
strings.Repeat("(?,?,?),", len(installers)),
",",
)

if err := sqlx.SelectContext(ctx, tx, &titleIDs, fmt.Sprintf(loadSoftwareTitles, values), args...); err != nil {
return ctxerr.Wrap(ctx, err, "load existing titles")
}
Expand Down Expand Up @@ -1441,7 +1467,7 @@ WHERE
postInstallScriptID,
// WHERE clause
globalOrTeamID,
installer.Title,
BundleIdentifierOrName(installer.BundleIdentifier, installer.Title),
installer.Source,
}

Expand Down Expand Up @@ -1472,7 +1498,7 @@ WHERE
postInstallScriptID,
installer.Platform,
installer.SelfService,
installer.Title,
BundleIdentifierOrName(installer.BundleIdentifier, installer.Title),
installer.Source,
installer.UserID,
installer.UserID,
Expand All @@ -1495,7 +1521,7 @@ WHERE
// ID (cannot use res.LastInsertID due to the upsert statement, won't
// give the id in case of update)
var installerID uint
if err := sqlx.GetContext(ctx, tx, &installerID, loadSoftwareInstallerID, globalOrTeamID, installer.Title, installer.Source); err != nil {
if err := sqlx.GetContext(ctx, tx, &installerID, loadSoftwareInstallerID, globalOrTeamID, BundleIdentifierOrName(installer.BundleIdentifier, installer.Title), installer.Source); err != nil {
return ctxerr.Wrapf(ctx, err, "load id of new/edited installer with name %q", installer.Filename)
}

Expand Down
73 changes: 61 additions & 12 deletions server/datastore/mysql/software_installers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -753,18 +753,19 @@ func testBatchSetSoftwareInstallers(t *testing.T, ds *Datastore) {
tfr0, err := fleet.NewTempFileReader(ins0File, t.TempDir)
require.NoError(t, err)
err = ds.BatchSetSoftwareInstallers(ctx, &team.ID, []*fleet.UploadSoftwareInstallerPayload{{
InstallScript: "install",
InstallerFile: tfr0,
StorageID: ins0,
Filename: "installer0",
Title: "ins0",
Source: "apps",
Version: "1",
PreInstallQuery: "foo",
UserID: user1.ID,
Platform: "darwin",
URL: "https://example.com",
ValidatedLabels: &fleet.LabelIdentsWithScope{},
InstallScript: "install",
InstallerFile: tfr0,
StorageID: ins0,
Filename: "installer0",
Title: "ins0",
Source: "apps",
Version: "1",
PreInstallQuery: "foo",
UserID: user1.ID,
Platform: "darwin",
URL: "https://example.com",
ValidatedLabels: &fleet.LabelIdentsWithScope{},
BundleIdentifier: "com.example.ins0",
}})
require.NoError(t, err)
softwareInstallers, err = ds.GetSoftwareInstallers(ctx, team.ID)
Expand Down Expand Up @@ -950,6 +951,54 @@ func testBatchSetSoftwareInstallers(t *testing.T, ds *Datastore) {
{Name: ins1, Source: "apps", Browser: ""},
})

// Add software installer with same name different bundle id
err = ds.BatchSetSoftwareInstallers(ctx, &team.ID, []*fleet.UploadSoftwareInstallerPayload{{
InstallScript: "install",
InstallerFile: tfr0,
StorageID: ins0,
Filename: "installer0",
Title: "ins0",
Source: "apps",
Version: "1",
PreInstallQuery: "foo",
UserID: user1.ID,
Platform: "darwin",
URL: "https://example.com",
ValidatedLabels: &fleet.LabelIdentsWithScope{},
BundleIdentifier: "com.example.different.ins0",
}})
require.NoError(t, err)
softwareInstallers, err = ds.GetSoftwareInstallers(ctx, team.ID)
require.NoError(t, err)
require.Len(t, softwareInstallers, 1)
assertSoftware([]fleet.SoftwareTitle{
{Name: ins0, Source: "apps", Browser: "", BundleIdentifier: ptr.String("com.example.different.ins0")},
})

// Add software installer with the same bundle id but different name
err = ds.BatchSetSoftwareInstallers(ctx, &team.ID, []*fleet.UploadSoftwareInstallerPayload{{
InstallScript: "install",
InstallerFile: tfr0,
StorageID: ins0,
Filename: "installer0",
Title: "ins0-different",
Source: "apps",
Version: "1",
PreInstallQuery: "foo",
UserID: user1.ID,
Platform: "darwin",
URL: "https://example.com",
ValidatedLabels: &fleet.LabelIdentsWithScope{},
BundleIdentifier: "com.example.ins0",
}})
require.NoError(t, err)
softwareInstallers, err = ds.GetSoftwareInstallers(ctx, team.ID)
require.NoError(t, err)
require.Len(t, softwareInstallers, 1)
assertSoftware([]fleet.SoftwareTitle{
{Name: "ins0-different", Source: "apps", Browser: "", BundleIdentifier: ptr.String("com.example.ins0")},
})

// remove everything
err = ds.BatchSetSoftwareInstallers(ctx, &team.ID, []*fleet.UploadSoftwareInstallerPayload{})
require.NoError(t, err)
Expand Down
Loading