diff --git a/test/extended-priv/machineosconfig.go b/test/extended-priv/machineosconfig.go index 2c611f6ff6..9bd9b9aa49 100644 --- a/test/extended-priv/machineosconfig.go +++ b/test/extended-priv/machineosconfig.go @@ -38,17 +38,83 @@ func NewMachineOSConfigList(oc *exutil.CLI) *MachineOSConfigList { return &MachineOSConfigList{*NewResourceList(oc, "machineosconfig")} } -// CreateMachineOSConfig creates a MOSC resource using the information provided in the arguments +// MOSCCreateOption configures optional behavior for CreateMOSC. +type MOSCCreateOption func(*moscCreateConfig) + +type moscCreateConfig struct { + namespace string + containerFiles []ContainerFile + defaultPullSecret bool + expireImage bool + useInternal bool + useExternal bool +} + +// WithContainerFiles configures the MOSC to use the given containerfiles. +func WithContainerFiles(files []ContainerFile) MOSCCreateOption { + return func(c *moscCreateConfig) { c.containerFiles = files } +} + +// WithDefaultPullSecret configures the MOSC to inherit the global pull secret instead of specifying one. +func WithDefaultPullSecret() MOSCCreateOption { + return func(c *moscCreateConfig) { c.defaultPullSecret = true } +} + +// WithNoImageExpiration configures the MOSC to not add expiration labels to images in external registries. +func WithNoImageExpiration() MOSCCreateOption { + return func(c *moscCreateConfig) { c.expireImage = false } +} + +// WithMOSCNamespace configures a custom namespace for storing the OS image (defaults to MachineConfigNamespace). +func WithMOSCNamespace(ns string) MOSCCreateOption { + return func(c *moscCreateConfig) { c.namespace = ns } +} + +// WithMOSCInternalRegistry forces the MOSC to use the cluster's internal registry. +func WithMOSCInternalRegistry() MOSCCreateOption { + return func(c *moscCreateConfig) { c.useInternal = true } +} + +// WithMOSCExternalRegistry forces the MOSC to use the external quay registry. +func WithMOSCExternalRegistry() MOSCCreateOption { + return func(c *moscCreateConfig) { c.useExternal = true } +} + +// CreateMOSC creates a MachineOSConfig resource using auto-detected or explicitly configured registry. +// By default it auto-selects internal registry if available, otherwise external, with image expiration enabled +// and an explicit pull secret configured. +func CreateMOSC(oc *exutil.CLI, name, pool string, opts ...MOSCCreateOption) (*MachineOSConfig, error) { + cfg := &moscCreateConfig{ + namespace: MachineConfigNamespace, + expireImage: true, + } + for _, o := range opts { + o(cfg) + } + + if cfg.useInternal { + return createMOSCUsingInternalRegistry(oc, cfg.namespace, name, pool, cfg.containerFiles, cfg.defaultPullSecret) + } + if cfg.useExternal { + return createMOSCUsingExternalRegistry(oc, name, pool, cfg.containerFiles, cfg.defaultPullSecret, cfg.expireImage) + } + + if CanUseInternalRegistryToStoreOSImage(oc) { + return createMOSCUsingInternalRegistry(oc, cfg.namespace, name, pool, cfg.containerFiles, cfg.defaultPullSecret) + } + return createMOSCUsingExternalRegistry(oc, name, pool, cfg.containerFiles, cfg.defaultPullSecret, cfg.expireImage) +} + +// CreateMachineOSConfig creates a MOSC resource with explicit pull/push secrets and push spec. +// Use this only when you need full control over the MOSC parameters (e.g. testing misconfigured MOSCs). func CreateMachineOSConfig(oc *exutil.CLI, moscAndMcpName, baseImagePullSecret, renderedImagePushSecret, pushSpec string, containerFile []ContainerFile) (*MachineOSConfig, error) { return createMachineOSConfig(oc, moscAndMcpName, &baseImagePullSecret, renderedImagePushSecret, pushSpec, containerFile) } -// CreateMachineOSConfigWithDefaultBasImagePullSecret creates a MOSC resource using the information provided in the arguments, it does not define the image pull secret -func CreateMachineOSConfigWithDefaultBasImagePullSecret(oc *exutil.CLI, moscAndMcpName, renderedImagePushSecret, pushSpec string, containerFile []ContainerFile) (*MachineOSConfig, error) { +func createMachineOSConfigWithDefaultPullSecret(oc *exutil.CLI, moscAndMcpName, renderedImagePushSecret, pushSpec string, containerFile []ContainerFile) (*MachineOSConfig, error) { return createMachineOSConfig(oc, moscAndMcpName, nil, renderedImagePushSecret, pushSpec, containerFile) } -// createMachineOSConfig creates a MOSC resource using the information provided in the arguments func createMachineOSConfig(oc *exutil.CLI, moscAndMcpName string, baseImagePullSecret *string, renderedImagePushSecret, pushSpec string, containerFile []ContainerFile) (*MachineOSConfig, error) { var ( containerFilesString = "[]" @@ -103,9 +169,7 @@ func CopySecretToMCONamespace(secret *Secret, newName string) (*Secret, error) { return &Secret{Resource: *mcoResource}, nil } -func CreateMachineOSConfigUsingInternalRegistry(oc *exutil.CLI, namespace, name, pool string, containerFile []ContainerFile, defaultPullSecret bool) (*MachineOSConfig, error) { - - // We use the builder SA secret in the namespace to push the images to the internal registry +func createMOSCUsingInternalRegistry(oc *exutil.CLI, namespace, name, pool string, containerFile []ContainerFile, defaultPullSecret bool) (*MachineOSConfig, error) { renderedImagePushSecret, err := CreateInternalRegistrySecretFromSA(oc, "builder", namespace, "cloned-push-secret"+exutil.GetRandomString(), MachineConfigNamespace) if err != nil { return NewMachineOSConfig(oc, name), err @@ -114,10 +178,7 @@ func CreateMachineOSConfigUsingInternalRegistry(oc *exutil.CLI, namespace, name, return NewMachineOSConfig(oc, name), fmt.Errorf("rendered image push secret does not exist: %s", renderedImagePushSecret) } - if namespace != MachineConfigNamespace { // If the secret is not in MCO, we copy it there - - // TODO: HERE WE NEED TO ADD THE NAMESPACE PULL SECRET TO THE CLUSTER'S PULL-SECRET SO THAT WE CAN PULL THE RESULTING IMAGE STORED IN A DIFFERENT NAMESPACE THAN MCO - // We use the default SA secret in MCO to pull the current image from the internal registry + if namespace != MachineConfigNamespace { namespacedPullSecret, err := CreateInternalRegistrySecretFromSA(oc, "default", namespace, "cloned-currentpull-secret"+exutil.GetRandomString(), namespace) if err != nil { return NewMachineOSConfig(oc, name), err @@ -151,11 +212,9 @@ func CreateMachineOSConfigUsingInternalRegistry(oc *exutil.CLI, namespace, name, NewMachineConfigPoolList(oc.AsAdmin()).waitForComplete() } - // We use a push spec stored in the internal registry in the MCO namespace. We use a different image for every pool pushSpec := fmt.Sprintf("%s/%s/ocb-%s-image:latest", InternalRegistrySvcURL, namespace, pool) if !defaultPullSecret { - // We use a copy of the cluster's pull secret to pull the images pullSecret := NewSecret(oc.AsAdmin(), "openshift-config", "pull-secret") baseImagePullSecret, err := CopySecretToMCONamespace(pullSecret, "cloned-basepull-secret-"+exutil.GetRandomString()) if err != nil { @@ -164,15 +223,11 @@ func CreateMachineOSConfigUsingInternalRegistry(oc *exutil.CLI, namespace, name, return CreateMachineOSConfig(oc, name, baseImagePullSecret.GetName(), renderedImagePushSecret.GetName(), pushSpec, containerFile) } - return CreateMachineOSConfigWithDefaultBasImagePullSecret(oc, name, renderedImagePushSecret.GetName(), pushSpec, containerFile) + return createMachineOSConfigWithDefaultPullSecret(oc, name, renderedImagePushSecret.GetName(), pushSpec, containerFile) } -// CreateMachineOSConfigUsingExternalRegistry creates a new MOSC resource using the mcoqe external registry. The credentials to pull and push images in the mcoqe repo should be previously added to the cluster's pull secret -func CreateMachineOSConfigUsingExternalRegistry(oc *exutil.CLI, name, pool string, containerFile []ContainerFile, defaultPullSecret, expireImage bool) (*MachineOSConfig, error) { - var ( - // We use a copy of the cluster's pull secret to pull the images - pullSecret = NewSecret(oc.AsAdmin(), "openshift-config", "pull-secret") - ) +func createMOSCUsingExternalRegistry(oc *exutil.CLI, name, pool string, containerFile []ContainerFile, defaultPullSecret, expireImage bool) (*MachineOSConfig, error) { + pullSecret := NewSecret(oc.AsAdmin(), "openshift-config", "pull-secret") copyPullSecret, err := CopySecretToMCONamespace(pullSecret, "cloned-pull-secret-"+exutil.GetRandomString()) if err != nil { return NewMachineOSConfig(oc, name), err @@ -183,10 +238,8 @@ func CreateMachineOSConfigUsingExternalRegistry(oc *exutil.CLI, name, pool strin return NewMachineOSConfig(oc, name), err } - // We use a push spec stored in the internal registry in the MCO namespace. We use a different image for every pool pushSpec := fmt.Sprintf("%s:ocb-%s-%s", DefaultLayeringQuayRepository, pool, clusterName) - // If we use the external registry we need to add an expiration date label so that the images are automatically cleaned configuredContainerFile := []ContainerFile{} if expireImage { if len(containerFile) == 0 { @@ -201,32 +254,10 @@ func CreateMachineOSConfigUsingExternalRegistry(oc *exutil.CLI, name, pool strin } if defaultPullSecret { - return CreateMachineOSConfigWithDefaultBasImagePullSecret(oc, name, copyPullSecret.GetName(), pushSpec, configuredContainerFile) + return createMachineOSConfigWithDefaultPullSecret(oc, name, copyPullSecret.GetName(), pushSpec, configuredContainerFile) } return CreateMachineOSConfig(oc, name, copyPullSecret.GetName(), copyPullSecret.GetName(), pushSpec, configuredContainerFile) - -} - -// CreateMachineOSConfigUsingExternalOrInternalRegistry creates a MOSC using internal registry if possible, if not possible it will use external registry. It will define the BaseImagePullSecret too -func CreateMachineOSConfigUsingExternalOrInternalRegistry(oc *exutil.CLI, namespace, name, pool string, containerFile []ContainerFile) (*MachineOSConfig, error) { - var ( - // When we create a new MOSC using the external registry we add an expiration label so that they are directly pruned by quay - expireImage = true - // We configure the pull secret in the MOSC resource even if it is only optional - defaultPullSecret = false - ) - return createMachineOSConfigUsingExternalOrInternalRegistry(oc, namespace, name, pool, containerFile, defaultPullSecret, expireImage) -} - -// createMachineOSConfigUsingExternalOrInternalRegistry creates a MOSC using internal registry if possible, if not possible it will use external registry -func createMachineOSConfigUsingExternalOrInternalRegistry(oc *exutil.CLI, namespace, name, pool string, containerFile []ContainerFile, defaultPullSecret, expireImage bool) (*MachineOSConfig, error) { - if CanUseInternalRegistryToStoreOSImage(oc) { - return CreateMachineOSConfigUsingInternalRegistry(oc, namespace, name, pool, containerFile, defaultPullSecret) - } - - return CreateMachineOSConfigUsingExternalRegistry(oc, name, pool, containerFile, defaultPullSecret, expireImage) - } // GetBaseImagePullSecret returns the pull secret configured in this MOSC diff --git a/test/extended-priv/mco_machineconfignode.go b/test/extended-priv/mco_machineconfignode.go index 99f8f1e204..ece575b921 100644 --- a/test/extended-priv/mco_machineconfignode.go +++ b/test/extended-priv/mco_machineconfignode.go @@ -424,7 +424,7 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati ) exutil.By("Configure OCB functionality for the MCP") - mosc, err := CreateMachineOSConfigUsingExternalOrInternalRegistry(oc.AsAdmin(), MachineConfigNamespace, moscName, mcp.GetName(), nil) + mosc, err := CreateMOSC(oc.AsAdmin(), moscName, mcp.GetName()) defer DisableOCL(mosc) o.Expect(err).NotTo(o.HaveOccurred(), "Error creating the MachineOSConfig resource") ValidateSuccessfulMOSC(mosc, nil) diff --git a/test/extended-priv/mco_ocb.go b/test/extended-priv/mco_ocb.go index 79e3c09ef0..aa51b881d8 100644 --- a/test/extended-priv/mco_ocb.go +++ b/test/extended-priv/mco_ocb.go @@ -25,34 +25,10 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/disruptive }) g.It("[PolarionID:83141][OTP] A valid MachineOSConfig leads to a successful MachineOSBuild and cleanup of its associated resources", func() { - var ( - mcpAndMoscName = "infra" - ) - - exutil.By("Create custom infra MCP") - // We add no workers to the infra pool, it is not necessary - infraMcp, err := CreateCustomMCP(oc.AsAdmin(), mcpAndMoscName, 0) - defer infraMcp.delete() - o.Expect(err).NotTo(o.HaveOccurred(), "Error creating a new custom pool: %s", mcpAndMoscName) - logger.Infof("OK!\n") - - exutil.By("Configure OCB functionality for the new infra MCP") - mosc, err := CreateMachineOSConfigUsingExternalOrInternalRegistry(oc.AsAdmin(), MachineConfigNamespace, mcpAndMoscName, mcpAndMoscName, nil) - defer mosc.CleanupAndDelete() - o.Expect(err).NotTo(o.HaveOccurred(), "Error creating the MachineOSConfig resource") - logger.Infof("OK!\n") - - ValidateSuccessfulMOSC(mosc, nil) - - exutil.By("Remove the MachineOSConfig resource") - o.Expect(mosc.CleanupAndDelete()).To(o.Succeed(), "Error cleaning up %s", mosc) - logger.Infof("OK!\n") - - ValidateMOSCIsGarbageCollected(mosc, infraMcp) - - exutil.AssertAllPodsToBeReady(oc.AsAdmin(), MachineConfigNamespace) - logger.Infof("OK!\n") + env := NewOCBTestEnvWithCustomMCP(oc, "infra") + defer env.CleanupMCPOnly() + env.ValidateAndCleanup(nil) }) g.It("[PolarionID:83138][OTP] A MachineOSConfig fails to apply or degrades if invalid inputs are given", func() { @@ -109,11 +85,9 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/disruptive }) g.It("[PolarionID:83140][OTP] A MachineOSConfig with custom containerfile definition can be successfully applied", func() { - var ( - mcp = GetCompactCompatiblePool(oc.AsAdmin()) - containerFileContent string - checkers []Checker - ) + mcp := GetCompactCompatiblePool(oc.AsAdmin()) + var containerFileContent string + var checkers []Checker if IsDisconnectedCluster(oc.AsAdmin()) { logger.Infof("Disconnected cluster detected, using containerfile that does not require network access") @@ -146,45 +120,28 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/disruptive }) g.It("[PolarionID:77781][OTP] A successfully built MachineOSConfig can be re-build", func() { + env := NewOCBTestEnvWithCompactPool(oc) + defer env.Cleanup() - var ( - mcp = GetCompactCompatiblePool(oc.AsAdmin()) - ) - - exutil.By("Configure OCB functionality for the new worker MCP") - mosc, err := CreateMachineOSConfigUsingExternalOrInternalRegistry(oc.AsAdmin(), MachineConfigNamespace, mcp.GetName(), mcp.GetName(), nil) - defer DisableOCL(mosc) - o.Expect(err).NotTo(o.HaveOccurred(), "Error creating the MachineOSConfig resource") - logger.Infof("OK!\n") - - ValidateSuccessfulMOSC(mosc, nil) + ValidateSuccessfulMOSC(env.MOSC, nil) - // rebuild the image and check that the image is properly applied in the nodes - RebuildImageAndCheck(mosc) + RebuildImageAndCheck(env.MOSC) exutil.By("Remove the MachineOSConfig resource") - o.Expect(DisableOCL(mosc)).To(o.Succeed(), "Error cleaning up %s", mosc) + o.Expect(DisableOCL(env.MOSC)).To(o.Succeed(), "Error cleaning up %s", env.MOSC) logger.Infof("OK!\n") }) g.It("[PolarionID:77782][OTP] A MachineOSConfig with an unfinished build can be re-build", func() { - - var ( - mcp = GetCompactCompatiblePool(oc.AsAdmin()) - ) - - exutil.By("Configure OCB functionality for the new worker MCP") - mosc, err := CreateMachineOSConfigUsingExternalOrInternalRegistry(oc.AsAdmin(), MachineConfigNamespace, mcp.GetName(), mcp.GetName(), nil) - defer DisableOCL(mosc) - o.Expect(err).NotTo(o.HaveOccurred(), "Error creating the MachineOSConfig resource") - logger.Infof("OK!\n") + env := NewOCBTestEnvWithCompactPool(oc) + defer env.Cleanup() exutil.By("Wait until MOSB starts building") var mosb *MachineOSBuild var job *Job o.Eventually(func() (*MachineOSBuild, error) { var err error - mosb, err = mosc.GetCurrentMachineOSBuild() + mosb, err = env.MOSC.GetCurrentMachineOSBuild() return mosb, err }, "5m", "20s").Should(Exist(), "No build was created when OCB was enabled") @@ -207,11 +164,10 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/disruptive // TODO: what's the intended MCP status when a build is interrupted? We need to check this status here - // rebuild the image and check that the image is properly applied in the nodes - RebuildImageAndCheck(mosc) + RebuildImageAndCheck(env.MOSC) exutil.By("Remove the MachineOSConfig resource") - o.Expect(DisableOCL(mosc)).To(o.Succeed(), "Error cleaning up %s", mosc) + o.Expect(DisableOCL(env.MOSC)).To(o.Succeed(), "Error cleaning up %s", env.MOSC) logger.Infof("OK!\n") }) @@ -253,7 +209,7 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/disruptive logger.Infof("OK!\n") exutil.By("Enable on-cluster layering (OCL) with a containerFile") - mosc, err := CreateMachineOSConfigUsingExternalOrInternalRegistry(oc.AsAdmin(), MachineConfigNamespace, mcp.GetName(), mcp.GetName(), containerFiles) + mosc, err := CreateMOSC(oc.AsAdmin(), mcp.GetName(), mcp.GetName(), WithContainerFiles(containerFiles)) o.Expect(err).NotTo(o.HaveOccurred(), "Error creating MachineOSConfig for %s", mcp.GetName()) defer DisableOCL(mosc) logger.Infof("OK!\n") @@ -324,7 +280,14 @@ func testContainerFile(containerFiles []ContainerFile, imageNamespace string, mc switch imageNamespace { case MachineConfigNamespace: exutil.By("Configure OCB functionality for the new infra MCP. Create MOSC") - mosc, err = createMachineOSConfigUsingExternalOrInternalRegistry(oc, MachineConfigNamespace, mcp.GetName(), mcp.GetName(), containerFiles, defaultPullSecret, true) + moscOpts := []MOSCCreateOption{} + if len(containerFiles) > 0 { + moscOpts = append(moscOpts, WithContainerFiles(containerFiles)) + } + if defaultPullSecret { + moscOpts = append(moscOpts, WithDefaultPullSecret()) + } + mosc, err = CreateMOSC(oc, mcp.GetName(), mcp.GetName(), moscOpts...) default: SkipTestIfCannotUseInternalRegistry(mcp.GetOC()) @@ -354,7 +317,14 @@ func testContainerFile(containerFiles []ContainerFile, imageNamespace string, mc logger.Infof("OK!\n") exutil.By("Configure OCB functionality for the new infra MCP. Create MOSC") - mosc, err = CreateMachineOSConfigUsingInternalRegistry(oc, tmpNamespace.GetName(), mcp.GetName(), mcp.GetName(), containerFiles, defaultPullSecret) + moscOpts := []MOSCCreateOption{WithMOSCInternalRegistry(), WithMOSCNamespace(tmpNamespace.GetName())} + if len(containerFiles) > 0 { + moscOpts = append(moscOpts, WithContainerFiles(containerFiles)) + } + if defaultPullSecret { + moscOpts = append(moscOpts, WithDefaultPullSecret()) + } + mosc, err = CreateMOSC(oc, mcp.GetName(), mcp.GetName(), moscOpts...) } defer DisableOCL(mosc) o.Expect(err).NotTo(o.HaveOccurred(), "Error creating the MachineOSConfig resource") diff --git a/test/extended-priv/mco_ocb_longduration.go b/test/extended-priv/mco_ocb_longduration.go index 8b3085598d..2f946ac268 100644 --- a/test/extended-priv/mco_ocb_longduration.go +++ b/test/extended-priv/mco_ocb_longduration.go @@ -64,7 +64,7 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati logger.Infof("OK!\n") exutil.By("Configure OCB functionality for the new worker MCP") - mosc, err := CreateMachineOSConfigUsingExternalOrInternalRegistry(oc.AsAdmin(), MachineConfigNamespace, moscName, wMcp.GetName(), nil) + mosc, err := CreateMOSC(oc.AsAdmin(), moscName, wMcp.GetName()) defer DisableOCL(mosc) o.Expect(err).NotTo(o.HaveOccurred(), "Error creating the MachineOSConfig resource") logger.Infof("OK!\n") @@ -122,7 +122,7 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati // MOSCs resources have to use the same name as the MCP moscName := infraMcp.GetName() - mosc, err := CreateMachineOSConfigUsingExternalOrInternalRegistry(oc.AsAdmin(), MachineConfigNamespace, moscName, infraMcp.GetName(), nil) + mosc, err := CreateMOSC(oc.AsAdmin(), moscName, infraMcp.GetName()) defer mosc.CleanupAndDelete() o.Expect(err).NotTo(o.HaveOccurred(), "Error creating the MachineOSConfig resource") moscList = append(moscList, mosc) @@ -156,24 +156,17 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati }) g.It("[PolarionID:83755][OTP] In OCL check no new image is applied on node after applying ssh/password/file MC .[Disruptive]", func() { - var ( - mcp = GetCompactCompatiblePool(oc.AsAdmin()) - node = mcp.GetSortedNodesOrFail()[0] - - moscName = mcp.GetName() - mcName = fmt.Sprintf("test-ssh-%s", GetCurrentTestPolarionIDNumber()) + env := NewOCBTestEnvWithCompactPool(oc) + defer env.Cleanup() + var ( + node = env.MCP.GetSortedNodesOrFail()[0] + mcName = fmt.Sprintf("test-ssh-%s", GetCurrentTestPolarionIDNumber()) _, key = GenerateSSHKeyPairOrFail() user = ign32PaswdUser{Name: "core", SSHAuthorizedKeys: []string{key}} ) - exutil.By("Configure OCB functionality for the new worker MCP") - mosc, err := CreateMachineOSConfigUsingExternalOrInternalRegistry(oc.AsAdmin(), MachineConfigNamespace, moscName, mcp.GetName(), nil) - defer DisableOCL(mosc) - o.Expect(err).NotTo(o.HaveOccurred(), "Error creating the MachineOSConfig resource") - logger.Infof("Applied MOSC!\n") - - ValidateSuccessfulMOSC(mosc, nil) + ValidateSuccessfulMOSC(env.MOSC, nil) logger.Infof("MOSC is applied!\n") exutil.By("Get the image that is currently applied on nodes") @@ -182,7 +175,7 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati logger.Infof("Got the initial image!\n") exutil.By("Create a new MC to deploy new authorized keys") - mc := NewMachineConfig(oc.AsAdmin(), mcName, mcp.GetName()) + mc := NewMachineConfig(oc.AsAdmin(), mcName, env.MCP.GetName()) mc.parameters = []string{fmt.Sprintf(`PWDUSERS=[%s]`, MarshalOrFail(user))} mc.skipWaitForMcp = true @@ -191,14 +184,14 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati logger.Infof("Created MC!\n") exutil.By("Check that the build is triggered with succeed status and not building") - mosb, err := mosc.GetCurrentMachineOSBuild() + mosb, err := env.MOSC.GetCurrentMachineOSBuild() logger.Infof("MOSB: %s\n", mosb) o.Expect(err).NotTo(o.HaveOccurred(), "Error getting MOSB from MOSC") o.Expect(mosb).To(HaveConditionField("Building", "status", FalseString), "Build is still building") o.Expect(mosb).To(HaveConditionField("Succeeded", "status", TrueString), "Build didn't succeed") logger.Infof("Checked that the build does not take place!\n") - mcp.waitForComplete() + env.MCP.waitForComplete() logger.Infof("OK!\n") exutil.By("Check that the image is not updated") @@ -206,7 +199,7 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati logger.Infof("Image is not updated!\n") exutil.By("Check that all expected keys are present and with the right permissions and owners") - currentMc := OrFail[*MachineConfig](mcp.GetConfiguredMachineConfig()) + currentMc := OrFail[*MachineConfig](env.MCP.GetConfiguredMachineConfig()) initialKeys := OrFail[[]string](currentMc.GetAuthorizedKeysByUserAsList("core")) checkAuthorizedKeyInNode(node, append(initialKeys, key)) logger.Infof("MC is configured with the expected keys!\n") @@ -224,7 +217,7 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati ) exutil.By("Configure OCB functionality for the compatible MCP") - mosc, err := CreateMachineOSConfigUsingInternalRegistry(oc.AsAdmin(), MachineConfigNamespace, moscName, mcp.GetName(), nil, true) + mosc, err := CreateMOSC(oc.AsAdmin(), moscName, mcp.GetName(), WithMOSCInternalRegistry(), WithDefaultPullSecret()) defer DisableOCL(mosc) o.Expect(err).NotTo(o.HaveOccurred(), "Error creating the MachineOSConfig resource") logger.Infof("OK!\n") @@ -234,48 +227,37 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati g.It("[PolarionID:82536][OTP][Skipped:Disconnected] Internal Registry In OCB to check when a image is removed the old build is triggered again and the MC should start updating directly. [Disruptive]", func() { SkipIfCompactOrSNO(oc.AsAdmin()) - SkipTestIfCannotUseInternalRegistry(oc.AsAdmin()) // This test case requires the internal registry to be enabled + SkipTestIfCannotUseInternalRegistry(oc.AsAdmin()) + + env := NewOCBTestEnvWithCustomMCP(oc, "infra", WithOCBWorkers(1), WithOCBMOSCOptions(WithMOSCInternalRegistry())) + defer env.Cleanup() var ( - infraMcpName = "infra" - mcName = fmt.Sprintf("tc-%s-int-kernelarg", GetCurrentTestPolarionIDNumber()) - kArgs = "test" + mcName = fmt.Sprintf("tc-%s-int-kernelarg", GetCurrentTestPolarionIDNumber()) + kArgs = "test" ) - exutil.By("Create custom infra MCP") - infraMcp, err := CreateCustomMCP(oc.AsAdmin(), infraMcpName, 1) - defer DeleteCustomMCP(oc.AsAdmin(), infraMcpName) - o.Expect(err).NotTo(o.HaveOccurred(), "Error creating a new custom pool: %s", infraMcpName) - logger.Infof("OK!\n") - - exutil.By("Create MOSC for custom MCP using internal registry") - moscName := infraMcp.GetName() - mosc, err := CreateMachineOSConfigUsingInternalRegistry(oc.AsAdmin(), MachineConfigNamespace, moscName, infraMcp.GetName(), nil, false) - defer DisableOCL(mosc) - o.Expect(err).NotTo(o.HaveOccurred(), "Error creating MOSC") - logger.Infof("OK!\n") - exutil.By("Validate initial MOSC and wait for MOSB-1 to succeed") - ValidateSuccessfulMOSC(mosc, nil) + ValidateSuccessfulMOSC(env.MOSC, nil) - mosb1, err := mosc.GetCurrentMachineOSBuild() + mosb1, err := env.MOSC.GetCurrentMachineOSBuild() o.Expect(err).NotTo(o.HaveOccurred(), "Error getting initial MOSB") logger.Infof("Initial MOSB created: %s\n", mosb1.GetName()) exutil.By("Apply MC with kernel argument to trigger new MOSB") - mc := NewMachineConfig(oc.AsAdmin(), mcName, infraMcp.GetName()) + mc := NewMachineConfig(oc.AsAdmin(), mcName, env.MCP.GetName()) mc.skipWaitForMcp = true defer mc.DeleteWithWait() - err = mc.Create("-p", "NAME="+mcName, "-p", "POOL="+infraMcp.GetName(), + err = mc.Create("-p", "NAME="+mcName, "-p", "POOL="+env.MCP.GetName(), "-p", fmt.Sprintf(`KERNEL_ARGS=["%s"]`, kArgs)) o.Expect(err).NotTo(o.HaveOccurred(), "Error creating MachineConfig %s", mc.GetName()) logger.Infof("OK!\n") exutil.By("Wait for MOSB-2 to be created and succeed") - checkNewBuildIsTriggered(mosc, mosb1) - mosb2, err := mosc.GetCurrentMachineOSBuild() + checkNewBuildIsTriggered(env.MOSC, mosb1) + mosb2, err := env.MOSC.GetCurrentMachineOSBuild() o.Expect(err).NotTo(o.HaveOccurred(), "Error getting MOSB-2") logger.Infof("Second MOSB created: %s\n", mosb2.GetName()) @@ -283,49 +265,28 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati o.Expect(removeImageStream(oc.AsAdmin(), mosb1)).To(o.BeTrue(), "Error deleting imagestream tag for MOSB-1") logger.Infof("OK!\n") - // Common verification after MOSB-1 deletion - verifyMOSBRebuildAfterImageDeletion(infraMcp, mosc, mosb1, mosb2, mc, mcName) + verifyMOSBRebuildAfterImageDeletion(env.MCP, env.MOSC, mosb1, mosb2, mc, mcName) }) g.It("[PolarionID:79172][OTP] OCB Inherit from global pull secret if baseImagePullSecret field is not specified [Disruptive]", func() { - var ( - infraMcpName = "infra" - ) + env := NewOCBTestEnvWithCustomMCP(oc, "infra", WithOCBSkipMOSC()) + defer env.CleanupMCPOnly() - exutil.By("Create custom infra MCP") - // We add no workers to the infra pool, it is not necessary - infraMcp, err := CreateCustomMCP(oc.AsAdmin(), infraMcpName, 0) - defer infraMcp.delete() - o.Expect(err).NotTo(o.HaveOccurred(), "Error creating a new custom pool: %s", infraMcpName) - logger.Infof("OK!\n") - - testContainerFile([]ContainerFile{}, MachineConfigNamespace, infraMcp, nil, true) + testContainerFile([]ContainerFile{}, MachineConfigNamespace, env.MCP, nil, true) }) g.It("[PolarionID:83136][OTP][Skipped:Disconnected] Panic Condition for Non-Matching MOSC Resources [Disruptive]", func() { - var ( - infraMcpName = "infra" - // MOSC has to use the same name as the mcp - moscName = infraMcpName - ) - exutil.By("Create New Custom MCP") - defer DeleteCustomMCP(oc.AsAdmin(), infraMcpName) - infraMcp, err := CreateCustomMCP(oc.AsAdmin(), infraMcpName, 1) - o.Expect(err).NotTo(o.HaveOccurred(), "Could not create a new custom MCP") - node := infraMcp.GetNodesOrFail()[0] - logger.Infof("%s", node.GetName()) - logger.Infof("OK!\n") + env := NewOCBTestEnvWithCustomMCP(oc, "infra", WithOCBWorkers(1)) + defer env.CleanupMCPOnly() - exutil.By("Configure OCB functionality for the new infra MCP") - mosc, err := CreateMachineOSConfigUsingExternalOrInternalRegistry(oc.AsAdmin(), MachineConfigNamespace, moscName, infraMcpName, nil) - defer DisableOCL(mosc) - o.Expect(err).NotTo(o.HaveOccurred(), "Error creating the MachineOSConfig resource") + node := env.MCP.GetNodesOrFail()[0] + logger.Infof("%s", node.GetName()) logger.Infof("OK!\n") exutil.By("Check that a new build has been triggered") - o.Eventually(mosc.GetCurrentMachineOSBuild, "5m", "20s").Should(Exist(), + o.Eventually(env.MOSC.GetCurrentMachineOSBuild, "5m", "20s").Should(Exist(), "No build was created when OCB was enabled") - mosb, err := mosc.GetCurrentMachineOSBuild() + mosb, err := env.MOSC.GetCurrentMachineOSBuild() o.Expect(err).NotTo(o.HaveOccurred(), "Error getting MOSB from MOSC") o.Eventually(mosb.GetJob, "5m", "20s").Should(Exist(), "No build pod was created when OCB was enabled") @@ -334,10 +295,10 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati logger.Infof("OK!\n") exutil.By("Delete the MCOS and check it is deleted") - o.Expect(mosc.CleanupAndDelete()).To(o.Succeed(), "Error cleaning up %s", mosc) - ValidateMOSCIsGarbageCollected(mosc, infraMcp) + o.Expect(env.MOSC.CleanupAndDelete()).To(o.Succeed(), "Error cleaning up %s", env.MOSC) + ValidateMOSCIsGarbageCollected(env.MOSC, env.MCP) o.Expect(mosb).NotTo(Exist(), "Build is not deleted") - o.Expect(mosc).NotTo(Exist(), "MOSC is not deleted") + o.Expect(env.MOSC).NotTo(Exist(), "MOSC is not deleted") logger.Infof("OK!\n") exutil.AssertAllPodsToBeReady(oc.AsAdmin(), MachineConfigNamespace) @@ -376,50 +337,35 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati }) g.It("[PolarionID:77498][OTP] OCB Trigger new build when renderedImagePushspec is updated [Disruptive]", func() { + env := NewOCBTestEnvWithCustomMCP(oc, "infra") + defer env.CleanupMCPOnly() + defer env.MOSC.CleanupAndDelete() - var ( - infraMcpName = "infra" - // MOSC resources have to use the same names as the MCP - moscName = infraMcpName - ) - - exutil.By("Create custom infra MCP") - // We add no workers to the infra pool, it is not necessary - infraMcp, err := CreateCustomMCP(oc.AsAdmin(), infraMcpName, 0) - defer infraMcp.delete() - o.Expect(err).NotTo(o.HaveOccurred(), "Error creating a new custom pool: %s", infraMcpName) - logger.Infof("OK!\n") - - exutil.By("Configure OCB functionality for the new infra MCP") - mosc, err := CreateMachineOSConfigUsingExternalOrInternalRegistry(oc.AsAdmin(), MachineConfigNamespace, moscName, infraMcpName, nil) - defer mosc.CleanupAndDelete() - o.Expect(err).NotTo(o.HaveOccurred(), "Error creating the MachineOSConfig resource") - logger.Infof("OK!\n") - - ValidateSuccessfulMOSC(mosc, nil) + ValidateSuccessfulMOSC(env.MOSC, nil) exutil.By("Set a new rendered image pull spec") - initialMOSB := OrFail[*MachineOSBuild](mosc.GetCurrentMachineOSBuild()) - initialRIPS := OrFail[string](mosc.GetRenderedImagePushspec()) + initialMOSB := OrFail[*MachineOSBuild](env.MOSC.GetCurrentMachineOSBuild()) + initialRIPS := OrFail[string](env.MOSC.GetRenderedImagePushspec()) o.Expect( - mosc.SetRenderedImagePushspec(strings.ReplaceAll(initialRIPS, "ocb-", "ocb77498-")), - ).NotTo(o.HaveOccurred(), "Error patching %s to set the new renderedImagePullSpec", mosc) + env.MOSC.SetRenderedImagePushspec(strings.ReplaceAll(initialRIPS, "ocb-", "ocb77498-")), + ).NotTo(o.HaveOccurred(), "Error patching %s to set the new renderedImagePullSpec", env.MOSC) logger.Infof("OK!\n") exutil.By("Check that a new build is triggered") - checkNewBuildIsTriggered(mosc, initialMOSB) + checkNewBuildIsTriggered(env.MOSC, initialMOSB) logger.Infof("OK!\n") exutil.By("Set the original rendered image pull spec") o.Expect( - mosc.SetRenderedImagePushspec(initialRIPS), - ).NotTo(o.HaveOccurred(), "Error patching %s to set the new renderedImagePullSpec", mosc) + env.MOSC.SetRenderedImagePushspec(initialRIPS), + ).NotTo(o.HaveOccurred(), "Error patching %s to set the new renderedImagePullSpec", env.MOSC) logger.Infof("OK!\n") exutil.By("Check that the initial build is reused") var currentMOSB *MachineOSBuild o.Eventually(func() (string, error) { - currentMOSB, err = mosc.GetCurrentMachineOSBuild() + var err error + currentMOSB, err = env.MOSC.GetCurrentMachineOSBuild() if err != nil || currentMOSB == nil { return "", err } @@ -431,69 +377,51 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati }) g.It("[PolarionID:77497][OTP] OCB Trigger new build when Containerfile is updated [Disruptive]", func() { - var ( - infraMcpName = "infra" - // MOSC resources have to use the same names as the MCP - moscName = infraMcpName containerFile = ContainerFile{Content: "RUN touch /etc/test-add-containerfile" + "\n" + ExpirationDockerfileLabel} containerFileMod = ContainerFile{Content: "RUN touch /etc/test-modified-containerfile" + "\n" + ExpirationDockerfileLabel} - - // We need to test a first MOSC without any container file, so we cannot add the expiration label in the first MOSC - expireImage = false - // We don't configure the pull secret in the MOSC, since it is optional - defaultPullSecret = true ) - exutil.By("Create custom infra MCP") - // We add no workers to the infra pool, it is not necessary - infraMcp, err := CreateCustomMCP(oc.AsAdmin(), infraMcpName, 0) - defer infraMcp.delete() - o.Expect(err).NotTo(o.HaveOccurred(), "Error creating a new custom pool: %s", infraMcpName) - logger.Infof("OK!\n") - - exutil.By("Configure OCB functionality for the new infra MCP") - mosc, err := createMachineOSConfigUsingExternalOrInternalRegistry(oc.AsAdmin(), MachineConfigNamespace, moscName, infraMcpName, nil, defaultPullSecret, expireImage) - - defer mosc.CleanupAndDelete() - o.Expect(err).NotTo(o.HaveOccurred(), "Error creating the MachineOSConfig resource") - logger.Infof("OK!\n") + env := NewOCBTestEnvWithCustomMCP(oc, "infra", WithOCBMOSCOptions(WithDefaultPullSecret(), WithNoImageExpiration())) + defer env.CleanupMCPOnly() + defer env.MOSC.CleanupAndDelete() - ValidateSuccessfulMOSC(mosc, nil) + ValidateSuccessfulMOSC(env.MOSC, nil) exutil.By("Add new container file") - initialMOSB := OrFail[*MachineOSBuild](mosc.GetCurrentMachineOSBuild()) + initialMOSB := OrFail[*MachineOSBuild](env.MOSC.GetCurrentMachineOSBuild()) o.Expect( - mosc.SetContainerfiles([]ContainerFile{containerFile}), - ).NotTo(o.HaveOccurred(), "Error patching %s to add a container file", mosc) + env.MOSC.SetContainerfiles([]ContainerFile{containerFile}), + ).NotTo(o.HaveOccurred(), "Error patching %s to add a container file", env.MOSC) logger.Infof("OK!\n") exutil.By("Check that a new build is triggered when a containerfile is added") - checkNewBuildIsTriggered(mosc, initialMOSB) + checkNewBuildIsTriggered(env.MOSC, initialMOSB) logger.Infof("OK!\n") exutil.By("Modify the container file") - currentMOSB := OrFail[*MachineOSBuild](mosc.GetCurrentMachineOSBuild()) + currentMOSB := OrFail[*MachineOSBuild](env.MOSC.GetCurrentMachineOSBuild()) o.Expect( - mosc.SetContainerfiles([]ContainerFile{containerFileMod}), - ).NotTo(o.HaveOccurred(), "Error patching %s to modify an existing container file", mosc) + env.MOSC.SetContainerfiles([]ContainerFile{containerFileMod}), + ).NotTo(o.HaveOccurred(), "Error patching %s to modify an existing container file", env.MOSC) logger.Infof("OK!\n") exutil.By("Check that a new build is triggered when a containerfile is modified") - checkNewBuildIsTriggered(mosc, currentMOSB) + checkNewBuildIsTriggered(env.MOSC, currentMOSB) logger.Infof("OK!\n") exutil.By("Remove the container files") o.Expect( - mosc.RemoveContainerfiles(), - ).NotTo(o.HaveOccurred(), "Error patching %s to remove the configured container files", mosc) + env.MOSC.RemoveContainerfiles(), + ).NotTo(o.HaveOccurred(), "Error patching %s to remove the configured container files", env.MOSC) logger.Infof("OK!\n") exutil.By("Check that the initial build is reused") o.Eventually(func() (string, error) { - currentMOSB, err = mosc.GetCurrentMachineOSBuild() + var err error + currentMOSB, err = env.MOSC.GetCurrentMachineOSBuild() if err != nil || currentMOSB == nil { return "", err } @@ -505,28 +433,21 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati }) g.It("[PolarionID:77576][OTP] In OCB. Create a new MC while a build is running [Disruptive]", func() { + env := NewOCBTestEnvWithCompactPool(oc) + defer env.Cleanup() var ( - mcp = GetCompactCompatiblePool(oc.AsAdmin()) - node = mcp.GetSortedNodesOrFail()[0] - moscName = mcp.GetName() - + node = env.MCP.GetSortedNodesOrFail()[0] kArgs = "test" mcName = "tc-77576-testkargs" - mc = NewMachineConfig(oc.AsAdmin(), mcName, mcp.GetName()) + mc = NewMachineConfig(oc.AsAdmin(), mcName, env.MCP.GetName()) ) - exutil.By("Configure OCB functionality for the new worker MCP") - mosc, err := CreateMachineOSConfigUsingExternalOrInternalRegistry(oc.AsAdmin(), MachineConfigNamespace, moscName, mcp.GetName(), nil) - defer DisableOCL(mosc) - o.Expect(err).NotTo(o.HaveOccurred(), "Error creating the MachineOSConfig resource") - logger.Infof("OK!\n") - exutil.By("Check that a new build has been triggered and is building") var mosb *MachineOSBuild o.Eventually(func() (*MachineOSBuild, error) { var err error - mosb, err = mosc.GetCurrentMachineOSBuild() + mosb, err = env.MOSC.GetCurrentMachineOSBuild() return mosb, err }, "5m", "20s").Should(Exist(), "No build was created when OCB was enabled") @@ -538,17 +459,17 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati exutil.By("Create a MC to trigger a new build") defer mc.DeleteWithWait() - err = mc.Create("-p", "NAME="+mcName, "-p", "POOL="+mcp.GetName(), "-p", fmt.Sprintf(`KERNEL_ARGS=["%s"]`, kArgs)) + err := mc.Create("-p", "NAME="+mcName, "-p", "POOL="+env.MCP.GetName(), "-p", fmt.Sprintf(`KERNEL_ARGS=["%s"]`, kArgs)) o.Expect(err).NotTo(o.HaveOccurred()) logger.Infof("OK!\n") exutil.By("Check that a new build is triggered and the old build is removed") - checkNewBuildIsTriggered(mosc, mosb) + checkNewBuildIsTriggered(env.MOSC, mosb) o.Eventually(mosb, "2m", "20s").ShouldNot(Exist(), "The old MOSB %s was not deleted", mosb) logger.Infof("OK!\n") exutil.By("Wait for the configuration to be applied") - mcp.waitForComplete() + env.MCP.waitForComplete() logger.Infof("OK!\n") exutil.By("Check that the MC was applied") @@ -558,37 +479,31 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati logger.Infof("OK!\n") exutil.By("Remove the MachineOSConfig resource") - o.Expect(DisableOCL(mosc)).To(o.Succeed(), "Error cleaning up %s", mosc) + o.Expect(DisableOCL(env.MOSC)).To(o.Succeed(), "Error cleaning up %s", env.MOSC) logger.Infof("OK!\n") }) g.It("[PolarionID:77977][OTP][Skipped:Disconnected] Install extension after OCB is enabled [Disruptive]", func() { + env := NewOCBTestEnvWithCompactPool(oc) + defer env.Cleanup() var ( - mcp = GetCompactCompatiblePool(oc.AsAdmin()) - moscName = mcp.GetName() // MOSC resources have to use the same name as the MCP - node = mcp.GetSortedNodesOrFail()[0] + node = env.MCP.GetSortedNodesOrFail()[0] mcName = "test-install-extension-" + GetCurrentTestPolarionIDNumber() - applicableExtensions, _ = GetAllApplicableExtensionsToMCPOrFail(mcp) + applicableExtensions, _ = GetAllApplicableExtensionsToMCPOrFail(env.MCP) ) - exutil.By("Configure OCB functionality for the new worker MCP") - mosc, err := CreateMachineOSConfigUsingExternalOrInternalRegistry(oc.AsAdmin(), MachineConfigNamespace, moscName, mcp.GetName(), nil) - defer DisableOCL(mosc) - o.Expect(err).NotTo(o.HaveOccurred(), "Error creating the MachineOSConfig resource") - logger.Infof("OK!\n") - - ValidateSuccessfulMOSC(mosc, nil) + ValidateSuccessfulMOSC(env.MOSC, nil) exutil.By("Create a MC") - mc := NewMachineConfig(oc.AsAdmin(), mcName, mcp.GetName()) + mc := NewMachineConfig(oc.AsAdmin(), mcName, env.MCP.GetName()) defer mc.DeleteWithWait() mc.parameters = []string{fmt.Sprintf(`EXTENSIONS=%s`, string(MarshalOrFail(applicableExtensions)))} mc.create() logger.Infof("OK!\n") exutil.By("Wait for the configuration to be applied") - mcp.waitForComplete() + env.MCP.waitForComplete() logger.Infof("OK!\n") CheckExtensions(node, applicableExtensions) @@ -598,8 +513,8 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati logger.Infof("OK!\n") exutil.By("Remove the MachineOSConfig resource") - o.Expect(DisableOCL(mosc)).To(o.Succeed(), "Error cleaning up %s", mosc) - ValidateMOSCIsGarbageCollected(mosc, mcp) + o.Expect(DisableOCL(env.MOSC)).To(o.Succeed(), "Error cleaning up %s", env.MOSC) + ValidateMOSCIsGarbageCollected(env.MOSC, env.MCP) logger.Infof("OK!\n") }) @@ -641,7 +556,7 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati logger.Infof("OK!\n") exutil.By("Create the MOSC") - mosc, err := CreateMachineOSConfigUsingExternalOrInternalRegistry(oc.AsAdmin(), MachineConfigNamespace, moscName, mcp.GetName(), []ContainerFile{{Content: containerFileContent}}) + mosc, err := CreateMOSC(oc.AsAdmin(), moscName, mcp.GetName(), WithContainerFiles([]ContainerFile{{Content: containerFileContent}})) defer DisableOCL(mosc) o.Expect(err).NotTo(o.HaveOccurred(), "Error creating the MachineOSConfig resource") logger.Infof("OK!\n") @@ -689,7 +604,7 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati ) exutil.By("Configure OCB functionality using external registry (Quay)") - mosc, err := CreateMachineOSConfigUsingExternalRegistry(oc.AsAdmin(), moscName, mcp.GetName(), nil, false, false) + mosc, err := CreateMOSC(oc.AsAdmin(), moscName, mcp.GetName(), WithMOSCExternalRegistry(), WithNoImageExpiration()) defer DisableOCL(mosc) o.Expect(err).NotTo(o.HaveOccurred(), "Error creating the MachineOSConfig resource") logger.Infof("OK!\n") @@ -699,33 +614,24 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati g.It("[PolarionID:85980][OTP][Skipped:Disconnected] Check when MOSB is degraded MCP should be degraded too with right fields updated. [Disruptive]", func() { var ( - infraMcpName = "infra" - moscName = infraMcpName - // Intentionally uses 'apt' on Alpine (which uses 'apk'), causing build to fail incorrectContainerFile = "FROM alpine:3.18\nRUN apt update && apt install -y cowsay\n" correctContainerFile = "FROM configs AS final\nRUN echo \"hello\" > /etc/test.txt\n" expectedDegradedMessage = "Failed to build OS image" ) - exutil.By("Create custom infra MCP") - infraMcp, err := CreateCustomMCP(oc.AsAdmin(), infraMcpName, 1) - defer DeleteCustomMCP(oc.AsAdmin(), infraMcpName) - o.Expect(err).NotTo(o.HaveOccurred(), "Error creating custom MCP: %s", infraMcpName) - node := infraMcp.GetNodesOrFail()[0] - logger.Infof("Infra node: %s\n", node.GetName()) - logger.Infof("OK!\n") + env := NewOCBTestEnvWithCustomMCP(oc, "infra", WithOCBWorkers(1), + WithOCBMOSCOptions(WithContainerFiles([]ContainerFile{{Content: incorrectContainerFile}}))) + defer env.CleanupMCPOnly() + defer env.MOSC.CleanupAndDelete() - exutil.By("Create MOSC with incorrect containerfile") - mosc, err := CreateMachineOSConfigUsingExternalOrInternalRegistry(oc.AsAdmin(), MachineConfigNamespace, moscName, infraMcpName, - []ContainerFile{{Content: incorrectContainerFile}}) - defer mosc.CleanupAndDelete() - o.Expect(err).NotTo(o.HaveOccurred(), "Error creating MOSC with incorrect containerfile") + node := env.MCP.GetNodesOrFail()[0] + logger.Infof("Infra node: %s\n", node.GetName()) logger.Infof("OK!\n") exutil.By("Verify MOSB is created and fails") - o.Eventually(mosc.GetCurrentMachineOSBuild, "5m", "20s").Should(Exist(), + o.Eventually(env.MOSC.GetCurrentMachineOSBuild, "5m", "20s").Should(Exist(), "No MOSB was created for the incorrect containerfile") - failedMOSB, err := mosc.GetCurrentMachineOSBuild() + failedMOSB, err := env.MOSC.GetCurrentMachineOSBuild() o.Expect(err).NotTo(o.HaveOccurred(), "Error getting MOSB from MOSC") logger.Infof("MOSB created: %s\n", failedMOSB.GetName()) o.Eventually(failedMOSB, "20m", "20s").Should(HaveConditionField("Failed", "status", TrueString), @@ -733,23 +639,23 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati logger.Infof("MOSB failed as expected\n") exutil.By("Verify MCP is degraded with ImageBuildDegraded condition") - o.Eventually(infraMcp, "5m", "20s").Should(BeDegraded(), "MCP should be degraded when build fails") - o.Eventually(infraMcp, "5m", "20s").Should(HaveConditionField("ImageBuildDegraded", "status", TrueString), + o.Eventually(env.MCP, "5m", "20s").Should(BeDegraded(), "MCP should be degraded when build fails") + o.Eventually(env.MCP, "5m", "20s").Should(HaveConditionField("ImageBuildDegraded", "status", TrueString), "MCP ImageBuildDegraded should be True when build fails") - o.Eventually(infraMcp, "5m", "20s").Should(HaveConditionField("ImageBuildDegraded", "message", o.ContainSubstring(expectedDegradedMessage)), + o.Eventually(env.MCP, "5m", "20s").Should(HaveConditionField("ImageBuildDegraded", "message", o.ContainSubstring(expectedDegradedMessage)), "MCP degradation message should indicate OS image build failure") - o.Eventually(infraMcp, "5m", "20s").Should(HaveConditionField("Degraded", "message", o.ContainSubstring("Custom OS image build failed")), + o.Eventually(env.MCP, "5m", "20s").Should(HaveConditionField("Degraded", "message", o.ContainSubstring("Custom OS image build failed")), "MCP Degraded message should indicate custom OS image build failed") logger.Infof("OK!\n") exutil.By("Fix the MOSC by updating containerfile") - o.Expect(mosc.SetContainerfiles([]ContainerFile{{Content: correctContainerFile}})).NotTo(o.HaveOccurred(), + o.Expect(env.MOSC.SetContainerfiles([]ContainerFile{{Content: correctContainerFile}})).NotTo(o.HaveOccurred(), "Error updating MOSC with correct containerfile") logger.Infof("OK!\n") exutil.By("Verify new MOSB is created and succeeds") - checkNewBuildIsTriggered(mosc, failedMOSB) - newMOSB, err := mosc.GetCurrentMachineOSBuild() + checkNewBuildIsTriggered(env.MOSC, failedMOSB) + newMOSB, err := env.MOSC.GetCurrentMachineOSBuild() o.Expect(err).NotTo(o.HaveOccurred(), "Error getting new MOSB") logger.Infof("New MOSB created: %s\n", newMOSB.GetName()) @@ -759,22 +665,20 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati logger.Infof("OK!\n") exutil.By("Verify MCP recovers and is no longer degraded") - // Check both ImageBuildDegraded (specific condition) and Degraded (overall status) - // to ensure complete recovery from the failed build state - o.Eventually(infraMcp, "5m", "20s").Should(HaveConditionField("ImageBuildDegraded", "status", FalseString), + o.Eventually(env.MCP, "5m", "20s").Should(HaveConditionField("ImageBuildDegraded", "status", FalseString), "MCP ImageBuildDegraded condition should be False after recovery") - o.Eventually(infraMcp, "5m", "20s").ShouldNot(BeDegraded(), + o.Eventually(env.MCP, "5m", "20s").ShouldNot(BeDegraded(), "MCP Degraded condition should be False after recovery") - o.Eventually(infraMcp, "5m", "20s").Should(HaveConditionField("Updating", "status", TrueString), + o.Eventually(env.MCP, "5m", "20s").Should(HaveConditionField("Updating", "status", TrueString), "MCP should be updating after successful build") logger.Infof("OK!\n") exutil.By("Wait for MCP to complete update") - infraMcp.waitForComplete() + env.MCP.waitForComplete() logger.Infof("OK!\n") exutil.By("Verify image is applied to node") - currentImagePullSpec := OrFail[string](mosc.GetStatusCurrentImagePullSpec()) + currentImagePullSpec := OrFail[string](env.MOSC.GetStatusCurrentImagePullSpec()) o.Expect(node.GetCurrentBootOSImage()).To(o.Equal(currentImagePullSpec), "Node should be using the correct OCL image after recovery") logger.Infof("Node is using image: %s\n", currentImagePullSpec) @@ -792,60 +696,48 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati SkipIfCompactOrSNO(oc.AsAdmin()) var ( - infraMcpName = "infra" mcName = fmt.Sprintf("tc-%s-ext-kernelarg", GetCurrentTestPolarionIDNumber()) kArgs = "test" containerFileNoExpiration = "FROM configs AS final\nLABEL maintainer=\"mco@example.com\"\n" ) - exutil.By("Create custom infra MCP") - infraMcp, err := CreateCustomMCP(oc.AsAdmin(), infraMcpName, 1) - defer DeleteCustomMCP(oc.AsAdmin(), infraMcpName) - o.Expect(err).NotTo(o.HaveOccurred(), "Error creating a new custom pool: %s", infraMcpName) - logger.Infof("OK!\n") - - exutil.By("Create MOSC for custom MCP using external registry") - moscName := infraMcp.GetName() - mosc, err := CreateMachineOSConfigUsingExternalRegistry(oc.AsAdmin(), moscName, infraMcp.GetName(), - []ContainerFile{{Content: containerFileNoExpiration}}, false, false) - defer DisableOCL(mosc) - o.Expect(err).NotTo(o.HaveOccurred(), "Error creating MOSC") - logger.Infof("OK!\n") + env := NewOCBTestEnvWithCustomMCP(oc, "infra", WithOCBWorkers(1), + WithOCBMOSCOptions(WithMOSCExternalRegistry(), WithNoImageExpiration(), WithContainerFiles([]ContainerFile{{Content: containerFileNoExpiration}}))) + defer env.Cleanup() exutil.By("Validate initial MOSC and wait for MOSB-1 to succeed") - ValidateSuccessfulMOSC(mosc, nil) + ValidateSuccessfulMOSC(env.MOSC, nil) - mosb1, err := mosc.GetCurrentMachineOSBuild() + mosb1, err := env.MOSC.GetCurrentMachineOSBuild() o.Expect(err).NotTo(o.HaveOccurred(), "Error getting initial MOSB") logger.Infof("Initial MOSB created: %s\n", mosb1.GetName()) exutil.By("Apply MC with kernel argument to trigger new MOSB") - mc := NewMachineConfig(oc.AsAdmin(), mcName, infraMcp.GetName()) + mc := NewMachineConfig(oc.AsAdmin(), mcName, env.MCP.GetName()) mc.skipWaitForMcp = true defer mc.DeleteWithWait() - err = mc.Create("-p", "NAME="+mcName, "-p", "POOL="+infraMcp.GetName(), + err = mc.Create("-p", "NAME="+mcName, "-p", "POOL="+env.MCP.GetName(), "-p", fmt.Sprintf(`KERNEL_ARGS=["%s"]`, kArgs)) o.Expect(err).NotTo(o.HaveOccurred(), "Error creating MachineConfig %s", mc.GetName()) logger.Infof("OK!\n") exutil.By("Wait for MOSB-2 to be created and succeed") - checkNewBuildIsTriggered(mosc, mosb1) - mosb2, err := mosc.GetCurrentMachineOSBuild() + checkNewBuildIsTriggered(env.MOSC, mosb1) + mosb2, err := env.MOSC.GetCurrentMachineOSBuild() o.Expect(err).NotTo(o.HaveOccurred(), "Error getting MOSB-2") logger.Infof("Second MOSB created: %s\n", mosb2.GetName()) exutil.By("Wait for MCP to complete update") - infraMcp.waitForComplete() + env.MCP.waitForComplete() logger.Infof("OK!\n") exutil.By("Delete MOSB-1 image from Quay using automated skopeo deletion") - o.Expect(removeQuayImageUsingSkopeo(oc.AsAdmin(), mosb1, infraMcp)).To(o.BeTrue(), "Error deleting Quay image for MOSB-1") + o.Expect(removeQuayImageUsingSkopeo(oc.AsAdmin(), mosb1, env.MCP)).To(o.BeTrue(), "Error deleting Quay image for MOSB-1") logger.Infof("OK!\n") - // Common verification after MOSB-1 deletion - verifyMOSBRebuildAfterImageDeletion(infraMcp, mosc, mosb1, mosb2, mc, mcName) + verifyMOSBRebuildAfterImageDeletion(env.MCP, env.MOSC, mosb1, mosb2, mc, mcName) }) }) diff --git a/test/extended-priv/mco_ocb_setup.go b/test/extended-priv/mco_ocb_setup.go new file mode 100644 index 0000000000..cb291b06a1 --- /dev/null +++ b/test/extended-priv/mco_ocb_setup.go @@ -0,0 +1,140 @@ +package extended + +import ( + 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" +) + +// OCBTestEnv manages common OCB test resources (MCP + MOSC) lifecycle. +// Use NewOCBTestEnvWithCustomMCP or NewOCBTestEnvWithCompactPool to create one, +// then defer env.Cleanup() or call env.ValidateAndCleanup(). +type OCBTestEnv struct { + OC *exutil.CLI + MCP *MachineConfigPool + MOSC *MachineOSConfig + isCustomMCP bool +} + +type ocbSetupConfig struct { + numWorkers int + moscOpts []MOSCCreateOption + skipMOSC bool +} + +// OCBSetupOption configures optional behavior for OCBTestEnv setup. +type OCBSetupOption func(*ocbSetupConfig) + +// WithOCBWorkers sets the number of worker nodes to add to the custom MCP. +func WithOCBWorkers(n int) OCBSetupOption { + return func(c *ocbSetupConfig) { c.numWorkers = n } +} + +// WithOCBMOSCOptions passes MOSCCreateOption values through to CreateMOSC. +func WithOCBMOSCOptions(opts ...MOSCCreateOption) OCBSetupOption { + return func(c *ocbSetupConfig) { c.moscOpts = append(c.moscOpts, opts...) } +} + +// WithOCBSkipMOSC skips creating a MOSC, only creates the MCP. +func WithOCBSkipMOSC() OCBSetupOption { + return func(c *ocbSetupConfig) { c.skipMOSC = true } +} + +func applyOCBOptions(opts []OCBSetupOption) ocbSetupConfig { + cfg := ocbSetupConfig{} + for _, opt := range opts { + opt(&cfg) + } + return cfg +} + +// NewOCBTestEnvWithCustomMCP creates a custom MCP and MOSC. +// The caller must defer env.Cleanup() to ensure proper teardown. +func NewOCBTestEnvWithCustomMCP(oc *exutil.CLI, mcpName string, opts ...OCBSetupOption) *OCBTestEnv { + cfg := applyOCBOptions(opts) + + exutil.By("Create custom " + mcpName + " MCP") + mcp, err := CreateCustomMCP(oc.AsAdmin(), mcpName, cfg.numWorkers) + o.Expect(err).NotTo(o.HaveOccurred(), "Error creating a new custom pool: %s", mcpName) + logger.Infof("OK!\n") + + env := &OCBTestEnv{ + OC: oc, + MCP: mcp, + isCustomMCP: true, + } + + if cfg.skipMOSC { + return env + } + + exutil.By("Configure OCB functionality for the " + mcpName + " MCP") + mosc, err := CreateMOSC(oc.AsAdmin(), mcpName, mcpName, cfg.moscOpts...) + o.Expect(err).NotTo(o.HaveOccurred(), "Error creating the MachineOSConfig resource") + logger.Infof("OK!\n") + + env.MOSC = mosc + return env +} + +// NewOCBTestEnvWithCompactPool uses the compact-compatible pool and creates a MOSC. +// The caller must defer env.Cleanup() to ensure proper teardown. +func NewOCBTestEnvWithCompactPool(oc *exutil.CLI, opts ...OCBSetupOption) *OCBTestEnv { + cfg := applyOCBOptions(opts) + mcp := GetCompactCompatiblePool(oc.AsAdmin()) + + env := &OCBTestEnv{ + OC: oc, + MCP: mcp, + } + + if cfg.skipMOSC { + return env + } + + exutil.By("Configure OCB functionality for the " + mcp.GetName() + " MCP") + mosc, err := CreateMOSC(oc.AsAdmin(), mcp.GetName(), mcp.GetName(), cfg.moscOpts...) + o.Expect(err).NotTo(o.HaveOccurred(), "Error creating the MachineOSConfig resource") + logger.Infof("OK!\n") + + env.MOSC = mosc + return env +} + +// Cleanup tears down the MOSC (via DisableOCL) and deletes the custom MCP if applicable. +func (env *OCBTestEnv) Cleanup() { + if env.MOSC != nil { + DisableOCL(env.MOSC) + } + if env.isCustomMCP && env.MCP != nil { + env.MCP.delete() + } +} + +// CleanupMOSCOnly removes only the MOSC without deleting the custom MCP. +func (env *OCBTestEnv) CleanupMOSCOnly() { + if env.MOSC != nil { + DisableOCL(env.MOSC) + } +} + +// CleanupMCPOnly deletes the custom MCP. +func (env *OCBTestEnv) CleanupMCPOnly() { + if env.isCustomMCP && env.MCP != nil { + env.MCP.delete() + } +} + +// ValidateAndCleanup validates the MOSC, cleans it up, and checks garbage collection. +func (env *OCBTestEnv) ValidateAndCleanup(checkers []Checker) { + ValidateSuccessfulMOSC(env.MOSC, checkers) + + exutil.By("Remove the MachineOSConfig resource") + o.Expect(env.MOSC.CleanupAndDelete()).To(o.Succeed(), "Error cleaning up %s", env.MOSC) + logger.Infof("OK!\n") + + ValidateMOSCIsGarbageCollected(env.MOSC, env.MCP) + + exutil.AssertAllPodsToBeReady(env.OC.AsAdmin(), MachineConfigNamespace) + logger.Infof("OK!\n") +} diff --git a/test/extended-priv/mco_osimagestream.go b/test/extended-priv/mco_osimagestream.go index fc6a69190e..37efb70c64 100644 --- a/test/extended-priv/mco_osimagestream.go +++ b/test/extended-priv/mco_osimagestream.go @@ -755,7 +755,7 @@ func testMOSBTriggeredOnStreamChange(oc *exutil.CLI, osis *OSImageStream, initia logger.Infof("OK!\n") exutil.By("Enable OCL functionality for the custom MCP") - mosc, err := CreateMachineOSConfigUsingExternalOrInternalRegistry(oc.AsAdmin(), MachineConfigNamespace, customMcpName, customMcpName, nil) + mosc, err := CreateMOSC(oc.AsAdmin(), customMcpName, customMcpName) o.Expect(err).NotTo(o.HaveOccurred(), "Error creating MachineOSConfig %s", customMcpName) defer mosc.CleanupAndDelete() logger.Infof("OK!\n")