From 7eb3628fe6e88f8472287bf76ca9b24f7da4df9c Mon Sep 17 00:00:00 2001 From: Lucas Manuel Rodriguez Date: Mon, 10 Jun 2024 16:49:45 -0300 Subject: [PATCH] Support RPM upgrades on fleetd packages (#19494) #18534 - [X] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://fleetdm.com/docs/contributing/committing-changes#changes-files) for more information. - [X] Manual QA for all new/changed functionality - For Orbit and Fleet Desktop changes: - [X] Manual QA must be performed in the three main OSs, macOS, Windows and Linux. - [x] Auto-update manual QA, from released version of component to new version (see [tools/tuf/test](../tools/tuf/test/README.md)). --- changes/18534-support-rpm-upgrade | 1 + orbit/pkg/packaging/linux_shared.go | 56 +++++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 changes/18534-support-rpm-upgrade diff --git a/changes/18534-support-rpm-upgrade b/changes/18534-support-rpm-upgrade new file mode 100644 index 0000000000..8294440820 --- /dev/null +++ b/changes/18534-support-rpm-upgrade @@ -0,0 +1 @@ +* Added support for upgrades to fleetd RPMs packages. diff --git a/orbit/pkg/packaging/linux_shared.go b/orbit/pkg/packaging/linux_shared.go index 8e0d67aff9..c7199b8163 100644 --- a/orbit/pkg/packaging/linux_shared.go +++ b/orbit/pkg/packaging/linux_shared.go @@ -15,6 +15,7 @@ import ( "github.com/fleetdm/fleet/v4/pkg/secure" "github.com/goreleaser/nfpm/v2" "github.com/goreleaser/nfpm/v2/files" + "github.com/goreleaser/nfpm/v2/rpm" "github.com/rs/zerolog/log" ) @@ -85,6 +86,8 @@ func buildNFPM(opt Options, pkger nfpm.Packager) (string, error) { // Write files + _, isRPM := pkger.(*rpm.RPM) + if err := writeSystemdUnit(opt, rootDir); err != nil { return "", fmt.Errorf("write systemd unit: %w", err) } @@ -110,9 +113,16 @@ func buildNFPM(opt Options, pkger nfpm.Packager) (string, error) { return "", fmt.Errorf("write preremove script: %w", err) } postRemovePath := filepath.Join(tmpDir, "postremove.sh") - if err := writePostRemove(opt, postRemovePath); err != nil { + if err := writePostRemove(postRemovePath); err != nil { return "", fmt.Errorf("write postremove script: %w", err) } + var postTransPath string + if isRPM { + postTransPath = filepath.Join(tmpDir, "posttrans.sh") + if err := writeRPMPostTrans(opt, postTransPath); err != nil { + return "", fmt.Errorf("write RPM posttrans script: %w", err) + } + } if opt.FleetCertificate != "" { if err := writeFleetServerCertificate(opt, orbitRoot); err != nil { @@ -194,6 +204,11 @@ func buildNFPM(opt Options, pkger nfpm.Packager) (string, error) { log.Debug().Interface("file", c).Msg("added file") } + rpmInfo := nfpm.RPM{} + if _, ok := pkger.(*rpm.RPM); ok { + rpmInfo.Scripts.PostTrans = postTransPath + } + // Build package info := &nfpm.Info{ Name: "fleet-osquery", @@ -211,6 +226,7 @@ func buildNFPM(opt Options, pkger nfpm.Packager) (string, error) { PreRemove: preRemovePath, PostRemove: postRemovePath, }, + RPM: rpmInfo, }, } filename := pkger.ConventionalFileName(info) @@ -367,7 +383,7 @@ pkill fleet-desktop || true return nil } -func writePostRemove(opt Options, path string) error { +func writePostRemove(path string) error { if err := os.WriteFile(path, []byte(`#!/bin/sh # For RPM during uninstall, $1 is 0 @@ -381,3 +397,39 @@ fi return nil } + +// postTransTemplate contains the template for RPM posttrans scriptlet (used when upgrading). +// See https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/. +// +// We cannot rely on "$1" because it's always "0" for RPM < 4.12 +// (see https://github.com/rpm-software-management/rpm/commit/ab069ec876639d46d12dd76dad54fd8fb762e43d) +// thus we check if orbit service is enabled, and if not we enable it (because posttrans +// will run both on "install" and "upgrade"). +var postTransTemplate = template.Must(template.New("posttrans").Parse(`#!/bin/sh + +# Exit on error +set -e + +if ! systemctl is-enabled orbit >/dev/null 2>&1; then + # If we have a systemd, daemon-reload away now + if command -v systemctl >/dev/null 2>&1; then + systemctl daemon-reload >/dev/null 2>&1 +{{ if .StartService -}} + systemctl restart orbit.service 2>&1 + systemctl enable orbit.service 2>&1 +{{- end}} + fi +fi +`)) + +// writeRPMPostTrans sets the posttrans scriptlets necessary to support RPM upgrades. +func writeRPMPostTrans(opt Options, path string) error { + var contents bytes.Buffer + if err := postTransTemplate.Execute(&contents, opt); err != nil { + return fmt.Errorf("execute template: %w", err) + } + if err := os.WriteFile(path, contents.Bytes(), constant.DefaultFileMode); err != nil { + return fmt.Errorf("write file: %w", err) + } + return nil +}