From 0a2ade7a416c7cd843b30eed0d9ff24034dca432 Mon Sep 17 00:00:00 2001 From: HarshwardhanPatil07 Date: Wed, 13 May 2026 17:38:54 +0530 Subject: [PATCH 1/5] Move OCP-88729 USBGuard test to mco_kernel.go and add extension RPM verification Address review feedback: move test from mco_security.go to mco_kernel.go since it tests extensions, and add verification that the usbguard RPM is installed on all worker nodes before checking the service is enabled. Signed-off-by: HarshwardhanPatil07 --- test/extended-priv/mco_kernel.go | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/extended-priv/mco_kernel.go b/test/extended-priv/mco_kernel.go index 93b9d98d81..b17e110880 100644 --- a/test/extended-priv/mco_kernel.go +++ b/test/extended-priv/mco_kernel.go @@ -332,4 +332,39 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati "The kernel arguments are not the expected ones") logger.Infof("OK!\n") }) + + g.It("[PolarionID:88729] Verify USBGuard extension can be installed and enabled via MachineConfig on worker nodes [Disruptive]", func() { + testID := GetCurrentTestPolarionIDNumber() + mcp := GetCompactCompatiblePool(oc.AsAdmin()) + + exutil.By("Create a MachineConfig to install the usbguard extension on worker nodes") + mcExt := NewMachineConfig(oc.AsAdmin(), fmt.Sprintf("test-%s-ext", testID), mcp.GetName()). + SetMCOTemplate("change-worker-extension-usbguard.yaml") + defer mcExt.DeleteWithWait() + mcExt.create() + logger.Infof("OK!\n") + + exutil.By("Create a MachineConfig to enable the usbguard systemd unit on worker nodes") + mcEnableName := fmt.Sprintf("test-%s-enable", testID) + mcEnable := NewMachineConfig(oc.AsAdmin(), mcEnableName, mcp.GetName()) + mcEnable.SetParams(fmt.Sprintf(`UNITS=[{"enabled": true, "name": "usbguard.service"}]`)) + defer mcEnable.DeleteWithWait() + mcEnable.create() + logger.Infof("OK!\n") + + exutil.By("Verify usbguard extension is installed on all worker nodes") + nodes := mcp.GetSortedNodesOrFail() + for _, node := range nodes { + o.Expect(node.RpmIsInstalled("usbguard")).To(o.BeTrue(), + "usbguard rpm should be installed on node %s", node.GetName()) + } + logger.Infof("OK!\n") + + exutil.By("Verify usbguard.service is enabled on all worker nodes") + for _, node := range nodes { + o.Expect(node.IsUnitEnabled("usbguard")).To(o.BeTrue(), + "usbguard.service should be enabled on node %s", node.GetName()) + } + logger.Infof("OK!\n") + }) }) From 7222f9d145643fa852c2ba79c6942333d9d8ecdc Mon Sep 17 00:00:00 2001 From: HarshwardhanPatil07 Date: Thu, 14 May 2026 12:37:05 +0530 Subject: [PATCH 2/5] OCP-88729: Optimize cleanup by deleting both MachineConfigs in one shot Delete both the extension and enable MachineConfigs in a single oc delete command during cleanup, triggering one pool rollout instead of two. Also revert unintended whitespace change in mco_security.go. Signed-off-by: HarshwardhanPatil07 --- test/extended-priv/mco_kernel.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/extended-priv/mco_kernel.go b/test/extended-priv/mco_kernel.go index b17e110880..65bb9e203c 100644 --- a/test/extended-priv/mco_kernel.go +++ b/test/extended-priv/mco_kernel.go @@ -345,10 +345,13 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati logger.Infof("OK!\n") exutil.By("Create a MachineConfig to enable the usbguard systemd unit on worker nodes") - mcEnableName := fmt.Sprintf("test-%s-enable", testID) - mcEnable := NewMachineConfig(oc.AsAdmin(), mcEnableName, mcp.GetName()) + mcEnable := NewMachineConfig(oc.AsAdmin(), fmt.Sprintf("test-%s-enable", testID), mcp.GetName()) mcEnable.SetParams(fmt.Sprintf(`UNITS=[{"enabled": true, "name": "usbguard.service"}]`)) - defer mcEnable.DeleteWithWait() + defer func() { + exutil.By("Cleanup: delete both MachineConfigs in one shot and wait for a single pool rollout") + oc.AsAdmin().WithoutNamespace().Run("delete").Args("mc", mcEnable.GetName(), mcExt.GetName(), "--ignore-not-found=true").Execute() + mcp.waitForComplete() + }() mcEnable.create() logger.Infof("OK!\n") From 2f91e47aa16220ac9faca8b3a4199c5ba1f7a58e Mon Sep 17 00:00:00 2001 From: HarshwardhanPatil07 Date: Mon, 25 May 2026 15:16:48 +0530 Subject: [PATCH 3/5] OCP-88729: Use mc.DeleteWithWait() for cleanup instead of raw oc delete Signed-off-by: HarshwardhanPatil07 --- test/extended-priv/mco_kernel.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/test/extended-priv/mco_kernel.go b/test/extended-priv/mco_kernel.go index 65bb9e203c..a75b5ec299 100644 --- a/test/extended-priv/mco_kernel.go +++ b/test/extended-priv/mco_kernel.go @@ -347,11 +347,7 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati exutil.By("Create a MachineConfig to enable the usbguard systemd unit on worker nodes") mcEnable := NewMachineConfig(oc.AsAdmin(), fmt.Sprintf("test-%s-enable", testID), mcp.GetName()) mcEnable.SetParams(fmt.Sprintf(`UNITS=[{"enabled": true, "name": "usbguard.service"}]`)) - defer func() { - exutil.By("Cleanup: delete both MachineConfigs in one shot and wait for a single pool rollout") - oc.AsAdmin().WithoutNamespace().Run("delete").Args("mc", mcEnable.GetName(), mcExt.GetName(), "--ignore-not-found=true").Execute() - mcp.waitForComplete() - }() + defer mcEnable.DeleteWithWait() mcEnable.create() logger.Infof("OK!\n") From 659340678935d69e870200b3468129136e991e94 Mon Sep 17 00:00:00 2001 From: HarshwardhanPatil07 Date: Thu, 28 May 2026 12:11:42 +0530 Subject: [PATCH 4/5] OCP-88729: Only wait on last MachineConfig deletion to avoid double-waiting Signed-off-by: HarshwardhanPatil07 --- test/extended-priv/mco_kernel.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/extended-priv/mco_kernel.go b/test/extended-priv/mco_kernel.go index a75b5ec299..7bcc5a0cdb 100644 --- a/test/extended-priv/mco_kernel.go +++ b/test/extended-priv/mco_kernel.go @@ -347,7 +347,7 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati exutil.By("Create a MachineConfig to enable the usbguard systemd unit on worker nodes") mcEnable := NewMachineConfig(oc.AsAdmin(), fmt.Sprintf("test-%s-enable", testID), mcp.GetName()) mcEnable.SetParams(fmt.Sprintf(`UNITS=[{"enabled": true, "name": "usbguard.service"}]`)) - defer mcEnable.DeleteWithWait() + defer mcEnable.Delete() mcEnable.create() logger.Infof("OK!\n") From 4dc05f6fe045f8e0ed49148ba38af6663639e50e Mon Sep 17 00:00:00 2001 From: HarshwardhanPatil07 Date: Fri, 5 Jun 2026 13:55:40 +0530 Subject: [PATCH 5/5] OCPBUGS-78524: Create mco_extensions.go suite with USBGuard, install all extensions, and invalid extensions tests Move extension-related tests into a dedicated mco_extensions.go suite: - OCP-88729: USBGuard extension install and enable (from mco_kernel.go) - OCP-56131/OCP-77354: Install all extensions (from mco_machineconfigpool.go) - OCP-56123: Invalid extensions degrade MCP (from mco_machineconfigpool.go) Signed-off-by: HarshwardhanPatil07 --- test/extended-priv/mco_extensions.go | 147 ++++++++++++++++++++ test/extended-priv/mco_kernel.go | 34 ----- test/extended-priv/mco_machineconfigpool.go | 93 ------------- 3 files changed, 147 insertions(+), 127 deletions(-) create mode 100644 test/extended-priv/mco_extensions.go diff --git a/test/extended-priv/mco_extensions.go b/test/extended-priv/mco_extensions.go new file mode 100644 index 0000000000..12aaaa4bb5 --- /dev/null +++ b/test/extended-priv/mco_extensions.go @@ -0,0 +1,147 @@ +package extended + +import ( + "fmt" + "regexp" + "strings" + + g "github.com/onsi/ginkgo/v2" + o "github.com/onsi/gomega" + exutil "github.com/openshift/machine-config-operator/test/extended-priv/util" + logger "github.com/openshift/machine-config-operator/test/extended-priv/util/logext" +) + +var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longduration][Serial][Disruptive] MCO extensions", func() { + defer g.GinkgoRecover() + + var oc = exutil.NewCLI("mco-extensions", exutil.KubeConfigPath()) + + g.JustBeforeEach(func() { + PreChecks(oc) + }) + + g.It("[PolarionID:88729] Verify USBGuard extension can be installed and enabled via MachineConfig on worker nodes [Disruptive]", func() { + testID := GetCurrentTestPolarionIDNumber() + mcp := GetCompactCompatiblePool(oc.AsAdmin()) + + exutil.By("Create a MachineConfig to install the usbguard extension on worker nodes") + mcExt := NewMachineConfig(oc.AsAdmin(), fmt.Sprintf("test-%s-ext", testID), mcp.GetName()). + SetMCOTemplate("change-worker-extension-usbguard.yaml") + defer mcExt.DeleteWithWait() + mcExt.create() + logger.Infof("OK!\n") + + exutil.By("Create a MachineConfig to enable the usbguard systemd unit on worker nodes") + mcEnable := NewMachineConfig(oc.AsAdmin(), fmt.Sprintf("test-%s-enable", testID), mcp.GetName()) + mcEnable.SetParams(fmt.Sprintf(`UNITS=[{"enabled": true, "name": "usbguard.service"}]`)) + defer mcEnable.Delete() + mcEnable.create() + logger.Infof("OK!\n") + + exutil.By("Verify usbguard extension is installed on all worker nodes") + nodes := mcp.GetSortedNodesOrFail() + for _, node := range nodes { + o.Expect(node.RpmIsInstalled("usbguard")).To(o.BeTrue(), + "usbguard rpm should be installed on node %s", node.GetName()) + } + logger.Infof("OK!\n") + + exutil.By("Verify usbguard.service is enabled on all worker nodes") + for _, node := range nodes { + o.Expect(node.IsUnitEnabled("usbguard")).To(o.BeTrue(), + "usbguard.service should be enabled on node %s", node.GetName()) + } + logger.Infof("OK!\n") + }) + + /* Map of extensions and packages for each extension + { + "ipsec": {"NetworkManager-libreswan", "libreswan"}, + "usbguard": {"usbguard"}, + "kerberos": {"krb5-workstation", "libkadm5"}, + "kernel-devel": {"kernel-devel", "kernel-headers"}, + "sandboxed-containers": {"kata-containers"}, + "sysstat": {"sysstat"}, + } */ + g.It("[PolarionID:56131][PolarionID:77354][OTP][LEVEL0] Install all extensions", func() { + var ( + coreOSMcp = GetCoreOsCompatiblePool(oc.AsAdmin()) + node = coreOSMcp.GetCoreOsNodesOrFail()[0] + + query = `mcd_local_unsupported_packages{node="` + node.GetName() + `"}` + valueJSONPath = `data.result.0.value.1` + + mcName = fmt.Sprintf("mco-tc-%s-all-extensions", GetCurrentTestPolarionIDNumber()) + + applicableExtensions, expectedRpmInstalledPackages = GetAllApplicableExtensionsToMCPOrFail(coreOSMcp) + + skipDrainChecks = IsSNO(oc.AsAdmin()) // SNO clusters should NOT drain the nodes before rebooting them. The validator is not prepared for that. + behaviourValidatorApply = UpdateBehaviourValidator{ + SkipDrainNodesValidation: skipDrainChecks, + Checkers: []Checker{ + CommandOutputChecker{ + Command: append([]string{"rpm", "-q"}, expectedRpmInstalledPackages...), + Matcher: o.MatchRegexp("(?s)" + strings.Join(expectedRpmInstalledPackages, ".*")), + ErrorMsg: "Extensions were not properly installed", + Desc: "Checking that all available extensions were properly installed", + }, + }, + } + ) + + coreOSMcp.SetWaitingTimeForExtensionsChange() + behaviourValidatorApply.Initialize(coreOSMcp, nil) + + exutil.By("Create a MC to install all available extensions") + mc := NewMachineConfig(oc.AsAdmin(), mcName, coreOSMcp.GetName()) + mc.parameters = []string{fmt.Sprintf(`EXTENSIONS=%s`, string(MarshalOrFail(applicableExtensions)))} + mc.skipWaitForMcp = true + + defer mc.DeleteWithWait() + mc.create() + logger.Infof("OK!\n") + + behaviourValidatorApply.Validate() + + exutil.By("Check that no unsupported packages are reported") + monitor, err := exutil.NewMonitor(oc.AsAdmin()) + o.Expect(err).NotTo(o.HaveOccurred(), "Error getting the monitor to query the metricts") + + o.Eventually(monitor.SimpleQuery, "10s", "2s").WithArguments(query).Should(HavePathWithValue(valueJSONPath, o.Equal("0")), + "There are reported unsupported packages in %s", node) + logger.Infof("OK!\n") + + CheckExtensions(node, applicableExtensions) + + exutil.By("Delete the MC") + mc.DeleteWithWait() + logger.Infof("OK!\n") + + exutil.By("Verify that extension packages where uninstalled after MC deletion") + for _, pkg := range expectedRpmInstalledPackages { + o.Expect(node.RpmIsInstalled(pkg)).To( + o.BeFalse(), + "Package %s should be uninstalled when we remove the extensions MC", pkg) + } + logger.Infof("OK!\n") + }) + + g.It("[PolarionID:56123][OTP] Invalid extensions should degrade the machine config pool", func() { + var ( + validExtension = "usbguard" + invalidExtension = "zsh" + mcName = "mco-tc-56123-invalid-extension" + mcp = GetCompactCompatiblePool(oc) + + expectedRDMessage = regexp.QuoteMeta(fmt.Sprintf("invalid extensions found: [%s]", invalidExtension)) // quotemeta to scape regex characters + expectedRDReason = "" + ) + + exutil.By("Create a MC with invalid extensions") + mc := NewMachineConfig(oc.AsAdmin(), mcName, mcp.GetName()) + mc.parameters = []string{fmt.Sprintf(`EXTENSIONS=["%s", "%s"]`, validExtension, invalidExtension)} + mc.skipWaitForMcp = true + + validateMcpRenderDegraded(mc, mcp, expectedRDMessage, expectedRDReason) + }) +}) diff --git a/test/extended-priv/mco_kernel.go b/test/extended-priv/mco_kernel.go index 7bcc5a0cdb..93b9d98d81 100644 --- a/test/extended-priv/mco_kernel.go +++ b/test/extended-priv/mco_kernel.go @@ -332,38 +332,4 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati "The kernel arguments are not the expected ones") logger.Infof("OK!\n") }) - - g.It("[PolarionID:88729] Verify USBGuard extension can be installed and enabled via MachineConfig on worker nodes [Disruptive]", func() { - testID := GetCurrentTestPolarionIDNumber() - mcp := GetCompactCompatiblePool(oc.AsAdmin()) - - exutil.By("Create a MachineConfig to install the usbguard extension on worker nodes") - mcExt := NewMachineConfig(oc.AsAdmin(), fmt.Sprintf("test-%s-ext", testID), mcp.GetName()). - SetMCOTemplate("change-worker-extension-usbguard.yaml") - defer mcExt.DeleteWithWait() - mcExt.create() - logger.Infof("OK!\n") - - exutil.By("Create a MachineConfig to enable the usbguard systemd unit on worker nodes") - mcEnable := NewMachineConfig(oc.AsAdmin(), fmt.Sprintf("test-%s-enable", testID), mcp.GetName()) - mcEnable.SetParams(fmt.Sprintf(`UNITS=[{"enabled": true, "name": "usbguard.service"}]`)) - defer mcEnable.Delete() - mcEnable.create() - logger.Infof("OK!\n") - - exutil.By("Verify usbguard extension is installed on all worker nodes") - nodes := mcp.GetSortedNodesOrFail() - for _, node := range nodes { - o.Expect(node.RpmIsInstalled("usbguard")).To(o.BeTrue(), - "usbguard rpm should be installed on node %s", node.GetName()) - } - logger.Infof("OK!\n") - - exutil.By("Verify usbguard.service is enabled on all worker nodes") - for _, node := range nodes { - o.Expect(node.IsUnitEnabled("usbguard")).To(o.BeTrue(), - "usbguard.service should be enabled on node %s", node.GetName()) - } - logger.Infof("OK!\n") - }) }) diff --git a/test/extended-priv/mco_machineconfigpool.go b/test/extended-priv/mco_machineconfigpool.go index 289caa51f9..01b10deaac 100644 --- a/test/extended-priv/mco_machineconfigpool.go +++ b/test/extended-priv/mco_machineconfigpool.go @@ -2,9 +2,7 @@ package extended import ( "fmt" - "regexp" "strconv" - "strings" logger "github.com/openshift/machine-config-operator/test/extended-priv/util/logext" @@ -103,78 +101,6 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati logger.Infof("OK!\n") }) - /* Map of extensions and packages for each extension - { - "ipsec": {"NetworkManager-libreswan", "libreswan"}, - "usbguard": {"usbguard"}, - "kerberos": {"krb5-workstation", "libkadm5"}, - "kernel-devel": {"kernel-devel", "kernel-headers"}, - "sandboxed-containers": {"kata-containers"}, - "sysstat": {"sysstat"}, - } */ - g.It("[PolarionID:56131][PolarionID:77354][OTP][LEVEL0] Install all extensions", func() { - var ( - coreOSMcp = GetCoreOsCompatiblePool(oc.AsAdmin()) - node = coreOSMcp.GetCoreOsNodesOrFail()[0] - - query = `mcd_local_unsupported_packages{node="` + node.GetName() + `"}` - valueJSONPath = `data.result.0.value.1` - - mcName = fmt.Sprintf("mco-tc-%s-all-extensions", GetCurrentTestPolarionIDNumber()) - - applicableExtensions, expectedRpmInstalledPackages = GetAllApplicableExtensionsToMCPOrFail(coreOSMcp) - - skipDrainChecks = IsSNO(oc.AsAdmin()) // SNO clusters should NOT drain the nodes before rebooting them. The validator is not prepared for that. - behaviourValidatorApply = UpdateBehaviourValidator{ - SkipDrainNodesValidation: skipDrainChecks, - Checkers: []Checker{ - CommandOutputChecker{ - Command: append([]string{"rpm", "-q"}, expectedRpmInstalledPackages...), - Matcher: o.MatchRegexp("(?s)" + strings.Join(expectedRpmInstalledPackages, ".*")), - ErrorMsg: "Extensions were not properly installed", - Desc: "Checking that all available extensions were properly installed", - }, - }, - } - ) - - coreOSMcp.SetWaitingTimeForExtensionsChange() - behaviourValidatorApply.Initialize(coreOSMcp, nil) - - exutil.By("Create a MC to install all available extensions") - mc := NewMachineConfig(oc.AsAdmin(), mcName, coreOSMcp.GetName()) - mc.parameters = []string{fmt.Sprintf(`EXTENSIONS=%s`, string(MarshalOrFail(applicableExtensions)))} - mc.skipWaitForMcp = true - - defer mc.DeleteWithWait() - mc.create() - logger.Infof("OK!\n") - - behaviourValidatorApply.Validate() - - exutil.By("Check that no unsupported packages are reported") - monitor, err := exutil.NewMonitor(oc.AsAdmin()) - o.Expect(err).NotTo(o.HaveOccurred(), "Error getting the monitor to query the metricts") - - o.Eventually(monitor.SimpleQuery, "10s", "2s").WithArguments(query).Should(HavePathWithValue(valueJSONPath, o.Equal("0")), - "There are reported unsupported packages in %s", node) - logger.Infof("OK!\n") - - CheckExtensions(node, applicableExtensions) - - exutil.By("Delete the MC") - mc.DeleteWithWait() - logger.Infof("OK!\n") - - exutil.By("Verify that extension packages where uninstalled after MC deletion") - for _, pkg := range expectedRpmInstalledPackages { - o.Expect(node.RpmIsInstalled(pkg)).To( - o.BeFalse(), - "Package %s should be uninstalled when we remove the extensions MC", pkg) - } - logger.Infof("OK!\n") - }) - g.It("[PolarionID:42390][PolarionID:45318][OTP] add machine config without ignition version. Block the Machine-Config-Operator upgrade rollout if any of the pools are Degraded", func() { createMcAndVerifyIgnitionVersion(oc, "empty ign version", "change-worker-ign-version-to-empty", "") }) @@ -269,25 +195,6 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati }) - g.It("[PolarionID:56123][OTP] Invalid extensions should degrade the machine config pool", func() { - var ( - validExtension = "usbguard" - invalidExtension = "zsh" - mcName = "mco-tc-56123-invalid-extension" - mcp = GetCompactCompatiblePool(oc) - - expectedRDMessage = regexp.QuoteMeta(fmt.Sprintf("invalid extensions found: [%s]", invalidExtension)) // quotemeta to scape regex characters - expectedRDReason = "" - ) - - exutil.By("Create a MC with invalid extensions") - mc := NewMachineConfig(oc.AsAdmin(), mcName, mcp.GetName()) - mc.parameters = []string{fmt.Sprintf(`EXTENSIONS=["%s", "%s"]`, validExtension, invalidExtension)} - mc.skipWaitForMcp = true - - validateMcpRenderDegraded(mc, mcp, expectedRDMessage, expectedRDReason) - }) - g.It("[PolarionID:70125][OTP] Test patch annotation way of updating a paused pool", func() { var (