sigs.k8s.io/kueue@v0.6.2/test/integration/framework/framework.go (about) 1 /* 2 Copyright 2022 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package framework 18 19 import ( 20 "context" 21 "crypto/tls" 22 "fmt" 23 "net" 24 "time" 25 26 kubeflow "github.com/kubeflow/mpi-operator/pkg/apis/kubeflow/v2beta1" 27 kftraining "github.com/kubeflow/training-operator/pkg/apis/kubeflow.org/v1" 28 "github.com/onsi/ginkgo/v2" 29 "github.com/onsi/gomega" 30 rayv1 "github.com/ray-project/kuberay/ray-operator/apis/ray/v1" 31 rayjobapi "github.com/ray-project/kuberay/ray-operator/apis/ray/v1alpha1" 32 zaplog "go.uber.org/zap" 33 "go.uber.org/zap/zapcore" 34 "k8s.io/client-go/kubernetes/scheme" 35 "k8s.io/client-go/rest" 36 ctrl "sigs.k8s.io/controller-runtime" 37 "sigs.k8s.io/controller-runtime/pkg/client" 38 "sigs.k8s.io/controller-runtime/pkg/envtest" 39 "sigs.k8s.io/controller-runtime/pkg/log/zap" 40 "sigs.k8s.io/controller-runtime/pkg/manager" 41 metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" 42 "sigs.k8s.io/controller-runtime/pkg/webhook" 43 jobsetapi "sigs.k8s.io/jobset/api/jobset/v1alpha2" 44 45 config "sigs.k8s.io/kueue/apis/config/v1beta1" 46 kueuealpha "sigs.k8s.io/kueue/apis/kueue/v1alpha1" 47 kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1" 48 ) 49 50 type ManagerSetup func(manager.Manager, context.Context) 51 52 type Framework struct { 53 CRDPath string 54 DepCRDPaths []string 55 WebhookPath string 56 testEnv *envtest.Environment 57 cancel context.CancelFunc 58 } 59 60 func (f *Framework) Init() *rest.Config { 61 opts := func(o *zap.Options) { 62 o.TimeEncoder = zapcore.RFC3339NanoTimeEncoder 63 o.ZapOpts = []zaplog.Option{zaplog.AddCaller()} 64 } 65 ctrl.SetLogger(zap.New( 66 zap.WriteTo(ginkgo.GinkgoWriter), 67 zap.UseDevMode(true), 68 zap.Level(zapcore.Level(-3)), 69 opts), 70 ) 71 72 ginkgo.By("bootstrapping test environment") 73 f.testEnv = &envtest.Environment{ 74 CRDDirectoryPaths: append(f.DepCRDPaths, f.CRDPath), 75 ErrorIfCRDPathMissing: true, 76 } 77 if len(f.WebhookPath) > 0 { 78 f.testEnv.WebhookInstallOptions.Paths = []string{f.WebhookPath} 79 } 80 81 cfg, err := f.testEnv.Start() 82 gomega.ExpectWithOffset(1, err).NotTo(gomega.HaveOccurred()) 83 gomega.ExpectWithOffset(1, cfg).NotTo(gomega.BeNil()) 84 85 return cfg 86 } 87 88 func (f *Framework) RunManager(cfg *rest.Config, managerSetup ManagerSetup) (context.Context, client.Client) { 89 err := config.AddToScheme(scheme.Scheme) 90 gomega.ExpectWithOffset(1, err).NotTo(gomega.HaveOccurred()) 91 92 err = kueue.AddToScheme(scheme.Scheme) 93 gomega.ExpectWithOffset(1, err).NotTo(gomega.HaveOccurred()) 94 95 err = kueuealpha.AddToScheme(scheme.Scheme) 96 gomega.ExpectWithOffset(1, err).NotTo(gomega.HaveOccurred()) 97 98 err = kubeflow.AddToScheme(scheme.Scheme) 99 gomega.ExpectWithOffset(1, err).NotTo(gomega.HaveOccurred()) 100 101 err = rayjobapi.AddToScheme(scheme.Scheme) 102 gomega.ExpectWithOffset(1, err).NotTo(gomega.HaveOccurred()) 103 104 err = rayv1.AddToScheme(scheme.Scheme) 105 gomega.ExpectWithOffset(1, err).NotTo(gomega.HaveOccurred()) 106 107 err = jobsetapi.AddToScheme(scheme.Scheme) 108 gomega.ExpectWithOffset(1, err).NotTo(gomega.HaveOccurred()) 109 110 err = kftraining.AddToScheme(scheme.Scheme) 111 gomega.ExpectWithOffset(1, err).NotTo(gomega.HaveOccurred()) 112 113 // +kubebuilder:scaffold:scheme 114 115 k8sClient, err := client.New(cfg, client.Options{Scheme: scheme.Scheme}) 116 gomega.ExpectWithOffset(1, err).NotTo(gomega.HaveOccurred()) 117 gomega.ExpectWithOffset(1, k8sClient).NotTo(gomega.BeNil()) 118 119 webhookInstallOptions := &f.testEnv.WebhookInstallOptions 120 mgrOpts := manager.Options{ 121 Scheme: scheme.Scheme, 122 Metrics: metricsserver.Options{ 123 BindAddress: "0", // disable metrics to avoid conflicts between packages. 124 }, 125 WebhookServer: webhook.NewServer( 126 webhook.Options{ 127 Host: webhookInstallOptions.LocalServingHost, 128 Port: webhookInstallOptions.LocalServingPort, 129 CertDir: webhookInstallOptions.LocalServingCertDir, 130 }), 131 } 132 mgr, err := ctrl.NewManager(cfg, mgrOpts) 133 gomega.ExpectWithOffset(1, err).NotTo(gomega.HaveOccurred(), "failed to create manager") 134 135 ctx, cancel := context.WithCancel(context.Background()) 136 f.cancel = cancel 137 managerSetup(mgr, ctx) 138 139 go func() { 140 defer ginkgo.GinkgoRecover() 141 err := mgr.Start(ctx) 142 gomega.ExpectWithOffset(1, err).NotTo(gomega.HaveOccurred(), "failed to run manager") 143 }() 144 145 if len(f.WebhookPath) > 0 { 146 // wait for the webhook server to get ready 147 dialer := &net.Dialer{Timeout: time.Second} 148 addrPort := fmt.Sprintf("%s:%d", webhookInstallOptions.LocalServingHost, webhookInstallOptions.LocalServingPort) 149 gomega.Eventually(func() error { 150 conn, err := tls.DialWithDialer(dialer, "tcp", addrPort, &tls.Config{InsecureSkipVerify: true}) 151 if err != nil { 152 return err 153 } 154 conn.Close() 155 return nil 156 }).Should(gomega.Succeed()) 157 } 158 159 return ctx, k8sClient 160 } 161 162 func (f *Framework) Teardown() { 163 ginkgo.By("tearing down the test environment") 164 f.cancel() 165 err := f.testEnv.Stop() 166 gomega.ExpectWithOffset(1, err).NotTo(gomega.HaveOccurred()) 167 }