Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
.idea/
coverage.out
/cloud-credential-tests-ext

.openshift-tests-extension/
182 changes: 116 additions & 66 deletions cmd/cloud-credential-tests-ext/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"flag"
"fmt"
"os"
"regexp"
Expand All @@ -21,92 +22,141 @@ func main() {
logs.InitLogs()
defer logs.FlushLogs()

// Create our registry of openshift-tests extensions
extensionRegistry, ext := setupExtension()
registerSuites(ext)
specs := buildTestSpecs()
specs = applyPlatformFilters(specs)
ext.AddSpecs(specs)

root := createRootCommand(extensionRegistry)
if err := root.Execute(); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
}

// setupExtension creates and registers the extension with the registry.
func setupExtension() (*e.Registry, *e.Extension) {
extensionRegistry := e.NewRegistry()
ext := e.NewExtension("openshift", "payload", "cloud-credential-operator")
extensionRegistry.Register(ext)
return extensionRegistry, ext
}

// Carve up the kube tests into our openshift suites...
ext.AddSuite(e.Suite{
Name: "cco/conformance/parallel",
Parents: []string{
"openshift/conformance/parallel",
// registerSuites registers all test suites for the extension.
func registerSuites(ext *e.Extension) {
suites := []e.Suite{
{
Name: "cco/conformance/parallel",
Parents: []string{
"openshift/conformance/parallel",
},
Qualifiers: []string{
`name.contains("[Level0]") && !(name.contains("[Serial]") || name.contains("[Disruptive]"))`,
},
},
Qualifiers: []string{
`!(name.contains("[Serial]") || name.contains("[Slow]"))`,
{
Name: "cco/conformance/serial",
Parents: []string{
"openshift/conformance/serial",
},
Qualifiers: []string{
`name.contains("[Serial]") && !name.contains("[Disruptive]")`,
},
},
})

ext.AddSuite(e.Suite{
Name: "cco/conformance/serial",
Parents: []string{
"openshift/conformance/serial",
{
Name: "cco/disruptive",
Parents: []string{"openshift/disruptive"},
Qualifiers: []string{
`name.contains("[Disruptive]")`,
},
},
Qualifiers: []string{
`name.contains("[Serial]")`,
{
Name: "cco/all",
Description: "All Cloud Credential Operator tests",
// No qualifiers means all tests from this extension will be included
// The source filter is automatically added by AddSuite
},
})
}

// Suite: optional/slow (long-running tests)
ext.AddSuite(e.Suite{
Name: "cco/optional/slow",
Parents: []string{"openshift/optional/slow"},
Qualifiers: []string{
`name.contains("[Slow]")`,
},
})
for _, suite := range suites {
ext.AddSuite(suite)
}
}

// If using Ginkgo, build test specs automatically
// Use custom filter to handle both file system paths and module paths for vendor exclusion
specs, err := g.BuildExtensionTestSpecsFromOpenShiftGinkgoSuite(func(spec *extensiontests.ExtensionTestSpec) bool {
// Only include tests from cloud-credential-operator module (exclude vendor tests)
for _, cl := range spec.CodeLocations {
// Handle file system paths (e.g., /path/to/vendor/k8s.io/...)
if strings.Contains(cl, "/vendor/") {
return false
}
// Handle module paths (e.g., k8s.io/kubernetes@v1.33.2/...)
if strings.HasPrefix(cl, "k8s.io/") || strings.HasPrefix(cl, "sigs.k8s.io/") {
return false
}
// Include cloud-credential-operator tests
if strings.Contains(cl, "cloud-credential-operator/test/extend") {
return true
}
}
return false
})
// buildTestSpecs builds test specs from Ginkgo suite, filtering out vendor tests.
func buildTestSpecs() extensiontests.ExtensionTestSpecs {
specs, err := g.BuildExtensionTestSpecsFromOpenShiftGinkgoSuite(shouldIncludeTest)
if err != nil {
panic(fmt.Sprintf("couldn't build extension test specs from ginkgo: %+v", err.Error()))
panic(fmt.Sprintf("couldn't build extension test specs from ginkgo: %v", err))
}
return specs
}

// shouldIncludeTest determines if a test spec should be included based on its code locations.
// It excludes vendor tests and external module tests, only including cloud-credential-operator tests.
func shouldIncludeTest(spec *extensiontests.ExtensionTestSpec) bool {
for _, location := range spec.CodeLocations {
// Exclude vendor directory tests
if strings.Contains(location, "/vendor/") {
return false
}
// Exclude external Kubernetes module tests
if strings.HasPrefix(location, "k8s.io/") || strings.HasPrefix(location, "sigs.k8s.io/") {
return false
}
// Include cloud-credential-operator tests
if strings.Contains(location, "cloud-credential-operator/test/extend") {
return true
}
}
return false
}

// Handle platform-specific tests by setting proper environmentSelector
foundPlatforms := make(map[string]string)
for _, test := range specs.Select(extensiontests.NameContains("[platform:")).Names() {
re := regexp.MustCompile(`\[platform:[a-z]*]`)
matches := re.FindAllString(test, -1)
for _, platformDef := range matches {
if _, ok := foundPlatforms[platformDef]; !ok {
platform := platformDef[strings.Index(platformDef, ":")+1 : len(platformDef)-1]
foundPlatforms[platformDef] = platform
// applyPlatformFilters applies platform-specific filters to test specs based on platform tags.
func applyPlatformFilters(specs extensiontests.ExtensionTestSpecs) extensiontests.ExtensionTestSpecs {
return specs.Walk(func(spec *extensiontests.ExtensionTestSpec) {
platformNames := extractPlatformNames(spec.Name)
if len(platformNames) == 0 {
return
}

if len(platformNames) == 1 {
spec.Include(extensiontests.PlatformEquals(platformNames[0]))
} else {
orExprs := make([]string, 0, len(platformNames))
for _, platformName := range platformNames {
orExprs = append(orExprs, extensiontests.PlatformEquals(platformName))
}
specs.Select(extensiontests.NameContains(platformDef)).
Include(extensiontests.PlatformEquals(platformDef[strings.Index(platformDef, ":")+1 : len(platformDef)-1]))
spec.Include(extensiontests.Or(orExprs...))
}
})
}

// extractPlatformNames extracts platform names from test spec name using platform tags.
func extractPlatformNames(specName string) []string {
platformRegex := regexp.MustCompile(`\[platform:([a-z0-9-]+)]`)
matches := platformRegex.FindAllStringSubmatch(specName, -1)
if len(matches) == 0 {
return nil
}

ext.AddSpecs(specs)
platformNames := make([]string, 0, len(matches))
for _, match := range matches {
if len(match) >= 2 {
platformNames = append(platformNames, match[1])
}
}
return platformNames
}

// Cobra stuff
// createRootCommand creates and configures the root Cobra command.
func createRootCommand(extensionRegistry *e.Registry) *cobra.Command {
root := &cobra.Command{
Long: "Cloud Credential Operator tests extension for OpenShift",
}

// Ensure Go flags (like --kubeconfig) are available on the root command.
root.PersistentFlags().AddGoFlagSet(flag.CommandLine)
root.AddCommand(cmd.DefaultExtensionCommands(extensionRegistry)...)

if err := func() error {
return root.Execute()
}(); err != nil {
os.Exit(1)
}
return root
}
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ require (
github.com/golang/glog v1.2.5
github.com/golang/mock v1.7.0-rc.1
github.com/google/go-cmp v0.7.0
github.com/google/go-github/v57 v57.0.0
github.com/google/uuid v1.6.0
github.com/microsoft/kiota-authentication-azure-go v1.3.1
github.com/microsoftgraph/msgraph-sdk-go v1.87.0
Expand All @@ -47,6 +48,7 @@ require (
github.com/spf13/cobra v1.10.1
github.com/spf13/pflag v1.0.10
github.com/stretchr/testify v1.11.1
github.com/tidwall/gjson v1.18.0
golang.org/x/mod v0.29.0
golang.org/x/oauth2 v0.32.0
golang.org/x/time v0.14.0
Expand Down Expand Up @@ -145,6 +147,7 @@ require (
github.com/google/btree v1.1.3 // indirect
github.com/google/cel-go v0.26.0 // indirect
github.com/google/gnostic-models v0.7.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/pprof v0.0.0-20251007162407-5df77e3f7d1d // indirect
github.com/google/s2a-go v0.1.9 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
Expand Down Expand Up @@ -189,6 +192,8 @@ require (
github.com/std-uritemplate/std-uritemplate/go/v2 v2.0.8 // indirect
github.com/stoewer/go-strcase v1.3.0 // indirect
github.com/stretchr/objx v0.5.3 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/vladimirvivien/gexe v0.5.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.mongodb.org/mongo-driver v1.17.4 // indirect
Expand Down
14 changes: 12 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,10 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-github/v57 v57.0.0 h1:L+Y3UPTY8ALM8x+TV0lg+IEBI+upibemtBD8Q9u7zHs=
github.com/google/go-github/v57 v57.0.0/go.mod h1:s0omdnye0hvK/ecLvpsGfJMiRt85PimQh4oygmLIxHw=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
Expand Down Expand Up @@ -624,6 +628,12 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/vladimirvivien/gexe v0.5.0 h1:AWBVaYnrTsGYBktXvcO0DfWPeSiZxn6mnQ5nvL+A1/A=
github.com/vladimirvivien/gexe v0.5.0/go.mod h1:3gjgTqE2c0VyHnU5UOIwk7gyNzZDGulPb/DJPgcw64E=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
Expand Down Expand Up @@ -1106,10 +1116,10 @@ k8s.io/apiextensions-apiserver v0.34.1 h1:NNPBva8FNAPt1iSVwIE0FsdrVriRXMsaWFMqJb
k8s.io/apiextensions-apiserver v0.34.1/go.mod h1:hP9Rld3zF5Ay2Of3BeEpLAToP+l4s5UlxiHfqRaRcMc=
k8s.io/apimachinery v0.24.2/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
k8s.io/apimachinery v0.24.3/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
k8s.io/apiserver v0.34.1 h1:U3JBGdgANK3dfFcyknWde1G6X1F4bg7PXuvlqt8lITA=
k8s.io/apiserver v0.34.1/go.mod h1:eOOc9nrVqlBI1AFCvVzsob0OxtPZUCPiUJL45JOTBG0=
k8s.io/apimachinery v0.35.0 h1:Z2L3IHvPVv/MJ7xRxHEtk6GoJElaAqDCCU0S6ncYok8=
k8s.io/apimachinery v0.35.0/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns=
k8s.io/apiserver v0.34.1 h1:U3JBGdgANK3dfFcyknWde1G6X1F4bg7PXuvlqt8lITA=
k8s.io/apiserver v0.34.1/go.mod h1:eOOc9nrVqlBI1AFCvVzsob0OxtPZUCPiUJL45JOTBG0=
k8s.io/client-go v0.24.2/go.mod h1:zg4Xaoo+umDsfCWr4fCnmLEtQXyCNXCvJuSsglNcV30=
k8s.io/client-go v0.35.0 h1:IAW0ifFbfQQwQmga0UdoH0yvdqrbwMdq9vIFEhRpxBE=
k8s.io/client-go v0.35.0/go.mod h1:q2E5AAyqcbeLGPdoRB+Nxe3KYTfPce1Dnu1myQdqz9o=
Expand Down
18 changes: 0 additions & 18 deletions test/extend/cco.go

This file was deleted.

Loading