Skip to content

Commit

Permalink
cnf ran: Add siteconfig operator pod restart and cluster instance del…
Browse files Browse the repository at this point in the history
…ete tests
  • Loading branch information
mpmaruthu committed Sep 25, 2024
1 parent 1b4a12d commit 0cb9f80
Show file tree
Hide file tree
Showing 6 changed files with 277 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ linters-settings:
linters:
disable:
- ireturn
- wsl
- structcheck
enable:
- asciicheck
Expand Down Expand Up @@ -141,7 +142,6 @@ linters:
- unparam
- unused
- varnamelen
- wsl
- nlreturn

output:
Expand Down
12 changes: 12 additions & 0 deletions tests/cnf/ran/gitopsztp/internal/tsparams/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ const (
LabelMachineConfigTestCases = "ztp-machine-config"
// LabelSpokeCheckerTests is the label for a particular set of test cases.
LabelSpokeCheckerTests = "ztp-spoke-checker"
// LabelClusterInstanceDeleteTestCases is the label for the siteconfig operator's cluster instance delete test cases.
LabelClusterInstanceDeleteTestCases = "ztp-cluster-instance-delete"

// LabelBiosDayZeroTests is the label for a particuarl set of test cases.
LabelBiosDayZeroTests = "ztp-bios-day-zero"
Expand Down Expand Up @@ -84,6 +86,10 @@ const (
ZtpTestPathCustomSourceNoCrFile = "ztp-test/custom-source-crs/no-cr-file"
// ZtpTestPathCustomSourceSearchPath is the git path for the policies app custome source search path test.
ZtpTestPathCustomSourceSearchPath = "ztp-test/custom-source-crs/search-path"
// ZtpTestPathDetachAIMNO is the git path for the siteconfig operator detach AI MNO cluster instance test.
ZtpTestPathDetachAIMNO = "ztp-test/siteconfig-operator/detach-ai-mno/"
// ZtpTestPathDetachAISNO is the git path for the siteconfig operator detach AI SNO cluster instance test.
ZtpTestPathDetachAISNO = "ztp-test/siteconfig-operator/detach-ai-sno/"
// ZtpKustomizationPath is the path to the kustomization file in the ztp test.
ZtpKustomizationPath = "/kustomization.yaml"

Expand Down Expand Up @@ -124,6 +130,12 @@ const (
ImageRegistryPVC = "image-registry-pvc"
// ImageRegistryPath is the path to where the image registry PV will be.
ImageRegistryPath = "/var/imageregistry"
// DefaultAIClusterTemplatesConfigMapName is the name of default AI cluster templates config map.
DefaultAIClusterTemplatesConfigMapName = "ai-cluster-templates-v1"
// DefaultAINodeTemplatesConfigMapName is the name of default AI node templates config map.
DefaultAINodeTemplatesConfigMapName = "ai-node-templates-v1"
// SiteconfigOperatorPodLabel is the name of siteconfig operator pod label selector.
SiteconfigOperatorPodLabel = "app.kubernetes.io/name=siteconfig-controller"

// LogLevel is the verbosity of glog statements in this test suite.
LogLevel glog.Level = 90
Expand Down
216 changes: 216 additions & 0 deletions tests/cnf/ran/gitopsztp/tests/ztp-cluster-instance-delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
package tests

import (
"time"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

"github.com/openshift-kni/eco-goinfra/pkg/assisted"
"github.com/openshift-kni/eco-goinfra/pkg/bmh"
"github.com/openshift-kni/eco-goinfra/pkg/configmap"
"github.com/openshift-kni/eco-goinfra/pkg/hive"
"github.com/openshift-kni/eco-goinfra/pkg/ocm"
"github.com/openshift-kni/eco-goinfra/pkg/pod"
"github.com/openshift-kni/eco-goinfra/pkg/reportxml"
"github.com/openshift-kni/eco-gotests/tests/cnf/ran/gitopsztp/internal/gitdetails"
"github.com/openshift-kni/eco-gotests/tests/cnf/ran/gitopsztp/internal/tsparams"
"github.com/openshift-kni/eco-gotests/tests/cnf/ran/internal/rancluster"
"github.com/openshift-kni/eco-gotests/tests/cnf/ran/internal/ranhelper"
"github.com/openshift-kni/eco-gotests/tests/cnf/ran/internal/ranparam"
"github.com/openshift-kni/eco-gotests/tests/cnf/ran/internal/version"

. "github.com/openshift-kni/eco-gotests/tests/cnf/ran/internal/raninittools"
)

var _ = Describe("ZTP Siteconfig Operator's Cluster Instance Delete Tests",
Label(tsparams.LabelClusterInstanceDeleteTestCases), func() {
// These tests use the hub and spoke architecture.
BeforeEach(func() {
By("verifying that ZTP meets the minimum version")
versionInRange, err := version.IsVersionStringInRange(RANConfig.ZTPVersion, "4.17", "")
Expect(err).ToNot(HaveOccurred(), "Failed to compare ZTP version string")

if !versionInRange {
Skip("ZTP Siteconfig operator tests require ZTP 4.17 or later")
}

})

AfterEach(func() {
// Recreate the ClusterInstance custom resource.
By("resetting the clusters app back to the original settings")
err := gitdetails.SetGitDetailsInArgoCd(
tsparams.ArgoCdClustersAppName, tsparams.ArgoCdAppDetails[tsparams.ArgoCdClustersAppName],
true, false)
Expect(err).ToNot(HaveOccurred(), "Failed to reset clusters app git details")

// Test teardown expected results validation.
By("checking the infra env manifests exists on hub")
_, err = assisted.PullInfraEnvInstall(HubAPIClient, RANConfig.Spoke1Name, RANConfig.Spoke1Name)
Expect(err).ToNot(HaveOccurred(), "Failed to find spoke infra env manifests")

By("checking the bare metal host manifests exists on hub")
_, err = bmh.Pull(HubAPIClient, RANConfig.Spoke1Name, RANConfig.Spoke1Name)
Expect(err).ToNot(HaveOccurred(), "Failed to find spoke bmh manifests")

By("checking the cluster deployment manifests exists on hub")
_, err = hive.PullClusterDeployment(HubAPIClient, RANConfig.Spoke1Name, RANConfig.Spoke1Name)
Expect(err).ToNot(HaveOccurred(), "Failed to find spoke cluster deployment manifests")

By("checking the NM state config manifests exists on hub")
nmStateConfigList, err := assisted.ListNmStateConfigs(HubAPIClient, RANConfig.Spoke1Name)
Expect(err).ToNot(HaveOccurred(), "Failed to list NM state config manifests")
Expect(nmStateConfigList).ToNot(BeEmpty(), "Failed to find NM state config manifests")

By("checking the klusterlet addon config manifests exists on hub")
_, err = ocm.PullKAC(HubAPIClient, RANConfig.Spoke1Name, RANConfig.Spoke1Name)
Expect(err).ToNot(HaveOccurred(), "Failed to find spoke kac manifests")

By("checking the agent cluster install manifests exists on hub")
_, err = assisted.PullAgentClusterInstall(HubAPIClient, RANConfig.Spoke1Name, RANConfig.Spoke1Name)
Expect(err).ToNot(HaveOccurred(), "Failed to find spoke agent cluster install manifests")
})

// 75374 - Detaching the AI multi-node openshift (MNO) spoke cluster.
It("Validate detaching the AI multi-node openshift spoke cluster", reportxml.ID("75374"), func() {
By("checking spoke cluster type")
spokeClusterType, err := rancluster.CheckSpokeClusterType(RANConfig.Spoke1APIClient)
Expect(err).ToNot(HaveOccurred(), "Failed to fetch spoke cluster type")

if spokeClusterType == ranparam.SNOCluster {
Skip("This test only applies to standard or multi-node openshift spoke cluster")
}

// Test step 1-Delete default assisted installer template reference ConfigMap CRs after spoke cluster installed.
By("deleting default assisted installer template reference ConfigMap custom resources", func() {

By("deleting default assisted installer cluster level templates ConfigMap CR")
clusterTemplateConfigMap, err := configmap.Pull(HubAPIClient, tsparams.DefaultAIClusterTemplatesConfigMapName,
ranparam.AcmOperatorNamespace)
if err == nil {
err = clusterTemplateConfigMap.Delete()
Expect(err).ToNot(HaveOccurred(), "Failed to delete AI cluster level templates config map")
}

By("deleting default assisted installer node level templates ConfigMap CR")
nodeTemplateConfigMap, err := configmap.Pull(HubAPIClient, tsparams.DefaultAINodeTemplatesConfigMapName,
ranparam.AcmOperatorNamespace)
if err == nil {
err = nodeTemplateConfigMap.Delete()
Expect(err).ToNot(HaveOccurred(), "Failed to delete AI node level templates config map")
}
})

// Test step 1 expected result validation.
By("verifying installed spoke cluster should still be functional")
_, err = version.GetOCPVersion(Spoke1APIClient)
Expect(err).ToNot(HaveOccurred(), "Failed to get OCP version from spoke and verify spoke cluster access")

// Test step 2-Update the ztp-test git path to delete the ClusterInstance CR in root level kustimozation.yaml.
By("updating the Argo CD clusters app with the detach AI MNO cluster instance git path")
exists, err := gitdetails.UpdateArgoCdAppGitPath(tsparams.ArgoCdClustersAppName,
tsparams.ZtpTestPathDetachAIMNO, true)
if !exists {
Skip(err.Error())
}

Expect(err).ToNot(HaveOccurred(), "Failed to update Argo CD clusters app with new git path")

// Test step 2 expected results validation.
ValidateAISpokeClusterInstallCRsRemoved()

// Test teardown.
// Recreate default assisted installer template reference ConfigMap CRs by deleting siteconfig operator pod.
By("deleting siteconfig operator pod running under rhacm namespace on hub cluster. ", func() {

By("Get the siteconfig operator pod name with label " + tsparams.SiteconfigOperatorPodLabel)
desiredPodName, err := ranhelper.GetPodNameWithLabel(HubAPIClient, ranparam.AcmOperatorNamespace,
tsparams.SiteconfigOperatorPodLabel)
Expect(err).ToNot(HaveOccurred(), "Failed to get siteconfig operator pod name with label "+
tsparams.SiteconfigOperatorPodLabel+" from "+ranparam.AcmOperatorNamespace+" namespace")

By("Pull the siteconfig operator pod name from namespace " + ranparam.AcmOperatorNamespace)
siteconfigOperatorPodName, err := pod.Pull(HubAPIClient, desiredPodName, ranparam.AcmOperatorNamespace)
if err == nil {
_, err = siteconfigOperatorPodName.DeleteAndWait(3 * time.Minute)
Expect(err).ToNot(HaveOccurred(), "Failed to delete siteconfig operator pod")
}
})

// Teardown test expected results validation.
// The default assisted installer template reference ConfigMap custom resource should be recreated successfully.
By("checking the default assisted installer template reference ConfigMap CRs recreated successfully.", func() {

By("checking default assisted installer cluster level templates ConfigMap CR exists")
_, err := configmap.Pull(HubAPIClient, tsparams.DefaultAIClusterTemplatesConfigMapName,
ranparam.AcmOperatorNamespace)
Expect(err).ToNot(HaveOccurred(), "Failed to find default AI cluster level templates config map")

By("checking default assisted installer node level templates ConfigMap CR exists")
_, err = configmap.Pull(HubAPIClient, tsparams.DefaultAINodeTemplatesConfigMapName,
ranparam.AcmOperatorNamespace)
Expect(err).ToNot(HaveOccurred(), "Failed to find default AI node level templates config map")

By("verifying installed spoke cluster should still be functional")
_, err = version.GetOCPVersion(Spoke1APIClient)
Expect(err).ToNot(HaveOccurred(), "Failed to get OCP version from spoke and verify spoke cluster access")
})
})

// 75376 - Detaching the AI single-node openshift (SNO) spoke cluster.
It("Validate detaching the AI single-node openshift spoke cluster", reportxml.ID("75376"), func() {
By("checking spoke cluster type")
spokeClusterType, err := rancluster.CheckSpokeClusterType(RANConfig.Spoke1APIClient)
Expect(err).ToNot(HaveOccurred(), "Failed to fetch spoke cluster type")

if spokeClusterType == ranparam.HighlyAvailableCluster {
Skip("This test only applies to single-node openshift spoke cluster")
}

// Test step 1-Update the ztp-test git path to delete the ClusterInstance CR in root level kustimozation.yaml.
By("updating the Argo CD clusters app with the detach AI SNO cluster instance git path")
exists, err := gitdetails.UpdateArgoCdAppGitPath(tsparams.ArgoCdClustersAppName,
tsparams.ZtpTestPathDetachAISNO, true)
if !exists {
Skip(err.Error())
}

Expect(err).ToNot(HaveOccurred(), "Failed to update Argo CD clusters app with new git path")

// Test step 1 expected results validation.
ValidateAISpokeClusterInstallCRsRemoved()
})
})

// ValidateAISpokeClusterInstallCRsRemoved verifies AI spoke cluster install CRs removed and spoke cluster accessible.
func ValidateAISpokeClusterInstallCRsRemoved() {
By("checking the infra env manifests removed on hub")
_, err := assisted.PullInfraEnvInstall(HubAPIClient, RANConfig.Spoke1Name, RANConfig.Spoke1Name)
Expect(err).To(HaveOccurred(), "Found spoke infra env manifests but expected to be removed")

By("checking the bare metal host manifests removed on hub")
_, err = bmh.Pull(HubAPIClient, RANConfig.Spoke1Name, RANConfig.Spoke1Name)
Expect(err).To(HaveOccurred(), "Found spoke bmh manifests but expected to be removed")

By("checking the cluster deployment manifests removed on hub")
_, err = hive.PullClusterDeployment(HubAPIClient, RANConfig.Spoke1Name, RANConfig.Spoke1Name)
Expect(err).To(HaveOccurred(), "Found spoke cluster deployment manifests but expected to be removed")

By("checking the NM state config manifests removed on hub")
nmStateConfigList, err := assisted.ListNmStateConfigs(HubAPIClient, RANConfig.Spoke1Name)
Expect(err).ToNot(HaveOccurred(), "Failed to list NM state config manifests")
Expect(nmStateConfigList).To(BeEmpty(), "Found spoke NM state config manifests but expected to be removed")

By("checking the klusterlet addon config manifests removed on hub")
_, err = ocm.PullKAC(HubAPIClient, RANConfig.Spoke1Name, RANConfig.Spoke1Name)
Expect(err).To(HaveOccurred(), "Found spoke kac manifests but expected to be removed")

By("checking the agent cluster install manifests removed on hub")
_, err = assisted.PullAgentClusterInstall(HubAPIClient, RANConfig.Spoke1Name, RANConfig.Spoke1Name)
Expect(err).To(HaveOccurred(), "Found spoke ACI manifests but expected to be removed")

By("verifying installed spoke cluster should still be functional")
_, err = version.GetOCPVersion(Spoke1APIClient)
Expect(err).ToNot(HaveOccurred(), "Failed to get OCP version from spoke and verify spoke cluster access")
}
15 changes: 15 additions & 0 deletions tests/cnf/ran/internal/rancluster/rancluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/openshift-kni/eco-goinfra/pkg/clients"
"github.com/openshift-kni/eco-goinfra/pkg/nodes"
. "github.com/openshift-kni/eco-gotests/tests/cnf/ran/internal/raninittools"
"github.com/openshift-kni/eco-gotests/tests/cnf/ran/internal/ranparam"
"github.com/openshift-kni/eco-gotests/tests/system-tests/diskencryption/tsparams"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
Expand Down Expand Up @@ -125,3 +126,17 @@ func WaitForNumberOfNodes(client *clients.Settings, expected int, timeout time.D
return false, nil
})
}

// CheckSpokeClusterType checks and returns a spoke cluster type based on number of control plane nodes.
func CheckSpokeClusterType(client *clients.Settings) (ranparam.ClusterType, error) {
controlPlaneNodesList, err := ListNodesByLabel(client, RANConfig.ControlPlaneLabelMap)
if err != nil {
return "", err
}

if len(controlPlaneNodesList) == 1 {
return ranparam.SNOCluster, nil
}

return ranparam.HighlyAvailableCluster, fmt.Errorf("could not determine spoke cluster type")
}
23 changes: 23 additions & 0 deletions tests/cnf/ran/internal/ranhelper/ranhelper.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ package ranhelper

import (
"context"
"fmt"
"os/exec"
"time"

"github.com/golang/glog"
"github.com/openshift-kni/eco-goinfra/pkg/clients"
"github.com/openshift-kni/eco-goinfra/pkg/pod"
"github.com/openshift-kni/eco-gotests/tests/cnf/ran/internal/ranparam"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
)
Expand Down Expand Up @@ -59,3 +63,22 @@ func ExecLocalCommand(timeout time.Duration, command string, args ...string) (st

return string(output), err
}

// GetPodNameWithLabel returns a pod name matching pod label selector in a given namespace.
func GetPodNameWithLabel(client *clients.Settings, podNamespace, podLabelSelector string) (string, error) {
podList, err := pod.List(client, podNamespace, metav1.ListOptions{LabelSelector: podLabelSelector})
if err != nil {
return "", err
}

glog.V(ranparam.LogLevel).Infof("Length of podList matching podLabelSelector is '%v'", len(podList))

if len(podList) < 1 {
return "", fmt.Errorf("no pod found with label %s under namespace %s", podLabelSelector, podNamespace)
}

glog.V(ranparam.LogLevel).Infof("podList[0] matching podLabelSelector is '%v'",
podList[0].Definition.Name)

return podList[0].Definition.Name, nil
}
10 changes: 10 additions & 0 deletions tests/cnf/ran/internal/ranparam/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,13 @@ const (
// MCE is the name of the multicluster engine operator.
MCE HubOperatorName = "multicluster-engine"
)

// ClusterType represents spoke cluster type.
type ClusterType string

const (
// SNOCluster represents spoke cluster type as single-node openshift (SNO) cluster.
SNOCluster ClusterType = "SNO"
// HighlyAvailableCluster represents spoke cluster type as multi-node openshift (MNO) cluster.
HighlyAvailableCluster ClusterType = "HighlyAvailable"
)

0 comments on commit 0cb9f80

Please sign in to comment.