-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cnf ran: ztp test migration preliminaries
This is the first PR for migrating the ZTP test suite and includes the ztp directory with the helper and tsparams packages. Additionally, some helpers and parameters are moved from the TALM suite into the ran directory so they may be shared with the ZTP tests.
- Loading branch information
Showing
25 changed files
with
1,119 additions
and
290 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
package ranhelper | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"math" | ||
"os" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/golang/glog" | ||
"github.com/openshift-kni/eco-goinfra/pkg/clients" | ||
"github.com/openshift-kni/eco-goinfra/pkg/deployment" | ||
"github.com/openshift-kni/eco-goinfra/pkg/olm" | ||
"github.com/openshift-kni/eco-gotests/tests/cnf/ran/internal/raninittools" | ||
"github.com/openshift-kni/eco-gotests/tests/cnf/ran/internal/ranparam" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/client-go/tools/clientcmd" | ||
) | ||
|
||
// InitializeSpokeNames initializes the name of spoke 1 and, if present, spoke 2. | ||
func InitializeSpokeNames() error { | ||
var err error | ||
|
||
// Spoke 1 is required to be present. | ||
ranparam.Spoke1Name, err = getClusterName(os.Getenv("KUBECONFIG")) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Spoke 2 is optional depending on the test. | ||
if raninittools.RANConfig.Spoke2Kubeconfig != "" { | ||
ranparam.Spoke2Name, err = getClusterName(raninittools.RANConfig.Spoke2Kubeconfig) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// InitializeTalmVersion initializes the version of the TALM operator from the hub cluster. | ||
func InitializeTalmVersion() error { | ||
var err error | ||
|
||
ranparam.TalmVersion, err = getOperatorVersionFromCsv( | ||
raninittools.HubAPIClient, ranparam.TalmOperatorHubNamespace, ranparam.OpenshiftOperatorNamespace) | ||
|
||
return err | ||
} | ||
|
||
// InitializeVersions initializes the versions of ACM, TALM, and ZTP from the hub cluster. | ||
func InitializeVersions() error { | ||
var err error | ||
|
||
err = InitializeTalmVersion() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
ranparam.AcmVersion, err = getOperatorVersionFromCsv( | ||
raninittools.HubAPIClient, ranparam.AcmOperatorName, ranparam.AcmOperatorNamespace) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
ranparam.ZtpVersion, err = getZtpVersionFromArgoCd( | ||
raninittools.HubAPIClient, ranparam.OpenshiftGitopsRepoServer, ranparam.OpenshiftGitops) | ||
|
||
return err | ||
} | ||
|
||
// IsVersionStringInRange checks if a version string is between a specified min and max value, inclusive. All the string | ||
// inputs to this function should be dot separated positive intergers, e.g. "1.0.0" or "4.10". Each string input must be | ||
// at least two dot separarted integers but may also be 3 or more, though only the first two are compared. | ||
func IsVersionStringInRange(version, minimum, maximum string) (bool, error) { | ||
versionValid, versionDigits := validateInputString(version) | ||
minimumValid, minimumDigits := validateInputString(minimum) | ||
maximumValid, maximumDigits := validateInputString(maximum) | ||
|
||
if !minimumValid { | ||
// Only accept invalid empty strings | ||
if minimum != "" { | ||
return false, fmt.Errorf("invalid minimum provided: '%s'", minimum) | ||
} | ||
|
||
// Assume the minimum digits are [0,0] for later comparison | ||
minimumDigits = []int{0, 0} | ||
} | ||
|
||
if !maximumValid { | ||
// Only accept invalid empty strings | ||
if maximum != "" { | ||
return false, fmt.Errorf("invalid maximum provided: '%s'", maximum) | ||
} | ||
|
||
// Assume the maximum digits are [math.MaxInt, math.MaxInt] for later comparison | ||
maximumDigits = []int{math.MaxInt, math.MaxInt} | ||
} | ||
|
||
// If the version was not valid then we need to check the min and max | ||
if !versionValid { | ||
// If no min or max was defined then return true | ||
if !minimumValid && !maximumValid { | ||
return true, nil | ||
} | ||
|
||
// Otherwise return whether the input maximum was an empty string or not | ||
return maximum == "", nil | ||
} | ||
|
||
// Otherwise the versions were valid so compare the digits | ||
for i := 0; i < 2; i++ { | ||
// The version bit should be between the minimum and maximum | ||
if versionDigits[i] < minimumDigits[i] || versionDigits[i] > maximumDigits[i] { | ||
return false, nil | ||
} | ||
} | ||
|
||
// At the end if we never returned then all the digits were in valid range | ||
return true, nil | ||
} | ||
|
||
// validateInputString validates that a string is at least two dot separated nonnegative integers. | ||
func validateInputString(input string) (bool, []int) { | ||
versionSplits := strings.Split(input, ".") | ||
|
||
if len(versionSplits) < 2 { | ||
return false, []int{} | ||
} | ||
|
||
digits := []int{} | ||
|
||
for i := 0; i < 2; i++ { | ||
digit, err := strconv.Atoi(versionSplits[i]) | ||
if err != nil || digit < 0 { | ||
return false, []int{} | ||
} | ||
|
||
digits = append(digits, digit) | ||
} | ||
|
||
return true, digits | ||
} | ||
|
||
// getClusterName extracts the cluster name from provided kubeconfig, assuming there's one cluster in the kubeconfig. | ||
func getClusterName(kubeconfigPath string) (string, error) { | ||
rawConfig, _ := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( | ||
&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfigPath}, | ||
&clientcmd.ConfigOverrides{ | ||
CurrentContext: "", | ||
}).RawConfig() | ||
|
||
for _, cluster := range rawConfig.Clusters { | ||
// Get a cluster name by parsing it from the server hostname. Expects the url to start with | ||
// `https://api.cluster-name.` so splitting by `.` gives the cluster name. | ||
splits := strings.Split(cluster.Server, ".") | ||
clusterName := splits[1] | ||
|
||
glog.V(ranparam.LogLevel).Infof("cluster name %s found for kubeconfig at %s", clusterName, kubeconfigPath) | ||
|
||
return clusterName, nil | ||
} | ||
|
||
return "", fmt.Errorf("could not get cluster name for kubeconfig at %s", kubeconfigPath) | ||
} | ||
|
||
// getOperatorVersionFromCsv returns operator version from csv, or an empty string if no CSV for the provided operator | ||
// is found. | ||
func getOperatorVersionFromCsv(client *clients.Settings, operatorName, operatorNamespace string) (string, error) { | ||
csv, err := olm.ListClusterServiceVersion(client, operatorNamespace, metav1.ListOptions{}) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
for _, csv := range csv { | ||
if strings.Contains(csv.Object.Name, operatorName) { | ||
return csv.Object.Spec.Version.String(), nil | ||
} | ||
} | ||
|
||
return "", fmt.Errorf("could not find version for operator %s in namespace %s", operatorName, operatorNamespace) | ||
} | ||
|
||
// getZtpVersionFromArgoCd is used to fetch the version of the ztp-site-generate init container. | ||
func getZtpVersionFromArgoCd(client *clients.Settings, name, namespace string) (string, error) { | ||
ztpDeployment, err := deployment.Pull(client, name, namespace) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
for _, container := range ztpDeployment.Definition.Spec.Template.Spec.InitContainers { | ||
// Match both the `ztp-site-generator` and `ztp-site-generate` images since which one matches is version | ||
// dependent. | ||
if strings.Contains(container.Image, "ztp-site-gen") { | ||
colonSplit := strings.Split(container.Image, ":") | ||
ztpVersion := colonSplit[len(colonSplit)-1] | ||
|
||
if ztpVersion == "latest" { | ||
glog.V(ranparam.LogLevel).Info("ztp-site-generate version tag was 'latest', returning empty version") | ||
|
||
return "", nil | ||
} | ||
|
||
// The format here will be like vX.Y.Z so we need to remove the v at the start. | ||
return ztpVersion[1:], nil | ||
} | ||
} | ||
|
||
return "", errors.New("unable to identify ZTP version") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.