Skip to content

Draft: test changes not the final outputs #1218

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions test/cvo/cvo.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
package cvo

import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
g "github.com/onsi/ginkgo/v2"
o "github.com/onsi/gomega"
exutil "github.com/openshift/cluster-version-operator/test/util"
)

var _ = Describe("[cvo-testing] cluster-version-operator-tests", func() {
It("should support passing tests", func() {
Expect(true).To(BeTrue())
var _ = g.Describe("[cvo-testing] cluster-version-operator-tests", func() {
defer g.GinkgoRecover()

projectName := "openshift-cluster-version"

oc := exutil.NewCLIWithoutNamespace(projectName)

g.It("should support passing tests", func() {
o.Expect(true).To(o.BeTrue())
})

g.It("Ingress to CVO is not breaking for monitoring scrape", func() {
exutil.By("Testing my commands")
err := oc.AsAdmin().WithoutNamespace().Run("version")
o.Expect(err).NotTo(o.HaveOccurred())
o.Expect(true).To(o.BeTrue())
})
})
1 change: 1 addition & 0 deletions test/cvo/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package cvo
5 changes: 5 additions & 0 deletions test/util/architecture/OWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
reviewers:
- aleskandro
- LiangquanLi930
- lwan-wanglin

177 changes: 177 additions & 0 deletions test/util/architecture/architecture.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
package architecture

import (
"fmt"
"strings"

"k8s.io/apimachinery/pkg/util/sets"

g "github.com/onsi/ginkgo/v2"
o "github.com/onsi/gomega"
exutil "github.com/openshift/openshift-tests-private/test/extended/util"
e2e "k8s.io/kubernetes/test/e2e/framework"
)

type Architecture int

const (
AMD64 Architecture = iota
ARM64
PPC64LE
S390X
MULTI
UNKNOWN
)

const (
NodeArchitectureLabel = "kubernetes.io/arch"
)

// SkipIfNoNodeWithArchitectures skip the test if the cluster is one of the given architectures
func SkipIfNoNodeWithArchitectures(oc *exutil.CLI, architectures ...Architecture) {
if sets.New(
GetAvailableArchitecturesSet(oc)...).IsSuperset(
sets.New(architectures...)) {
return
}
g.Skip(fmt.Sprintf("Skip for no nodes with requested architectures"))
}

// SkipArchitectures skip the test if the cluster is one of the given architectures
func SkipArchitectures(oc *exutil.CLI, architectures ...Architecture) (architecture Architecture) {
architecture = ClusterArchitecture(oc)
for _, arch := range architectures {
if arch == architecture {
g.Skip(fmt.Sprintf("Skip for cluster architecture: %s", arch.String()))
}
}
return
}

// SkipNonAmd64SingleArch skip the test if the cluster is not an AMD64, single-arch, cluster
func SkipNonAmd64SingleArch(oc *exutil.CLI) (Architecture Architecture) {
architecture := ClusterArchitecture(oc)
if architecture != AMD64 {
g.Skip(fmt.Sprintf("Skip for cluster architecture: %s", architecture.String()))
}
return
}

// GetAvailableArchitecturesSet returns multi-arch node cluster's Architectures
func GetAvailableArchitecturesSet(oc *exutil.CLI) []Architecture {
output, err := oc.WithoutNamespace().AsAdmin().Run("get").Args("nodes", "-o=jsonpath={.items[*].status.nodeInfo.architecture}").Output()
if err != nil {
e2e.Failf("unable to get the cluster architecture: ", err)
}
if output == "" {
e2e.Failf("the retrieved architecture is empty")
}
architectureList := strings.Split(output, " ")
archMap := make(map[Architecture]bool, 0)
var architectures []Architecture
for _, nodeArchitecture := range architectureList {
if _, ok := archMap[FromString(nodeArchitecture)]; !ok {
archMap[FromString(nodeArchitecture)] = true
architectures = append(architectures, FromString(nodeArchitecture))
}
}
return architectures
}

// SkipNonMultiArchCluster skip the test if the cluster is not an multi-arch cluster
func SkipNonMultiArchCluster(oc *exutil.CLI) {
if !IsMultiArchCluster(oc) {
g.Skip("This cluster is not multi-arch cluster, skip this case!")
}
}

// IsMultiArchCluster check if the cluster is multi-arch cluster
func IsMultiArchCluster(oc *exutil.CLI) bool {
architectures := GetAvailableArchitecturesSet(oc)
return len(architectures) > 1
}

// FromString returns the Architecture value for the given string
func FromString(arch string) Architecture {
switch arch {
case "amd64":
return AMD64
case "arm64":
return ARM64
case "ppc64le":
return PPC64LE
case "s390x":
return S390X
case "multi":
return MULTI
default:
e2e.Failf("Unknown architecture %s", arch)
}
return AMD64
}

// String returns the string value for the given Architecture
func (a Architecture) String() string {
switch a {
case AMD64:
return "amd64"
case ARM64:
return "arm64"
case PPC64LE:
return "ppc64le"
case S390X:
return "s390x"
case MULTI:
return "multi"
default:
e2e.Failf("Unknown architecture %d", a)
}
return ""
}

// ClusterArchitecture returns the cluster's Architecture
// If the cluster uses the multi-arch payload, this function returns Architecture.multi
func ClusterArchitecture(oc *exutil.CLI) (architecture Architecture) {
output, err := oc.WithoutNamespace().AsAdmin().Run("get").Args("nodes", "-o=jsonpath={.items[*].status.nodeInfo.architecture}").Output()
if err != nil {
e2e.Failf("unable to get the cluster architecture: ", err)
}
if output == "" {
e2e.Failf("the retrieved architecture is empty")
}
architectureList := strings.Split(output, " ")
architecture = FromString(architectureList[0])
for _, nodeArchitecture := range architectureList[1:] {
if FromString(nodeArchitecture) != architecture {
e2e.Logf("Found multi-arch node cluster")
return MULTI
}
}
return
}

func (a Architecture) GNUString() string {
switch a {
case AMD64:
return "x86_64"
case ARM64:
return "aarch64"
case PPC64LE:
return "ppc64le"
case S390X:
return "s390x"
case MULTI:
return "multi"
default:
e2e.Failf("Unknown architecture %d", a)
}
return ""
}

// GetControlPlaneArch get the architecture of the contol plane node
func GetControlPlaneArch(oc *exutil.CLI) Architecture {
masterNode, err := exutil.GetFirstMasterNode(oc)
architecture, err := oc.AsAdmin().WithoutNamespace().Run("get").Args("node", masterNode, "-o=jsonpath={.status.nodeInfo.architecture}").Output()
o.Expect(err).NotTo(o.HaveOccurred())
return FromString(architecture)
}
65 changes: 65 additions & 0 deletions test/util/assert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package util

import (
"fmt"
"strings"

g "github.com/onsi/ginkgo/v2"
o "github.com/onsi/gomega"
e2e "k8s.io/kubernetes/test/e2e/framework"
)

// e is return value of Wait.Poll
// msg is the reason why time out
// the function assert return value of Wait.Poll, and expect NO error
// if e is Nil, just pass and nothing happen.
// if e is not Nil, will not print the default error message "timed out waiting for the condition" because it causes RP AA not to analysis result exactly.
// if e is "timed out waiting for the condition" or "context deadline exceeded", it is replaced by msg.
// if e is not "timed out waiting for the condition", it print e and then case fails.

func AssertWaitPollNoErr(e error, msg string) {
if e == nil {
return
}
var err error
if strings.Compare(e.Error(), "timed out waiting for the condition") == 0 || strings.Compare(e.Error(), "context deadline exceeded") == 0 {
err = fmt.Errorf("case: %v\nerror: %s", g.CurrentSpecReport().FullText(), msg)
} else {
err = fmt.Errorf("case: %v\nerror: %s", g.CurrentSpecReport().FullText(), e.Error())
}
o.Expect(err).NotTo(o.HaveOccurred())

}

// e is return value of Wait.Poll
// msg is the reason why not get
// the function assert return value of Wait.Poll, and expect error raised.
// if e is not Nil, just pass and nothing happen.
// if e is Nil, will print expected error info and then case fails.

func AssertWaitPollWithErr(e error, msg string) {
if e != nil {
e2e.Logf("the error: %v", e)
return
}

err := fmt.Errorf("case: %v\nexpected error not got because of %v", g.CurrentSpecReport().FullText(), msg)
o.Expect(err).NotTo(o.HaveOccurred())

}

// OrFail function will process another function's return values and fail if any of those returned values is ane error != nil and returns the first value
// example: if we have: func getValued() (string, error)
//
// we can do: value := OrFail[string](getValue())
func OrFail[T any](vals ...any) T {

for _, val := range vals {
err, ok := val.(error)
if ok {
o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred())
}
}

return vals[0].(T)
}
16 changes: 16 additions & 0 deletions test/util/auth_rule_resolver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package util

import (
rbacinformers "k8s.io/client-go/informers/rbac/v1"
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
rbacauthorizer "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac"
)

func NewRuleResolver(informers rbacinformers.Interface) rbacregistryvalidation.AuthorizationRuleResolver {
return rbacregistryvalidation.NewDefaultRuleResolver(
&rbacauthorizer.RoleGetter{Lister: informers.Roles().Lister()},
&rbacauthorizer.RoleBindingLister{Lister: informers.RoleBindings().Lister()},
&rbacauthorizer.ClusterRoleGetter{Lister: informers.ClusterRoles().Lister()},
&rbacauthorizer.ClusterRoleBindingLister{Lister: informers.ClusterRoleBindings().Lister()},
)
}
Loading