forked from kubernetes/kubernetes
-
Notifications
You must be signed in to change notification settings - Fork 99
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
UPSTREAM: <carry>: Create minimal wrapper needed to run k8s e2e tests
- Loading branch information
1 parent
6c05b7c
commit ab1d3ba
Showing
7 changed files
with
617 additions
and
3 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"flag" | ||
"fmt" | ||
"math/rand" | ||
"os" | ||
"sort" | ||
"time" | ||
|
||
"github.com/spf13/cobra" | ||
"github.com/spf13/pflag" | ||
|
||
utilflag "k8s.io/component-base/cli/flag" | ||
"k8s.io/component-base/logs" | ||
"k8s.io/kubernetes/test/e2e/framework" | ||
|
||
// initialize framework extensions | ||
_ "k8s.io/kubernetes/test/e2e/framework/debug/init" | ||
_ "k8s.io/kubernetes/test/e2e/framework/metrics/init" | ||
) | ||
|
||
func main() { | ||
logs.InitLogs() | ||
defer logs.FlushLogs() | ||
|
||
rand.Seed(time.Now().UTC().UnixNano()) | ||
|
||
pflag.CommandLine.SetNormalizeFunc(utilflag.WordSepNormalizeFunc) | ||
|
||
root := &cobra.Command{ | ||
Long: "OpenShift Tests compatible wrapper", | ||
} | ||
|
||
root.AddCommand( | ||
newRunTestCommand(), | ||
newListTestsCommand(), | ||
) | ||
|
||
f := flag.CommandLine.Lookup("v") | ||
root.PersistentFlags().AddGoFlag(f) | ||
pflag.CommandLine = pflag.NewFlagSet("empty", pflag.ExitOnError) | ||
flag.CommandLine = flag.NewFlagSet("empty", flag.ExitOnError) | ||
framework.RegisterCommonFlags(flag.CommandLine) | ||
framework.RegisterClusterFlags(flag.CommandLine) | ||
|
||
if err := func() error { | ||
return root.Execute() | ||
}(); err != nil { | ||
if ex, ok := err.(ExitError); ok { | ||
fmt.Fprintf(os.Stderr, "Ginkgo exit error %d: %v\n", ex.Code, err) | ||
os.Exit(ex.Code) | ||
} | ||
fmt.Fprintf(os.Stderr, "error: %v\n", err) | ||
os.Exit(1) | ||
} | ||
} | ||
|
||
func newRunTestCommand() *cobra.Command { | ||
testOpt := NewTestOptions(os.Stdout, os.Stderr) | ||
|
||
cmd := &cobra.Command{ | ||
Use: "run-test NAME", | ||
Short: "Run a single test by name", | ||
Long: "Execute a single test.", | ||
SilenceUsage: true, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
if err := initializeTestFramework(os.Getenv("TEST_PROVIDER")); err != nil { | ||
return err | ||
} | ||
|
||
return testOpt.Run(args) | ||
}, | ||
} | ||
return cmd | ||
} | ||
|
||
func newListTestsCommand() *cobra.Command { | ||
cmd := &cobra.Command{ | ||
Use: "list", | ||
Short: "List available tests", | ||
Long: "List the available tests in this binary.", | ||
SilenceUsage: true, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
tests := testsForSuite() | ||
sort.Slice(tests, func(i, j int) bool { return tests[i].Name < tests[j].Name }) | ||
data, err := json.Marshal(tests) | ||
if err != nil { | ||
return err | ||
} | ||
fmt.Fprintf(os.Stdout, "%s\n", data) | ||
return nil | ||
}, | ||
} | ||
|
||
return cmd | ||
} |
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,146 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
|
||
"github.com/onsi/ginkgo/v2" | ||
"github.com/onsi/gomega" | ||
|
||
corev1 "k8s.io/api/core/v1" | ||
kclientset "k8s.io/client-go/kubernetes" | ||
"k8s.io/client-go/tools/clientcmd" | ||
"k8s.io/kubernetes/openshift-hack/e2e" | ||
conformancetestdata "k8s.io/kubernetes/test/conformance/testdata" | ||
"k8s.io/kubernetes/test/e2e/framework" | ||
"k8s.io/kubernetes/test/e2e/framework/testfiles" | ||
"k8s.io/kubernetes/test/e2e/storage/external" | ||
e2etestingmanifests "k8s.io/kubernetes/test/e2e/testing-manifests" | ||
testfixtures "k8s.io/kubernetes/test/fixtures" | ||
|
||
// this appears to inexplicably auto-register global flags. | ||
_ "k8s.io/kubernetes/test/e2e/storage/drivers" | ||
|
||
// these are loading important global flags that we need to get and set | ||
_ "k8s.io/kubernetes/test/e2e" | ||
_ "k8s.io/kubernetes/test/e2e/lifecycle" | ||
) | ||
|
||
// copied directly from github.com/openshift/origin/cmd/openshift-tests/provider.go | ||
// and github.com/openshift/origin/test/extended/util/test.go | ||
func initializeTestFramework(provider string) error { | ||
providerInfo := &ClusterConfiguration{} | ||
if err := json.Unmarshal([]byte(provider), &providerInfo); err != nil { | ||
return fmt.Errorf("provider must be a JSON object with the 'type' key at a minimum: %v", err) | ||
} | ||
if len(providerInfo.ProviderName) == 0 { | ||
return fmt.Errorf("provider must be a JSON object with the 'type' key") | ||
} | ||
config := &ClusterConfiguration{} | ||
if err := json.Unmarshal([]byte(provider), config); err != nil { | ||
return fmt.Errorf("provider must decode into the ClusterConfig object: %v", err) | ||
} | ||
|
||
// update context with loaded config | ||
context := &framework.TestContext | ||
context.Provider = config.ProviderName | ||
context.CloudConfig = framework.CloudConfig{ | ||
ProjectID: config.ProjectID, | ||
Region: config.Region, | ||
Zone: config.Zone, | ||
Zones: config.Zones, | ||
NumNodes: config.NumNodes, | ||
MultiMaster: config.MultiMaster, | ||
MultiZone: config.MultiZone, | ||
ConfigFile: config.ConfigFile, | ||
} | ||
context.AllowedNotReadyNodes = -1 | ||
context.MinStartupPods = -1 | ||
context.MaxNodesToGather = 0 | ||
context.KubeConfig = os.Getenv("KUBECONFIG") | ||
|
||
// allow the CSI tests to access test data, but only briefly | ||
// TODO: ideally CSI would not use any of these test methods | ||
// var err error | ||
// exutil.WithCleanup(func() { err = initCSITests(dryRun) }) | ||
// TODO: for now I'm only initializing CSI directly, but we probably need that | ||
// WithCleanup here as well | ||
if err := initCSITests(); err != nil { | ||
return err | ||
} | ||
|
||
if ad := os.Getenv("ARTIFACT_DIR"); len(strings.TrimSpace(ad)) == 0 { | ||
os.Setenv("ARTIFACT_DIR", filepath.Join(os.TempDir(), "artifacts")) | ||
} | ||
|
||
context.DeleteNamespace = os.Getenv("DELETE_NAMESPACE") != "false" | ||
context.VerifyServiceAccount = true | ||
testfiles.AddFileSource(e2etestingmanifests.GetE2ETestingManifestsFS()) | ||
testfiles.AddFileSource(testfixtures.GetTestFixturesFS()) | ||
testfiles.AddFileSource(conformancetestdata.GetConformanceTestdataFS()) | ||
context.KubectlPath = "kubectl" | ||
// context.KubeConfig = KubeConfigPath() | ||
context.KubeConfig = os.Getenv("KUBECONFIG") | ||
|
||
// "debian" is used when not set. At least GlusterFS tests need "custom". | ||
// (There is no option for "rhel" or "centos".) | ||
context.NodeOSDistro = "custom" | ||
context.MasterOSDistro = "custom" | ||
|
||
// load and set the host variable for kubectl | ||
clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(&clientcmd.ClientConfigLoadingRules{ExplicitPath: context.KubeConfig}, &clientcmd.ConfigOverrides{}) | ||
cfg, err := clientConfig.ClientConfig() | ||
if err != nil { | ||
return err | ||
} | ||
context.Host = cfg.Host | ||
|
||
// Ensure that Kube tests run privileged (like they do upstream) | ||
context.CreateTestingNS = func(baseName string, c kclientset.Interface, labels map[string]string) (*corev1.Namespace, error) { | ||
return e2e.CreateTestingNS(baseName, c, labels, true) | ||
} | ||
|
||
gomega.RegisterFailHandler(ginkgo.Fail) | ||
|
||
framework.AfterReadingAllFlags(context) | ||
context.DumpLogsOnFailure = true | ||
|
||
// these constants are taken from kube e2e and used by tests | ||
context.IPFamily = "ipv4" | ||
if config.HasIPv6 && !config.HasIPv4 { | ||
context.IPFamily = "ipv6" | ||
} | ||
|
||
context.ReportDir = os.Getenv("TEST_JUNIT_DIR") | ||
|
||
return nil | ||
} | ||
|
||
const ( | ||
manifestEnvVar = "TEST_CSI_DRIVER_FILES" | ||
) | ||
|
||
// copied directly from github.com/openshift/origin/cmd/openshift-tests/csi.go | ||
// Initialize openshift/csi suite, i.e. define CSI tests from TEST_CSI_DRIVER_FILES. | ||
func initCSITests() error { | ||
manifestList := os.Getenv(manifestEnvVar) | ||
if manifestList != "" { | ||
manifests := strings.Split(manifestList, ",") | ||
for _, manifest := range manifests { | ||
if err := external.AddDriverDefinition(manifest); err != nil { | ||
return fmt.Errorf("failed to load manifest from %q: %s", manifest, err) | ||
} | ||
// Register the base dir of the manifest file as a file source. | ||
// With this we can reference the CSI driver's storageClass | ||
// in the manifest file (FromFile field). | ||
testfiles.AddFileSource(testfiles.RootFileSource{ | ||
Root: filepath.Dir(manifest), | ||
}) | ||
} | ||
} | ||
|
||
return nil | ||
} |
Oops, something went wrong.