diff --git a/test/extended/machine_config/helpers.go b/test/extended/machine_config/helpers.go index 01c482628702..170377860170 100644 --- a/test/extended/machine_config/helpers.go +++ b/test/extended/machine_config/helpers.go @@ -21,6 +21,7 @@ import ( corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" "k8s.io/kubernetes/test/e2e/framework" e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper" "k8s.io/utils/ptr" @@ -317,3 +318,16 @@ func ApplyBootImageFixture(oc *exutil.CLI, fixture string) { WaitForMachineConfigurationStatusUpdate(oc) } + +// Get nodes from a Pool +func getNodesForPool(ctx context.Context, oc *exutil.CLI, kubeClient *kubernetes.Clientset, pool *mcfgv1.MachineConfigPool) (*corev1.NodeList, error) { + selector, err := metav1.LabelSelectorAsSelector(pool.Spec.NodeSelector) + if err != nil { + return nil, fmt.Errorf("invalid label selector: %w", err) + } + nodes, err := kubeClient.CoreV1().Nodes().List(ctx, metav1.ListOptions{LabelSelector: selector.String()}) + if err != nil { + return nil, fmt.Errorf("couldnt get nodes for mcp: %w", err) + } + return nodes, nil +} diff --git a/test/extended/machine_config/pinnedimages.go b/test/extended/machine_config/pinnedimages.go new file mode 100644 index 000000000000..fdbf54a79ded --- /dev/null +++ b/test/extended/machine_config/pinnedimages.go @@ -0,0 +1,254 @@ +package machine_config + +import ( + "context" + "fmt" + "io/ioutil" + "path/filepath" + "strings" + "time" + + g "github.com/onsi/ginkgo/v2" + o "github.com/onsi/gomega" + + mcfgv1alpha1 "github.com/openshift/api/machineconfiguration/v1alpha1" + mcClient "github.com/openshift/client-go/machineconfiguration/clientset/versioned" + exutil "github.com/openshift/origin/test/extended/util" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/test/e2e/framework" + "sigs.k8s.io/yaml" +) + +// This test is [Serial] because it modifies the state of the images present on Node in each test. +var _ = g.Describe("[sig-mco][OCPFeatureGate:PinnedImages][OCPFeatureGate:MachineConfigNodes][Serial]", func() { + defer g.GinkgoRecover() + var ( + MCOPinnedImageBaseDir = exutil.FixturePath("testdata", "machine_config", "pinnedimage") + MCOMachineConfigPoolBaseDir = exutil.FixturePath("testdata", "machine_config", "machineconfigpool") + MCOKubeletConfigBaseDir = exutil.FixturePath("testdata", "machine_config", "kubeletconfig") + + pinnedImageSetFixture = filepath.Join(MCOPinnedImageBaseDir, "pis.yaml") + customMCPFixture = filepath.Join(MCOMachineConfigPoolBaseDir, "customMCP.yaml") + customMCPpinnedImageSetFixture = filepath.Join(MCOPinnedImageBaseDir, "customMCPpis.yaml") + customGCMCPpinnedImageSetFixture = filepath.Join(MCOPinnedImageBaseDir, "customGCMCPpis.yaml") + customGcKCFixture = filepath.Join(MCOKubeletConfigBaseDir, "gcKC.yaml") + invalidPinnedImageSetFixture = filepath.Join(MCOPinnedImageBaseDir, "invalidPis.yaml") + + oc = exutil.NewCLIWithoutNamespace("machine-config") + ) + // Ensure each test pins a separate image, since we are not deleting them after each + + g.It("All Nodes in a custom Pool should have the PinnedImages even after Garbage Collection [apigroup:machineconfiguration.openshift.io]", func() { + kubeClient, err := kubernetes.NewForConfig(oc.KubeFramework().ClientConfig()) + o.Expect(err).NotTo(o.HaveOccurred(), "Get KubeClient") + + // Create custom MCP + err = oc.Run("apply").Args("-f", customMCPFixture).Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + defer deleteMCP(oc, "custom") + + // Add node to pool + nodes, err := kubeClient.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{LabelSelector: labels.SelectorFromSet(labels.Set{"node-role.kubernetes.io/worker": ""}).String()}) + o.Expect(err).NotTo(o.HaveOccurred(), "Get all nodes") + o.Expect(nodes.Items).NotTo(o.BeEmpty()) + err = oc.AsAdmin().Run("label").Args("node", nodes.Items[0].Name, "node-role.kubernetes.io/custom=").Execute() + o.Expect(err).NotTo(o.HaveOccurred(), "Label node") + defer unlabelNode(oc, nodes.Items[0].Name) + + // Apply KC to Pool + err = oc.Run("apply").Args("-f", customGcKCFixture).Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + defer deleteKC(oc, "custom-gc-config") + + SimplePISTest(oc, kubeClient, customGCMCPpinnedImageSetFixture, true) + }) + + g.It("All Nodes in a Custom Pool should have the PinnedImages in PIS [apigroup:machineconfiguration.openshift.io]", func() { + kubeClient, err := kubernetes.NewForConfig(oc.KubeFramework().ClientConfig()) + o.Expect(err).NotTo(o.HaveOccurred(), "Get KubeClient") + + // Create custom MCP + err = oc.Run("apply").Args("-f", customMCPFixture).Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + defer deleteMCP(oc, "custom") + + // Add node to pool + nodes, err := kubeClient.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{LabelSelector: labels.SelectorFromSet(labels.Set{"node-role.kubernetes.io/worker": ""}).String()}) + o.Expect(err).NotTo(o.HaveOccurred(), "Get all nodes") + o.Expect(nodes.Items).NotTo(o.BeEmpty()) + err = oc.AsAdmin().Run("label").Args("node", nodes.Items[0].Name, "node-role.kubernetes.io/custom=").Execute() + o.Expect(err).NotTo(o.HaveOccurred(), "Label node") + defer unlabelNode(oc, nodes.Items[0].Name) + + SimplePISTest(oc, kubeClient, customMCPpinnedImageSetFixture, true) + }) + + g.It("All Nodes in a standard Pool should have the PinnedImages PIS [apigroup:machineconfiguration.openshift.io]", func() { + kubeClient, err := kubernetes.NewForConfig(oc.KubeFramework().ClientConfig()) + o.Expect(err).NotTo(o.HaveOccurred(), "Get KubeClient") + + SimplePISTest(oc, kubeClient, pinnedImageSetFixture, true) + }) + + g.It("Invalid PIS leads to degraded MCN in a standard Pool [apigroup:machineconfiguration.openshift.io]", func() { + kubeClient, err := kubernetes.NewForConfig(oc.KubeFramework().ClientConfig()) + o.Expect(err).NotTo(o.HaveOccurred(), "Get KubeClient") + + SimplePISTest(oc, kubeClient, invalidPinnedImageSetFixture, false) + }) + + g.It("Invalid PIS leads to degraded MCN in a custom Pool [apigroup:machineconfiguration.openshift.io]", func() { + kubeClient, err := kubernetes.NewForConfig(oc.KubeFramework().ClientConfig()) + o.Expect(err).NotTo(o.HaveOccurred(), "Get KubeClient") + + // Create custom MCP + err = oc.Run("apply").Args("-f", customMCPFixture).Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + defer deleteMCP(oc, "custom") + + // Add node to pool + nodes, err := kubeClient.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{LabelSelector: labels.SelectorFromSet(labels.Set{"node-role.kubernetes.io/worker": ""}).String()}) + o.Expect(err).NotTo(o.HaveOccurred(), "Get all nodes") + o.Expect(nodes.Items).NotTo(o.BeEmpty()) + err = oc.AsAdmin().Run("label").Args("node", nodes.Items[0].Name, "node-role.kubernetes.io/custom=").Execute() + o.Expect(err).NotTo(o.HaveOccurred(), "Label node") + defer unlabelNode(oc, nodes.Items[0].Name) + + SimplePISTest(oc, kubeClient, invalidPinnedImageSetFixture, false) + }) + +}) + +func SimplePISTest(oc *exutil.CLI, kubeClient *kubernetes.Clientset, fixture string, success bool) { + clientSet, err := mcClient.NewForConfig(oc.KubeFramework().ClientConfig()) + o.Expect(err).NotTo(o.HaveOccurred()) + + pis, err := getPISFromFixture(fixture) + o.Expect(err).NotTo(o.HaveOccurred()) + + err = oc.Run("apply").Args("-f", fixture).Execute() + o.Expect(err).NotTo(o.HaveOccurred(), "Applied PIS") + defer deletePIS(oc, pis.Name) + + waitTime := time.Minute * 20 + ctx, cancel := context.WithTimeout(context.Background(), waitTime) + defer cancel() + + err = waitForPISStatusX(ctx, oc, kubeClient, clientSet, pis.Name, success) + o.Expect(err).NotTo(o.HaveOccurred(), "Checking status of PIS") +} + +func detectXCondition(oc *exutil.CLI, node corev1.Node, mcn *mcfgv1alpha1.MachineConfigNode, appliedPIS *mcfgv1alpha1.PinnedImageSet, detectingSuccess bool) (bool, bool, error) { + if detectingSuccess { + for _, cond := range mcn.Status.Conditions { + if mcfgv1alpha1.StateProgress(cond.Type) == mcfgv1alpha1.MachineConfigNodePinnedImageSetsDegraded && cond.Status == "True" { + return false, true, fmt.Errorf("PIS degraded for MCN %s with reason: %s and message: %s", mcn.Name, cond.Reason, cond.Message) + } + + if mcfgv1alpha1.StateProgress(cond.Type) == mcfgv1alpha1.MachineConfigNodePinnedImageSetsProgressing && cond.Status == "True" { + return false, false, nil + } + } + for _, img := range appliedPIS.Spec.PinnedImages { + crictlStatus, err := exutil.DebugNodeRetryWithOptionsAndChroot(oc, node.Name, "openshift-machine-config-operator", "crictl", "inspecti", img.Name) + if err != nil { + return false, false, fmt.Errorf("failed to execute `crictl inspecti %s` on node %s: %w", img.Name, node.Name, err) + } + if !strings.Contains(crictlStatus, "imageSpec") { + return false, false, fmt.Errorf("Image %s not present on node %s: %w", img.Name, node.Name, err) + } + } + return true, false, nil + } else { + for _, cond := range mcn.Status.Conditions { + if mcfgv1alpha1.StateProgress(cond.Type) == mcfgv1alpha1.MachineConfigNodePinnedImageSetsDegraded && cond.Status == "True" { + continue + } + if mcfgv1alpha1.StateProgress(cond.Type) == mcfgv1alpha1.MachineConfigNodePinnedImageSetsProgressing && cond.Status == "True" { + return false, false, nil + } + } + return true, false, nil + } +} + +func waitForPISStatusX(ctx context.Context, oc *exutil.CLI, kubeClient *kubernetes.Clientset, clientSet *mcClient.Clientset, pisName string, success bool) error { + return wait.PollUntilContextCancel(ctx, time.Second, true, func(ctx context.Context) (done bool, err error) { + // Wait for PIS object to get created + appliedPIS, err := clientSet.MachineconfigurationV1alpha1().PinnedImageSets().Get(context.TODO(), pisName, metav1.GetOptions{}) + if err != nil { + return false, fmt.Errorf("PIS Object not created yet: %w", err) + } + + pool, err := clientSet.MachineconfigurationV1().MachineConfigPools().Get(ctx, appliedPIS.Labels["machineconfiguration.openshift.io/role"], metav1.GetOptions{}) + if err != nil { + return false, fmt.Errorf("failed to get MCP mentioned in PIS: %w", err) + } + + nodes, err := getNodesForPool(ctx, oc, kubeClient, pool) + if err != nil { + return false, fmt.Errorf("failed to get Nodes from MCP %q mentioned in PIS: %w", pool.Name, err) + } + + doneNodes := 0 + for _, node := range nodes.Items { + mcn, err := clientSet.MachineconfigurationV1alpha1().MachineConfigNodes().Get(ctx, node.Name, metav1.GetOptions{}) + if err != nil { + return false, fmt.Errorf("failed to get mcn: %w", err) + } + toContinue, isFatal, err := detectXCondition(oc, node, mcn, appliedPIS, success) + if !toContinue { + if isFatal { + return true, err + } else { + if err != nil { + framework.Logf("Retrying PIS Status with non-fatal error: %v", err) + } + return false, nil + } + } + doneNodes += 1 + } + if doneNodes == len(nodes.Items) { + return true, nil + } + + return false, nil + }) +} + +func unlabelNode(oc *exutil.CLI, name string) error { + return oc.AsAdmin().Run("label").Args("node", name, "node-role.kubernetes.io/custom-").Execute() +} + +func deleteKC(oc *exutil.CLI, name string) error { + return oc.Run("delete").Args("kubeletconfig", name).Execute() +} + +func deleteMCP(oc *exutil.CLI, name string) error { + return oc.Run("delete").Args("mcp", name).Execute() +} + +func deletePIS(oc *exutil.CLI, name string) error { + return oc.Run("delete").Args("pinnedimageset", name).Execute() +} + +func getPISFromFixture(path string) (*mcfgv1alpha1.PinnedImageSet, error) { + data, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + + ob := new(mcfgv1alpha1.PinnedImageSet) + err = yaml.Unmarshal(data, ob) + if err != nil { + return nil, err + } + + return ob, nil +} diff --git a/test/extended/testdata/bindata.go b/test/extended/testdata/bindata.go index ed0f5791d68b..dfcca1f4fc84 100644 --- a/test/extended/testdata/bindata.go +++ b/test/extended/testdata/bindata.go @@ -419,10 +419,16 @@ // test/extended/testdata/ldap/ldapserver-service.yaml // test/extended/testdata/long_names/Dockerfile // test/extended/testdata/long_names/fixture.json +// test/extended/testdata/machine_config/kubeletconfig/gcKC.yaml +// test/extended/testdata/machine_config/machineconfigpool/customMCP.yaml // test/extended/testdata/machine_config/machineconfigurations/managedbootimages-all.yaml // test/extended/testdata/machine_config/machineconfigurations/managedbootimages-empty.yaml // test/extended/testdata/machine_config/machineconfigurations/managedbootimages-none.yaml // test/extended/testdata/machine_config/machineconfigurations/managedbootimages-partial.yaml +// test/extended/testdata/machine_config/pinnedimage/customGCMCPpis.yaml +// test/extended/testdata/machine_config/pinnedimage/customMCPpis.yaml +// test/extended/testdata/machine_config/pinnedimage/invalidPis.yaml +// test/extended/testdata/machine_config/pinnedimage/pis.yaml // test/extended/testdata/marketplace/csc/02-csc.yaml // test/extended/testdata/marketplace/opsrc/02-opsrc.yaml // test/extended/testdata/mixed-api-versions.yaml @@ -49020,6 +49026,65 @@ func testExtendedTestdataLong_namesFixtureJson() (*asset, error) { return a, nil } +var _testExtendedTestdataMachine_configKubeletconfigGckcYaml = []byte(`apiVersion: machineconfiguration.openshift.io/v1 +kind: KubeletConfig +metadata: + name: custom-gc-config +spec: + machineConfigPoolSelector: + matchLabels: + pools.operator.machineconfiguration.openshift.io/custom: "" + kubeletConfig: + imageMinimumGCAge: 0s + imageGCHighThresholdPercent: 2 + imageGCLowThresholdPercent: 1 +`) + +func testExtendedTestdataMachine_configKubeletconfigGckcYamlBytes() ([]byte, error) { + return _testExtendedTestdataMachine_configKubeletconfigGckcYaml, nil +} + +func testExtendedTestdataMachine_configKubeletconfigGckcYaml() (*asset, error) { + bytes, err := testExtendedTestdataMachine_configKubeletconfigGckcYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "test/extended/testdata/machine_config/kubeletconfig/gcKC.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _testExtendedTestdataMachine_configMachineconfigpoolCustommcpYaml = []byte(`apiVersion: machineconfiguration.openshift.io/v1 +kind: MachineConfigPool +metadata: + name: custom + labels: + pools.operator.machineconfiguration.openshift.io/custom: "" +spec: + machineConfigSelector: + matchExpressions: + - {key: machineconfiguration.openshift.io/role, operator: In, values: [worker,custom]} + nodeSelector: + matchLabels: + node-role.kubernetes.io/custom: "" +`) + +func testExtendedTestdataMachine_configMachineconfigpoolCustommcpYamlBytes() ([]byte, error) { + return _testExtendedTestdataMachine_configMachineconfigpoolCustommcpYaml, nil +} + +func testExtendedTestdataMachine_configMachineconfigpoolCustommcpYaml() (*asset, error) { + bytes, err := testExtendedTestdataMachine_configMachineconfigpoolCustommcpYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "test/extended/testdata/machine_config/machineconfigpool/customMCP.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + var _testExtendedTestdataMachine_configMachineconfigurationsManagedbootimagesAllYaml = []byte(`apiVersion: operator.openshift.io/v1 kind: MachineConfiguration metadata: @@ -49142,6 +49207,110 @@ func testExtendedTestdataMachine_configMachineconfigurationsManagedbootimagesPar return a, nil } +var _testExtendedTestdataMachine_configPinnedimageCustomgcmcppisYaml = []byte(`apiVersion: machineconfiguration.openshift.io/v1alpha1 +kind: PinnedImageSet +metadata: + name: test-pinned + labels: + machineconfiguration.openshift.io/role: "custom" +spec: + pinnedImages: + - name: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:e43b2ef4fbc42dbcbea5d67f57f3feed38f6b45fb712c99acb06490103e277a9 +`) + +func testExtendedTestdataMachine_configPinnedimageCustomgcmcppisYamlBytes() ([]byte, error) { + return _testExtendedTestdataMachine_configPinnedimageCustomgcmcppisYaml, nil +} + +func testExtendedTestdataMachine_configPinnedimageCustomgcmcppisYaml() (*asset, error) { + bytes, err := testExtendedTestdataMachine_configPinnedimageCustomgcmcppisYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "test/extended/testdata/machine_config/pinnedimage/customGCMCPpis.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _testExtendedTestdataMachine_configPinnedimageCustommcppisYaml = []byte(`apiVersion: machineconfiguration.openshift.io/v1alpha1 +kind: PinnedImageSet +metadata: + name: test-pinned + labels: + machineconfiguration.openshift.io/role: "custom" +spec: + pinnedImages: + - name: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:479f8a99cbe432551448776965aac1f44501c08aa01539d77ab5976fdbbe1c83 +`) + +func testExtendedTestdataMachine_configPinnedimageCustommcppisYamlBytes() ([]byte, error) { + return _testExtendedTestdataMachine_configPinnedimageCustommcppisYaml, nil +} + +func testExtendedTestdataMachine_configPinnedimageCustommcppisYaml() (*asset, error) { + bytes, err := testExtendedTestdataMachine_configPinnedimageCustommcppisYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "test/extended/testdata/machine_config/pinnedimage/customMCPpis.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _testExtendedTestdataMachine_configPinnedimageInvalidpisYaml = []byte(`apiVersion: machineconfiguration.openshift.io/v1alpha1 +kind: PinnedImageSet +metadata: + name: test-pinned + labels: + machineconfiguration.openshift.io/role: "worker" +spec: + pinnedImages: + - name: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:86d26e7ebcccd6f07a75db5b1e56283b25c2ee1c6a755d6ffc5a4d59beb9cdef +`) + +func testExtendedTestdataMachine_configPinnedimageInvalidpisYamlBytes() ([]byte, error) { + return _testExtendedTestdataMachine_configPinnedimageInvalidpisYaml, nil +} + +func testExtendedTestdataMachine_configPinnedimageInvalidpisYaml() (*asset, error) { + bytes, err := testExtendedTestdataMachine_configPinnedimageInvalidpisYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "test/extended/testdata/machine_config/pinnedimage/invalidPis.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _testExtendedTestdataMachine_configPinnedimagePisYaml = []byte(`apiVersion: machineconfiguration.openshift.io/v1alpha1 +kind: PinnedImageSet +metadata: + name: test-pinned + labels: + machineconfiguration.openshift.io/role: "worker" +spec: + pinnedImages: + - name: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:86d26e7ebcccd6f07a75db5b1e56283b25c2ee1c6a755d6ffc5a4d59beb9c504 +`) + +func testExtendedTestdataMachine_configPinnedimagePisYamlBytes() ([]byte, error) { + return _testExtendedTestdataMachine_configPinnedimagePisYaml, nil +} + +func testExtendedTestdataMachine_configPinnedimagePisYaml() (*asset, error) { + bytes, err := testExtendedTestdataMachine_configPinnedimagePisYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "test/extended/testdata/machine_config/pinnedimage/pis.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + var _testExtendedTestdataMarketplaceCsc02CscYaml = []byte(`apiVersion: template.openshift.io/v1 kind: Template metadata: @@ -55774,10 +55943,16 @@ var _bindata = map[string]func() (*asset, error){ "test/extended/testdata/ldap/ldapserver-service.yaml": testExtendedTestdataLdapLdapserverServiceYaml, "test/extended/testdata/long_names/Dockerfile": testExtendedTestdataLong_namesDockerfile, "test/extended/testdata/long_names/fixture.json": testExtendedTestdataLong_namesFixtureJson, + "test/extended/testdata/machine_config/kubeletconfig/gcKC.yaml": testExtendedTestdataMachine_configKubeletconfigGckcYaml, + "test/extended/testdata/machine_config/machineconfigpool/customMCP.yaml": testExtendedTestdataMachine_configMachineconfigpoolCustommcpYaml, "test/extended/testdata/machine_config/machineconfigurations/managedbootimages-all.yaml": testExtendedTestdataMachine_configMachineconfigurationsManagedbootimagesAllYaml, "test/extended/testdata/machine_config/machineconfigurations/managedbootimages-empty.yaml": testExtendedTestdataMachine_configMachineconfigurationsManagedbootimagesEmptyYaml, "test/extended/testdata/machine_config/machineconfigurations/managedbootimages-none.yaml": testExtendedTestdataMachine_configMachineconfigurationsManagedbootimagesNoneYaml, "test/extended/testdata/machine_config/machineconfigurations/managedbootimages-partial.yaml": testExtendedTestdataMachine_configMachineconfigurationsManagedbootimagesPartialYaml, + "test/extended/testdata/machine_config/pinnedimage/customGCMCPpis.yaml": testExtendedTestdataMachine_configPinnedimageCustomgcmcppisYaml, + "test/extended/testdata/machine_config/pinnedimage/customMCPpis.yaml": testExtendedTestdataMachine_configPinnedimageCustommcppisYaml, + "test/extended/testdata/machine_config/pinnedimage/invalidPis.yaml": testExtendedTestdataMachine_configPinnedimageInvalidpisYaml, + "test/extended/testdata/machine_config/pinnedimage/pis.yaml": testExtendedTestdataMachine_configPinnedimagePisYaml, "test/extended/testdata/marketplace/csc/02-csc.yaml": testExtendedTestdataMarketplaceCsc02CscYaml, "test/extended/testdata/marketplace/opsrc/02-opsrc.yaml": testExtendedTestdataMarketplaceOpsrc02OpsrcYaml, "test/extended/testdata/mixed-api-versions.yaml": testExtendedTestdataMixedApiVersionsYaml, @@ -56520,12 +56695,24 @@ var _bintree = &bintree{nil, map[string]*bintree{ "fixture.json": {testExtendedTestdataLong_namesFixtureJson, map[string]*bintree{}}, }}, "machine_config": {nil, map[string]*bintree{ + "kubeletconfig": {nil, map[string]*bintree{ + "gcKC.yaml": {testExtendedTestdataMachine_configKubeletconfigGckcYaml, map[string]*bintree{}}, + }}, + "machineconfigpool": {nil, map[string]*bintree{ + "customMCP.yaml": {testExtendedTestdataMachine_configMachineconfigpoolCustommcpYaml, map[string]*bintree{}}, + }}, "machineconfigurations": {nil, map[string]*bintree{ "managedbootimages-all.yaml": {testExtendedTestdataMachine_configMachineconfigurationsManagedbootimagesAllYaml, map[string]*bintree{}}, "managedbootimages-empty.yaml": {testExtendedTestdataMachine_configMachineconfigurationsManagedbootimagesEmptyYaml, map[string]*bintree{}}, "managedbootimages-none.yaml": {testExtendedTestdataMachine_configMachineconfigurationsManagedbootimagesNoneYaml, map[string]*bintree{}}, "managedbootimages-partial.yaml": {testExtendedTestdataMachine_configMachineconfigurationsManagedbootimagesPartialYaml, map[string]*bintree{}}, }}, + "pinnedimage": {nil, map[string]*bintree{ + "customGCMCPpis.yaml": {testExtendedTestdataMachine_configPinnedimageCustomgcmcppisYaml, map[string]*bintree{}}, + "customMCPpis.yaml": {testExtendedTestdataMachine_configPinnedimageCustommcppisYaml, map[string]*bintree{}}, + "invalidPis.yaml": {testExtendedTestdataMachine_configPinnedimageInvalidpisYaml, map[string]*bintree{}}, + "pis.yaml": {testExtendedTestdataMachine_configPinnedimagePisYaml, map[string]*bintree{}}, + }}, }}, "marketplace": {nil, map[string]*bintree{ "csc": {nil, map[string]*bintree{ diff --git a/test/extended/testdata/machine_config/kubeletconfig/gcKC.yaml b/test/extended/testdata/machine_config/kubeletconfig/gcKC.yaml new file mode 100644 index 000000000000..cca3734938e4 --- /dev/null +++ b/test/extended/testdata/machine_config/kubeletconfig/gcKC.yaml @@ -0,0 +1,12 @@ +apiVersion: machineconfiguration.openshift.io/v1 +kind: KubeletConfig +metadata: + name: custom-gc-config +spec: + machineConfigPoolSelector: + matchLabels: + pools.operator.machineconfiguration.openshift.io/custom: "" + kubeletConfig: + imageMinimumGCAge: 0s + imageGCHighThresholdPercent: 2 + imageGCLowThresholdPercent: 1 diff --git a/test/extended/testdata/machine_config/machineconfigpool/customMCP.yaml b/test/extended/testdata/machine_config/machineconfigpool/customMCP.yaml new file mode 100644 index 000000000000..ff86b303ffc1 --- /dev/null +++ b/test/extended/testdata/machine_config/machineconfigpool/customMCP.yaml @@ -0,0 +1,13 @@ +apiVersion: machineconfiguration.openshift.io/v1 +kind: MachineConfigPool +metadata: + name: custom + labels: + pools.operator.machineconfiguration.openshift.io/custom: "" +spec: + machineConfigSelector: + matchExpressions: + - {key: machineconfiguration.openshift.io/role, operator: In, values: [worker,custom]} + nodeSelector: + matchLabels: + node-role.kubernetes.io/custom: "" diff --git a/test/extended/testdata/machine_config/pinnedimage/customGCMCPpis.yaml b/test/extended/testdata/machine_config/pinnedimage/customGCMCPpis.yaml new file mode 100644 index 000000000000..46f98fb4bc09 --- /dev/null +++ b/test/extended/testdata/machine_config/pinnedimage/customGCMCPpis.yaml @@ -0,0 +1,9 @@ +apiVersion: machineconfiguration.openshift.io/v1alpha1 +kind: PinnedImageSet +metadata: + name: test-pinned + labels: + machineconfiguration.openshift.io/role: "custom" +spec: + pinnedImages: + - name: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:e43b2ef4fbc42dbcbea5d67f57f3feed38f6b45fb712c99acb06490103e277a9 diff --git a/test/extended/testdata/machine_config/pinnedimage/customMCPpis.yaml b/test/extended/testdata/machine_config/pinnedimage/customMCPpis.yaml new file mode 100644 index 000000000000..5a69125d94be --- /dev/null +++ b/test/extended/testdata/machine_config/pinnedimage/customMCPpis.yaml @@ -0,0 +1,9 @@ +apiVersion: machineconfiguration.openshift.io/v1alpha1 +kind: PinnedImageSet +metadata: + name: test-pinned + labels: + machineconfiguration.openshift.io/role: "custom" +spec: + pinnedImages: + - name: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:479f8a99cbe432551448776965aac1f44501c08aa01539d77ab5976fdbbe1c83 diff --git a/test/extended/testdata/machine_config/pinnedimage/invalidPis.yaml b/test/extended/testdata/machine_config/pinnedimage/invalidPis.yaml new file mode 100644 index 000000000000..f7cfabe825c7 --- /dev/null +++ b/test/extended/testdata/machine_config/pinnedimage/invalidPis.yaml @@ -0,0 +1,9 @@ +apiVersion: machineconfiguration.openshift.io/v1alpha1 +kind: PinnedImageSet +metadata: + name: test-pinned + labels: + machineconfiguration.openshift.io/role: "worker" +spec: + pinnedImages: + - name: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:86d26e7ebcccd6f07a75db5b1e56283b25c2ee1c6a755d6ffc5a4d59beb9cdef diff --git a/test/extended/testdata/machine_config/pinnedimage/pis.yaml b/test/extended/testdata/machine_config/pinnedimage/pis.yaml new file mode 100644 index 000000000000..a1b3b1071e9c --- /dev/null +++ b/test/extended/testdata/machine_config/pinnedimage/pis.yaml @@ -0,0 +1,9 @@ +apiVersion: machineconfiguration.openshift.io/v1alpha1 +kind: PinnedImageSet +metadata: + name: test-pinned + labels: + machineconfiguration.openshift.io/role: "worker" +spec: + pinnedImages: + - name: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:86d26e7ebcccd6f07a75db5b1e56283b25c2ee1c6a755d6ffc5a4d59beb9c504 diff --git a/test/extended/util/annotate/generated/zz_generated.annotations.go b/test/extended/util/annotate/generated/zz_generated.annotations.go index 49c3b948a50b..502d19c80108 100644 --- a/test/extended/util/annotate/generated/zz_generated.annotations.go +++ b/test/extended/util/annotate/generated/zz_generated.annotations.go @@ -1379,6 +1379,16 @@ var Annotations = map[string]string{ "[sig-mco][OCPFeatureGate:ManagedBootImages][Serial] Should update boot images only on MachineSets that are opted in [apigroup:machineconfiguration.openshift.io]": " [Suite:openshift/conformance/serial]", + "[sig-mco][OCPFeatureGate:PinnedImages][OCPFeatureGate:MachineConfigNodes][Serial] All Nodes in a Custom Pool should have the PinnedImages in PIS [apigroup:machineconfiguration.openshift.io]": " [Suite:openshift/conformance/serial]", + + "[sig-mco][OCPFeatureGate:PinnedImages][OCPFeatureGate:MachineConfigNodes][Serial] All Nodes in a custom Pool should have the PinnedImages even after Garbage Collection [apigroup:machineconfiguration.openshift.io]": " [Suite:openshift/conformance/serial]", + + "[sig-mco][OCPFeatureGate:PinnedImages][OCPFeatureGate:MachineConfigNodes][Serial] All Nodes in a standard Pool should have the PinnedImages PIS [apigroup:machineconfiguration.openshift.io]": " [Suite:openshift/conformance/serial]", + + "[sig-mco][OCPFeatureGate:PinnedImages][OCPFeatureGate:MachineConfigNodes][Serial] Invalid PIS leads to degraded MCN in a custom Pool [apigroup:machineconfiguration.openshift.io]": " [Suite:openshift/conformance/serial]", + + "[sig-mco][OCPFeatureGate:PinnedImages][OCPFeatureGate:MachineConfigNodes][Serial] Invalid PIS leads to degraded MCN in a standard Pool [apigroup:machineconfiguration.openshift.io]": " [Suite:openshift/conformance/serial]", + "[sig-network-edge] DNS should answer A and AAAA queries for a dual-stack service [apigroup:config.openshift.io]": " [Suite:openshift/conformance/parallel]", "[sig-network-edge] DNS should answer endpoint and wildcard queries for the cluster": " [Disabled:Broken]", diff --git a/zz_generated.manifests/test-reporting.yaml b/zz_generated.manifests/test-reporting.yaml index ecaae900dc10..c41e58310ce2 100644 --- a/zz_generated.manifests/test-reporting.yaml +++ b/zz_generated.manifests/test-reporting.yaml @@ -98,6 +98,19 @@ spec: - testName: '[sig-imageregistry][OCPFeatureGate:ImageStreamImportMode][Serial] ImageStream API import mode should be PreserveOriginal or Legacy depending on desired.architecture field in the CV [apigroup:image.openshift.io]' + - featureGate: MachineConfigNodes + tests: + - testName: '[sig-mco][OCPFeatureGate:PinnedImages][OCPFeatureGate:MachineConfigNodes][Serial] + All Nodes in a Custom Pool should have the PinnedImages in PIS [apigroup:machineconfiguration.openshift.io]' + - testName: '[sig-mco][OCPFeatureGate:PinnedImages][OCPFeatureGate:MachineConfigNodes][Serial] + All Nodes in a custom Pool should have the PinnedImages even after Garbage + Collection [apigroup:machineconfiguration.openshift.io]' + - testName: '[sig-mco][OCPFeatureGate:PinnedImages][OCPFeatureGate:MachineConfigNodes][Serial] + All Nodes in a standard Pool should have the PinnedImages PIS [apigroup:machineconfiguration.openshift.io]' + - testName: '[sig-mco][OCPFeatureGate:PinnedImages][OCPFeatureGate:MachineConfigNodes][Serial] + Invalid PIS leads to degraded MCN in a custom Pool [apigroup:machineconfiguration.openshift.io]' + - testName: '[sig-mco][OCPFeatureGate:PinnedImages][OCPFeatureGate:MachineConfigNodes][Serial] + Invalid PIS leads to degraded MCN in a standard Pool [apigroup:machineconfiguration.openshift.io]' - featureGate: ManagedBootImages tests: - testName: '[sig-mco][OCPFeatureGate:ManagedBootImages][Serial] Should degrade @@ -456,6 +469,19 @@ spec: networks and persistent ips configured created using [OCPFeatureGate:NetworkSegmentation] UserDefinedNetwork [Suite:openshift/network/virtualization] should keep ip when the VMI attached to a secondary UDN is migrated between nodes' + - featureGate: PinnedImages + tests: + - testName: '[sig-mco][OCPFeatureGate:PinnedImages][OCPFeatureGate:MachineConfigNodes][Serial] + All Nodes in a Custom Pool should have the PinnedImages in PIS [apigroup:machineconfiguration.openshift.io]' + - testName: '[sig-mco][OCPFeatureGate:PinnedImages][OCPFeatureGate:MachineConfigNodes][Serial] + All Nodes in a custom Pool should have the PinnedImages even after Garbage + Collection [apigroup:machineconfiguration.openshift.io]' + - testName: '[sig-mco][OCPFeatureGate:PinnedImages][OCPFeatureGate:MachineConfigNodes][Serial] + All Nodes in a standard Pool should have the PinnedImages PIS [apigroup:machineconfiguration.openshift.io]' + - testName: '[sig-mco][OCPFeatureGate:PinnedImages][OCPFeatureGate:MachineConfigNodes][Serial] + Invalid PIS leads to degraded MCN in a custom Pool [apigroup:machineconfiguration.openshift.io]' + - testName: '[sig-mco][OCPFeatureGate:PinnedImages][OCPFeatureGate:MachineConfigNodes][Serial] + Invalid PIS leads to degraded MCN in a standard Pool [apigroup:machineconfiguration.openshift.io]' - featureGate: SELinuxMount tests: - testName: '[sig-storage] CSI Mock selinux on mount SELinuxMount [LinuxOnly]