From 90ff808f21a39c53432419e7f1a557392b4b2de7 Mon Sep 17 00:00:00 2001 From: Lincoln Wallace Date: Sun, 20 Jul 2025 15:57:40 -0300 Subject: [PATCH 01/10] feat: add remove hook and access to etc-default-grub for remove hook - Add remove hook to drop custom GRUB config file 60_rt-conf.cfg - snapcraft.yaml: add hooks session with remove hook to access /etc/default/grub.d/60_rt-conf.cfg Signed-off-by: Lincoln Wallace --- snap/hooks/remove | 10 ++++++++++ snap/snapcraft.yaml | 5 +++++ 2 files changed, 15 insertions(+) create mode 100755 snap/hooks/remove diff --git a/snap/hooks/remove b/snap/hooks/remove new file mode 100755 index 00000000..b697d689 --- /dev/null +++ b/snap/hooks/remove @@ -0,0 +1,10 @@ +#!/bin/bash + +set -eu + +if snapctl is-connected etc-default-grubd; then + rm /etc/default/grub.d/60_rt-conf.cfg || true + exit 0 +fi + +echo "WARN: The etc-default-grubd plug isn't connected, please manually remove the config file on /etc/default/grub.d/60_rt-conf.cfg" >&2 diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 1c23b6a8..4d584b12 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -37,6 +37,11 @@ plugs: read: - /etc/default/grub +hooks: + remove: + plugs: + - etc-default-grub + apps: rt-conf: &rt-conf plugs: From 00459e8c458dbd3366519e859afedcdc17f07e0e Mon Sep 17 00:00:00 2001 From: Lincoln Wallace Date: Mon, 21 Jul 2025 10:42:57 -0300 Subject: [PATCH 02/10] feat: log to journal Signed-off-by: Lincoln Wallace --- snap/hooks/remove | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snap/hooks/remove b/snap/hooks/remove index b697d689..7819cfcb 100755 --- a/snap/hooks/remove +++ b/snap/hooks/remove @@ -7,4 +7,4 @@ if snapctl is-connected etc-default-grubd; then exit 0 fi -echo "WARN: The etc-default-grubd plug isn't connected, please manually remove the config file on /etc/default/grub.d/60_rt-conf.cfg" >&2 +echo "[rt-conf snap]: The etc-default-grubd plug isn't connected, please manually remove the config file on /etc/default/grub.d/60_rt-conf.cfg" | logger From e52f0d73bb18bcb61784f9b343d09791e50286a5 Mon Sep 17 00:00:00 2001 From: Lincoln Wallace Date: Mon, 21 Jul 2025 10:48:25 -0300 Subject: [PATCH 03/10] refact: improve log message Signed-off-by: Lincoln Wallace --- snap/hooks/remove | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snap/hooks/remove b/snap/hooks/remove index 7819cfcb..1259057f 100755 --- a/snap/hooks/remove +++ b/snap/hooks/remove @@ -7,4 +7,4 @@ if snapctl is-connected etc-default-grubd; then exit 0 fi -echo "[rt-conf snap]: The etc-default-grubd plug isn't connected, please manually remove the config file on /etc/default/grub.d/60_rt-conf.cfg" | logger +echo "[rt-conf snap] WARNING: The 'etc-default-grubd' plug is not connected. Please manually remove the configuration file at /etc/default/grub.d/60_rt-conf.cfg." | logger From 19596c3a8f770fd13a51aa2a8597e15bad154cb0 Mon Sep 17 00:00:00 2001 From: Lincoln Wallace Date: Mon, 21 Jul 2025 10:51:17 -0300 Subject: [PATCH 04/10] fix: plug name Signed-off-by: Lincoln Wallace --- snap/hooks/remove | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snap/hooks/remove b/snap/hooks/remove index 1259057f..dbf49b07 100755 --- a/snap/hooks/remove +++ b/snap/hooks/remove @@ -2,9 +2,9 @@ set -eu -if snapctl is-connected etc-default-grubd; then +if snapctl is-connected etc-default-grub; then rm /etc/default/grub.d/60_rt-conf.cfg || true exit 0 fi -echo "[rt-conf snap] WARNING: The 'etc-default-grubd' plug is not connected. Please manually remove the configuration file at /etc/default/grub.d/60_rt-conf.cfg." | logger +echo "[rt-conf snap] WARNING: The 'etc-default-grub' plug is not connected. Please manually remove the configuration file at /etc/default/grub.d/60_rt-conf.cfg." | logger From 22c5a0a595d680e1b27d28d044939c69490bcf6e Mon Sep 17 00:00:00 2001 From: Lincoln Wallace Date: Mon, 21 Jul 2025 11:36:08 -0300 Subject: [PATCH 05/10] refact: remove hook, drop echo message Signed-off-by: Lincoln Wallace --- snap/hooks/remove | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/snap/hooks/remove b/snap/hooks/remove index dbf49b07..457e8b55 100755 --- a/snap/hooks/remove +++ b/snap/hooks/remove @@ -1,10 +1,9 @@ -#!/bin/bash +#!/bin/bash -eu -set -eu +tag="snap.$SNAP_INSTANCE_NAME.hook.refresh" # matching what snapd sets if snapctl is-connected etc-default-grub; then - rm /etc/default/grub.d/60_rt-conf.cfg || true - exit 0 + rm -f /etc/default/grub.d/60_rt-conf.cfg +else + logger --stderr --priority error --tag=$tag "The 'etc-default-grub' plug is not connected. Please manually remove the configuration file at /etc/default/grub.d/60_rt-conf.cfg." fi - -echo "[rt-conf snap] WARNING: The 'etc-default-grub' plug is not connected. Please manually remove the configuration file at /etc/default/grub.d/60_rt-conf.cfg." | logger From 8022b3cbb2267a5a5d1dfadc7a95252c1b84bd11 Mon Sep 17 00:00:00 2001 From: Lincoln Wallace Date: Mon, 21 Jul 2025 11:56:06 -0300 Subject: [PATCH 06/10] feat: add exit 1 (even that snapd will ignore it) Signed-off-by: Lincoln Wallace --- snap/hooks/remove | 1 + 1 file changed, 1 insertion(+) diff --git a/snap/hooks/remove b/snap/hooks/remove index 457e8b55..70f91d3d 100755 --- a/snap/hooks/remove +++ b/snap/hooks/remove @@ -6,4 +6,5 @@ if snapctl is-connected etc-default-grub; then rm -f /etc/default/grub.d/60_rt-conf.cfg else logger --stderr --priority error --tag=$tag "The 'etc-default-grub' plug is not connected. Please manually remove the configuration file at /etc/default/grub.d/60_rt-conf.cfg." + exit 1 fi From 36cc8b10cc928f7c1067b5216fbbc00aa61289e4 Mon Sep 17 00:00:00 2001 From: Lincoln Wallace Date: Mon, 21 Jul 2025 12:12:21 -0300 Subject: [PATCH 07/10] feat: use disconnect hook instead of remove hook to drop GRUB cfg file Signed-off-by: Lincoln Wallace --- snap/hooks/disconnect-plug-etc-default-grub | 3 +++ snap/hooks/remove | 10 ---------- snap/snapcraft.yaml | 2 +- 3 files changed, 4 insertions(+), 11 deletions(-) create mode 100755 snap/hooks/disconnect-plug-etc-default-grub delete mode 100755 snap/hooks/remove diff --git a/snap/hooks/disconnect-plug-etc-default-grub b/snap/hooks/disconnect-plug-etc-default-grub new file mode 100755 index 00000000..ed8ead07 --- /dev/null +++ b/snap/hooks/disconnect-plug-etc-default-grub @@ -0,0 +1,3 @@ +#!/bin/bash -eu + +rm -f /etc/default/grub.d/60_rt-conf.cfg diff --git a/snap/hooks/remove b/snap/hooks/remove deleted file mode 100755 index 70f91d3d..00000000 --- a/snap/hooks/remove +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -eu - -tag="snap.$SNAP_INSTANCE_NAME.hook.refresh" # matching what snapd sets - -if snapctl is-connected etc-default-grub; then - rm -f /etc/default/grub.d/60_rt-conf.cfg -else - logger --stderr --priority error --tag=$tag "The 'etc-default-grub' plug is not connected. Please manually remove the configuration file at /etc/default/grub.d/60_rt-conf.cfg." - exit 1 -fi diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 4d584b12..c5698fa2 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -38,7 +38,7 @@ plugs: - /etc/default/grub hooks: - remove: + disconnect-plug-etc-default-grub: plugs: - etc-default-grub From b274359595d27675b01796f95ebcb0373ae9b306 Mon Sep 17 00:00:00 2001 From: Lincoln Wallace Date: Mon, 18 Aug 2025 08:52:11 -0300 Subject: [PATCH 08/10] feat: use remove hook instead of disconnect hook Signed-off-by: Lincoln Wallace --- snap/hooks/disconnect-plug-etc-default-grub | 3 --- snap/hooks/remove | 9 +++++++++ snap/snapcraft.yaml | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) delete mode 100755 snap/hooks/disconnect-plug-etc-default-grub create mode 100755 snap/hooks/remove diff --git a/snap/hooks/disconnect-plug-etc-default-grub b/snap/hooks/disconnect-plug-etc-default-grub deleted file mode 100755 index ed8ead07..00000000 --- a/snap/hooks/disconnect-plug-etc-default-grub +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -eu - -rm -f /etc/default/grub.d/60_rt-conf.cfg diff --git a/snap/hooks/remove b/snap/hooks/remove new file mode 100755 index 00000000..457e8b55 --- /dev/null +++ b/snap/hooks/remove @@ -0,0 +1,9 @@ +#!/bin/bash -eu + +tag="snap.$SNAP_INSTANCE_NAME.hook.refresh" # matching what snapd sets + +if snapctl is-connected etc-default-grub; then + rm -f /etc/default/grub.d/60_rt-conf.cfg +else + logger --stderr --priority error --tag=$tag "The 'etc-default-grub' plug is not connected. Please manually remove the configuration file at /etc/default/grub.d/60_rt-conf.cfg." +fi diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index c5698fa2..4d584b12 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -38,7 +38,7 @@ plugs: - /etc/default/grub hooks: - disconnect-plug-etc-default-grub: + remove: plugs: - etc-default-grub From 491cfa1a2cc40be62898d0d8384fb9f7eca2b946 Mon Sep 17 00:00:00 2001 From: Lincoln Wallace Date: Tue, 16 Sep 2025 10:30:42 -0300 Subject: [PATCH 09/10] feat: remove grub drop-in file in remove hook and on disconnect hook - create environment variable to track grub drop-in file location Signed-off-by: Lincoln Wallace --- snap/hooks/disconnect-plug-etc-default-grub | 3 +++ snap/hooks/remove | 9 ++------- snap/snapcraft.yaml | 1 + 3 files changed, 6 insertions(+), 7 deletions(-) create mode 100644 snap/hooks/disconnect-plug-etc-default-grub diff --git a/snap/hooks/disconnect-plug-etc-default-grub b/snap/hooks/disconnect-plug-etc-default-grub new file mode 100644 index 00000000..249197ad --- /dev/null +++ b/snap/hooks/disconnect-plug-etc-default-grub @@ -0,0 +1,3 @@ +#!/bin/bash -eu + +rm -f $GRUB_DROPIN_FILE diff --git a/snap/hooks/remove b/snap/hooks/remove index 457e8b55..ec4360b3 100755 --- a/snap/hooks/remove +++ b/snap/hooks/remove @@ -1,9 +1,4 @@ #!/bin/bash -eu -tag="snap.$SNAP_INSTANCE_NAME.hook.refresh" # matching what snapd sets - -if snapctl is-connected etc-default-grub; then - rm -f /etc/default/grub.d/60_rt-conf.cfg -else - logger --stderr --priority error --tag=$tag "The 'etc-default-grub' plug is not connected. Please manually remove the configuration file at /etc/default/grub.d/60_rt-conf.cfg." -fi +# Remove the grub drop-in file if it exists +rm -f $GRUB_DROPIN_FILE diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 4d584b12..6c2e99cb 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -11,6 +11,7 @@ confinement: strict environment: DEFAULT_CONFIG_FILE: $SNAP_COMMON/config.yaml + GRUB_DROPIN_FILE: /etc/default/grub.d/60_rt-conf.cfg parts: local: From 4276d0614ced3ce63db737f2bae154f2521bb03c Mon Sep 17 00:00:00 2001 From: Lincoln Wallace Date: Tue, 16 Sep 2025 11:09:21 -0300 Subject: [PATCH 10/10] feat: use env var for grub drop in file and update tests Signed-off-by: Lincoln Wallace --- cmd/rt-conf/main.go | 7 ------- src/kcmd/grub.go | 5 +++++ src/kcmd/grub_test.go | 43 ++++++++++++++++++++++++++++++++++++++ src/model/kcmdline_test.go | 4 ++++ 4 files changed, 52 insertions(+), 7 deletions(-) diff --git a/cmd/rt-conf/main.go b/cmd/rt-conf/main.go index d8e89f3f..8e95de25 100644 --- a/cmd/rt-conf/main.go +++ b/cmd/rt-conf/main.go @@ -37,9 +37,6 @@ func run(args []string) error { configPath := flags.String("file", envConfigFile, "Path to the configuration file") - grubCfgPath := flags.String("grub-custom-file", - "/etc/default/grub.d/60_rt-conf.cfg", - "Path to the output drop-in grub configuration file, relevant only for GRUB bootloader") verbose := flags.Bool("verbose", verboseDefaultCfg, "Verbose mode, prints more information to the console") @@ -73,10 +70,6 @@ func run(args []string) error { } } - conf.GrubCfg = model.Grub{ - GrubDropInFile: *grubCfgPath, - } - if msgs, err := kcmd.ProcessKcmdArgs(&conf); err != nil { return fmt.Errorf("failed to process kernel cmdline args: %v", err) } else { diff --git a/src/kcmd/grub.go b/src/kcmd/grub.go index f6860fbe..cb719784 100644 --- a/src/kcmd/grub.go +++ b/src/kcmd/grub.go @@ -15,6 +15,11 @@ func UpdateGrub(cfg *model.InternalConfig) ([]string, error) { if len(cfg.Data.KernelCmdline.Parameters) == 0 { return nil, fmt.Errorf("no parameters to inject") } + grubDropInFilePath, exists := os.LookupEnv("GRUB_DROPIN_FILE") + if !exists { + return nil, fmt.Errorf("GRUB_DROPIN_FILE environment variable not set") + } + cfg.GrubCfg.GrubDropInFile = grubDropInFilePath if err := cfg.Data.KernelCmdline.HasDuplicates(); err != nil { return nil, fmt.Errorf("invalid new parameters: %v", err) diff --git a/src/kcmd/grub_test.go b/src/kcmd/grub_test.go index 93089089..3f203fa8 100644 --- a/src/kcmd/grub_test.go +++ b/src/kcmd/grub_test.go @@ -67,11 +67,15 @@ func TestUpdateGrub(t *testing.T) { kcmd model.KernelCmdline expectErr string expectOutput string + envVars map[string]string }{ { name: "No params to inject", kcmd: model.KernelCmdline{}, expectErr: "no parameters to inject", + envVars: map[string]string{ + "GRUB_DROPIN_FILE": "/tmp/60-rt-conf.cfg", + }, }, { name: "detected bootloader GRUB", @@ -81,6 +85,9 @@ func TestUpdateGrub(t *testing.T) { }, }, expectOutput: "Detected bootloader: GRUB", + envVars: map[string]string{ + "GRUB_DROPIN_FILE": "/tmp/60-rt-conf.cfg", + }, }, { name: "ProcessFile fails", @@ -90,6 +97,9 @@ func TestUpdateGrub(t *testing.T) { }, }, expectErr: "error updating", + envVars: map[string]string{ + "GRUB_DROPIN_FILE": "/tmp/60-rt-conf.cfg", + }, }, { name: "Success", @@ -100,6 +110,9 @@ func TestUpdateGrub(t *testing.T) { }, }, expectOutput: "Detected bootloader: GRUB", + envVars: map[string]string{ + "GRUB_DROPIN_FILE": "/tmp/60-rt-conf.cfg", + }, }, { name: "duplicate parameters with different values", @@ -111,6 +124,19 @@ func TestUpdateGrub(t *testing.T) { }, }, expectErr: "invalid new parameters", + envVars: map[string]string{ + "GRUB_DROPIN_FILE": "/tmp/60-rt-conf.cfg", + }, + }, + { + name: "GRUB_DROPIN_FILE not set", + kcmd: model.KernelCmdline{ + Parameters: []string{ + "isolcpus=1-3", + "nohz=on", + }, + }, + expectErr: "environment variable not set", }, } @@ -119,6 +145,23 @@ func TestUpdateGrub(t *testing.T) { tmpDir := t.TempDir() cfgPath := filepath.Join(tmpDir, "rt-conf.cfg") + if tc.envVars != nil { + for tck, v := range tc.envVars { + if err := os.Setenv(tck, v); err != nil { + t.Fatalf("failed to set env var %s: %v", tck, err) + } + } + } + + // Unset env vars after the test + t.Cleanup(func() { + for tck := range tc.envVars { + if err := os.Unsetenv(tck); err != nil { + t.Fatalf("failed to unset env var %s: %v", tck, err) + } + } + }) + conf := &model.InternalConfig{ Data: model.Config{ KernelCmdline: tc.kcmd, diff --git a/src/model/kcmdline_test.go b/src/model/kcmdline_test.go index de5d277a..98b7df36 100644 --- a/src/model/kcmdline_test.go +++ b/src/model/kcmdline_test.go @@ -54,6 +54,10 @@ func mainLogic(t *testing.T, c TestCase, i int) (string, error) { t.Fatalf("failed to write grub: %v", err) } + if err := os.Setenv("GRUB_DROPIN_FILE", tempCustomCfgPath); err != nil { + t.Fatalf("failed to set env var GRUB_DROPIN_FILE: %v", err) + } + t.Cleanup(func() { if err := os.Remove(tempConfigPath); err != nil { t.Fatal(err)