diff --git a/.github/workflows/verify_unit_test.yml b/.github/workflows/verify_unit_test.yml new file mode 100644 index 0000000..25c3e1d --- /dev/null +++ b/.github/workflows/verify_unit_test.yml @@ -0,0 +1,24 @@ +name: Verify Unit tests + +on: + pull_request: + paths: + - 'support/**' + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: v1.19 + + + - name: Run unit tests + run: go test ./support/. -v + \ No newline at end of file diff --git a/go.mod b/go.mod index e9c5f12..605db4d 100644 --- a/go.mod +++ b/go.mod @@ -9,9 +9,11 @@ require ( github.com/openshift/client-go v0.0.0-20221019143426-16aed247da5c github.com/project-codeflare/multi-cluster-app-dispatcher v1.37.0 github.com/ray-project/kuberay/ray-operator v0.0.0-20231016183545-097828931d15 + github.com/stretchr/testify v1.8.4 k8s.io/api v0.26.3 k8s.io/apimachinery v0.26.3 k8s.io/client-go v0.26.3 + sigs.k8s.io/controller-runtime v0.14.6 ) require ( @@ -21,6 +23,8 @@ require ( github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.10.1 // indirect + github.com/evanphx/json-patch v4.12.0+incompatible // indirect + github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.1 // indirect @@ -43,11 +47,14 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.37.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/objx v0.5.0 // indirect golang.org/x/net v0.12.0 // indirect golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect golang.org/x/sys v0.10.0 // indirect @@ -62,7 +69,6 @@ require ( k8s.io/klog/v2 v2.90.1 // indirect k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d // indirect k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 // indirect - sigs.k8s.io/controller-runtime v0.14.6 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect diff --git a/go.sum b/go.sum index f7abb7a..1d6f968 100644 --- a/go.sum +++ b/go.sum @@ -80,11 +80,13 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= +github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -100,6 +102,7 @@ github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KE github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.20.1 h1:FBLnyygC4/IZZr893oiomc9XaghoveYTrLC1F86HID8= @@ -378,6 +381,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -387,7 +391,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= @@ -407,13 +412,16 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= @@ -658,6 +666,7 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -778,6 +787,7 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.26.3 h1:emf74GIQMTik01Aum9dPP0gAypL8JTLl/lHa4V9RFSU= k8s.io/api v0.26.3/go.mod h1:PXsqwPMXBSBcL1lJ9CYDKy7kIReUydukS5JiRlxC3qE= +k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI= k8s.io/apimachinery v0.26.3 h1:dQx6PNETJ7nODU3XPtrwkfuubs6w7sX0M8n61zHIV/k= k8s.io/apimachinery v0.26.3/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= k8s.io/client-go v0.26.3 h1:k1UY+KXfkxV2ScEL3gilKcF7761xkYsSD6BC9szIu8s= diff --git a/support/batch_test.go b/support/batch_test.go new file mode 100644 index 0000000..cf2df26 --- /dev/null +++ b/support/batch_test.go @@ -0,0 +1,55 @@ +/* +Copyright 2023. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package support + +import ( + "testing" + + "github.com/onsi/gomega" + + batchv1 "k8s.io/api/batch/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +func TestGetJob(t *testing.T) { + + g := gomega.NewGomegaWithT(t) + + fakeJobs := []runtime.Object{ + &batchv1.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-job-1", + Namespace: "my-namespace", + }, + }, + } + fakeClient := NewFakeKubeClientWithObjects(fakeJobs...) + + test := With(t).(*T) + test.client = &testClient{ + core: fakeClient, + } + + // Call the Job function using the fake client + jobFunc := Job(test, "my-namespace", "my-job-1") + job := jobFunc(g) + + g.Expect(job.Name).To(gomega.Equal("my-job-1")) + g.Expect(job.Namespace).To(gomega.Equal("my-namespace")) + +} diff --git a/support/core_test.go b/support/core_test.go new file mode 100644 index 0000000..6ab8d6d --- /dev/null +++ b/support/core_test.go @@ -0,0 +1,51 @@ +package support + +import ( + "testing" + + "github.com/onsi/gomega" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes/fake" +) + +func TestGetPods(t *testing.T) { + // Create a fake Kubernetes client for testing + fakeClient := fake.NewSimpleClientset(&corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pod", + Namespace: "test-namespace", + }, + }) + + test := With(t).(*T) + test.client = &testClient{ + core: fakeClient, + } + + // Call the GetPods function with the fake client and namespace + pods := GetPods(test, "test-namespace", metav1.ListOptions{}) + + test.Expect(pods).Should(gomega.HaveLen(1), "Expected 1 pod, but got %d", len(pods)) + test.Expect(pods[0].Name).To(gomega.Equal("test-pod"), "Expected pod name 'test-pod', but got '%s'", pods[0].Name) +} + +func TestGetNodes(t *testing.T) { + // Create a fake Kubernetes client for testing + fakeClient := fake.NewSimpleClientset(&corev1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-node", + }, + }) + + test := With(t).(*T) + test.client = &testClient{ + core: fakeClient, + } + nodes := GetNodes(test) + + test.Expect(nodes).Should(gomega.HaveLen(1), "Expected 1 node, but got %d", len(nodes)) + test.Expect(nodes[0].Name).To(gomega.Equal("test-node"), "Expected node name 'test-node', but got '%s'", nodes[0].Name) + +} diff --git a/support/environment_test.go b/support/environment_test.go new file mode 100644 index 0000000..f0d762c --- /dev/null +++ b/support/environment_test.go @@ -0,0 +1,136 @@ +package support + +import ( + "fmt" + "os" + "testing" + + "github.com/onsi/gomega" +) + +func TestGetCodeFlareSDKVersion(t *testing.T) { + // Set the environment variable. + os.Setenv(CodeFlareTestSdkVersion, "1.2.3") + + // Get the version. + version := GetCodeFlareSDKVersion() + + // Assert that the version is correct. + if version != "1.2.3" { + gomega.Expect(version).To(gomega.Equal("1.2.3"), "Expected version 1.2.3, but got %s", version) + + } +} + +func TestGetRayVersion(t *testing.T) { + // Set the environment variable. + os.Setenv(CodeFlareTestRayVersion, "1.4.5") + + // Get the version. + version := GetRayVersion() + + // Assert that the version is correct. + if version != "1.4.5" { + gomega.Expect(version).To(gomega.Equal("1.2.3"), "Expected version 1.4.5, but got %s", version) + } +} + +func TestGetRayImage(t *testing.T) { + // Set the environment variable. + os.Setenv(CodeFlareTestRayImage, "ray/ray:latest") + + // Get the image. + image := GetRayImage() + + // Assert that the image is correct. + if image != "ray/ray:latest" { + gomega.Expect(image).To(gomega.Equal("ray/ray:latest"), "Expected image ray/ray:latest, but got %s", image) + + } +} + +func TestGetPyTorchImage(t *testing.T) { + // Set the environment variable. + os.Setenv(CodeFlareTestPyTorchImage, "pytorch/pytorch:latest") + + // Get the image. + image := GetPyTorchImage() + + // Assert that the image is correct. + if image != "pytorch/pytorch:latest" { + gomega.Expect(image).To(gomega.Equal("pytorch/pytorch:latest"), "Expected image pytorch/pytorch:latest, but got %s", image) + + } +} + +func TestGetClusterID(t *testing.T) { + os.Setenv(ClusterID, "my-cluster-id") + clusterId, ok := GetClusterId() + if !ok { + gomega.Expect(ok).To(gomega.BeTrue(), "Expected GetClusterId() to return true, but got false.") + } + if clusterId != "my-cluster-id" { + gomega.Expect(clusterId).To(gomega.Equal("my-cluster-id"), "Expected GetClusterId() to return 'my-cluster-id', but got '%s'.", clusterId) + } +} + +func TestGetInstascaleOcmSecret(t *testing.T) { + // Set the Instascale OCM secret environment variable. + os.Setenv(InstaScaleOcmSecret, "default/instascale-ocm-secret") + // Get the Instascale OCM secret namespace and secret name. + namespace, secretName := GetInstascaleOcmSecret() + + // Verify that the namespace and secret name are correct. + if namespace != "default" || secretName != "instascale-ocm-secret" { + gomega.Expect(fmt.Sprintf("%s/%s", namespace, secretName)).To( + gomega.Equal("default/instascale-ocm-secret"), + "Expected GetInstascaleOcmSecret() to return 'default/instascale-ocm-secret', but got '%s/%s'.", + namespace, secretName, + ) + + } + +} + +func TestGetClusterType(t *testing.T) { + tests := []struct { + name string + envVarValue string + expected ClusterType + }{ + { + name: "OSD cluster", + envVarValue: "OSD", + expected: OsdCluster, + }, + { + name: "OCP cluster", + envVarValue: "OCP", + expected: OcpCluster, + }, + { + name: "Hypershift cluster", + envVarValue: "HYPERSHIFT", + expected: HypershiftCluster, + }, + { + name: "KIND cluster", + envVarValue: "KIND", + expected: KindCluster, + }, + } + ttt := With(t) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + os.Setenv(ClusterTypeEnvVar, tt.envVarValue) + actual := GetClusterType(ttt) + if actual != tt.expected { + gomega.Expect(actual).To( + gomega.Equal(tt.expected), + "Expected GetClusterType() to return %v, but got %v", tt.expected, actual, + ) + + } + }) + } +} diff --git a/support/events_test.go b/support/events_test.go new file mode 100644 index 0000000..b2d5bbb --- /dev/null +++ b/support/events_test.go @@ -0,0 +1,40 @@ +package support + +import ( + "testing" +) + +func TestGetDefaultEventValueIfNull(t *testing.T) { + tests := []struct { + input string + expected string + }{ + {"World", "World"}, + } + + for _, test := range tests { + actual := getDefaultEventValueIfNull(test.input) + if actual != test.expected { + t.Errorf("getDefaultEventValueIfNull(%s) = %s; expected %s", test.input, actual, test.expected) + } + } +} + +func TestGetWhitespaceStr(t *testing.T) { + tests := []struct { + size int + expected string + }{ + {0, ""}, + {1, " "}, + {5, " "}, + {10, " "}, + } + + for _, test := range tests { + actual := getWhitespaceStr(test.size) + if actual != test.expected { + t.Errorf("getWhitespaceStr(%d) = %s; expected %s", test.size, actual, test.expected) + } + } +} diff --git a/support/fakeclient.go b/support/fakeclient.go new file mode 100644 index 0000000..2b3599a --- /dev/null +++ b/support/fakeclient.go @@ -0,0 +1,11 @@ +package support + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/fake" +) + +func NewFakeKubeClientWithObjects(objects ...runtime.Object) *fake.Clientset { + fakeClient := fake.NewSimpleClientset(objects...) + return fakeClient +} diff --git a/support/fakeclientwithscheme.go b/support/fakeclientwithscheme.go new file mode 100644 index 0000000..cb44a9c --- /dev/null +++ b/support/fakeclientwithscheme.go @@ -0,0 +1,11 @@ +package support + +import ( + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +func NewFakeKubeClientWithScheme(scheme *runtime.Scheme, objects ...client.Object) client.Client { + return fake.NewClientBuilder().WithScheme(scheme).WithObjects(objects...).Build() +} diff --git a/support/image_test.go b/support/image_test.go new file mode 100644 index 0000000..7642f61 --- /dev/null +++ b/support/image_test.go @@ -0,0 +1,38 @@ +package support + +import ( + "context" + "testing" + + "github.com/onsi/gomega" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + imagev1 "github.com/openshift/api/image/v1" +) + +func TestGetImageStream(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + scheme := runtime.NewScheme() + _ = imagev1.AddToScheme(scheme) + + fakeImageStream := []client.Object{ + &imagev1.ImageStream{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-imagestream-1", + Namespace: "my-namespace", + }, + }, + } + fakeClient := NewFakeKubeClientWithScheme(scheme, fakeImageStream...) + + image := &imagev1.ImageStream{} + + err := fakeClient.Get(context.TODO(), client.ObjectKey{Name: "my-imagestream-1", Namespace: "my-namespace"}, image) + g.Expect(err).ToNot(gomega.HaveOccurred()) + g.Expect(image.Name).To(gomega.Equal("my-imagestream-1")) + g.Expect(image.Namespace).To(gomega.Equal("my-namespace")) +} diff --git a/support/ingress.go b/support/ingress.go index d834f3b..bef1325 100644 --- a/support/ingress.go +++ b/support/ingress.go @@ -35,6 +35,7 @@ func Ingress(t Test, namespace, name string) func(g gomega.Gomega) *networkingv1 func GetIngress(t Test, namespace, name string) *networkingv1.Ingress { t.T().Helper() + return Ingress(t, namespace, name)(t) } diff --git a/support/ingress_test.go b/support/ingress_test.go new file mode 100644 index 0000000..97ac3a8 --- /dev/null +++ b/support/ingress_test.go @@ -0,0 +1,38 @@ +package support + +import ( + "testing" + + "github.com/onsi/gomega" + + networkingv1 "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +func TestGetIngress(t *testing.T) { + + g := gomega.NewGomegaWithT(t) + // Create a fake client that returns Ingress objects. + fakeIngress := []runtime.Object{ + &networkingv1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-ingress-1", + Namespace: "my-namespace", + }, + }, + } + fakeClient := NewFakeKubeClientWithObjects(fakeIngress...) + + test := With(t).(*T) + test.client = &testClient{ + core: fakeClient, + } + + // Call the Ingress function using the fake client + ingressFunc := Ingress(test, "my-namespace", "my-ingress-1") + ingress := ingressFunc(g) + + g.Expect(ingress.Name).To(gomega.Equal("my-ingress-1")) + g.Expect(ingress.Namespace).To(gomega.Equal("my-namespace")) +} diff --git a/support/machine_test.go b/support/machine_test.go new file mode 100644 index 0000000..ef4a721 --- /dev/null +++ b/support/machine_test.go @@ -0,0 +1,40 @@ +package support + +import ( + "context" + "testing" + + "github.com/onsi/gomega" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + machinev1beta1 "github.com/openshift/api/machine/v1beta1" +) + +func TestGetMachineSets(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + scheme := runtime.NewScheme() + _ = machinev1beta1.AddToScheme(scheme) + + testmachines := []client.Object{ + &machinev1beta1.MachineSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-machineset-1", + Namespace: "openshift-machine-api", + }, + }, + } + fakeClient := NewFakeKubeClientWithScheme(scheme, testmachines...) + + machine := &machinev1beta1.MachineSet{} + err := fakeClient.Get(context.TODO(), client.ObjectKey{Name: "test-machineset-1", Namespace: "openshift-machine-api"}, machine) + g.Expect(err).ToNot(gomega.HaveOccurred()) + + // Assertions + g.Expect(machine.Name).To(gomega.Equal("test-machineset-1")) + g.Expect(machine.Namespace).To(gomega.Equal("openshift-machine-api")) + +} diff --git a/support/ocm_test.go b/support/ocm_test.go new file mode 100644 index 0000000..4f8024e --- /dev/null +++ b/support/ocm_test.go @@ -0,0 +1,35 @@ +package support + +// Need to MOck OCM COnnection + +/* +import ( + "testing" + "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes/fake" + ocmsdk "github.com/openshift-online/ocm-sdk-go" + cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" +) + +func TestGetMachinePools(t *testing.T) { + // Create a fake OpenShift client for testing + fakeClient := fake.NewSimpleClientset(machinePool{ + &cmv1.MachinePool{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-machinepool", + Namespace: "test-namespace", + }, + }, + }) + + test := With(t).(*T) + test.client = &testClient{ + core: fakeClient, + } + + // Call the GetMachinePools function with the fake client and connection + machinePools := GetMachinePools(test, &ocmsdk.Connection{}) + test.Expect(machinePools).Should(gomega.HaveLen(1), "Expected 1 machine pool, but got %d", len(machinePools)) +} +*/ diff --git a/support/ray_test.go b/support/ray_test.go new file mode 100644 index 0000000..2c84408 --- /dev/null +++ b/support/ray_test.go @@ -0,0 +1,63 @@ +package support + +import ( + "context" + "testing" + + "github.com/onsi/gomega" + rayv1alpha1 "github.com/ray-project/kuberay/ray-operator/apis/ray/v1" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func TestGetRayJob(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + scheme := runtime.NewScheme() + _ = rayv1alpha1.AddToScheme(scheme) + + fakeRayJobs := []client.Object{ + &rayv1alpha1.RayJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-job-1", + Namespace: "my-namespace", + }, + }, + } + + fakeClient := NewFakeKubeClientWithScheme(scheme, fakeRayJobs...) + + rayJob := &rayv1alpha1.RayJob{} + err := fakeClient.Get(context.TODO(), client.ObjectKey{Name: "my-job-1", Namespace: "my-namespace"}, rayJob) + g.Expect(err).ToNot(gomega.HaveOccurred()) + + g.Expect(rayJob.Name).To(gomega.Equal("my-job-1")) + g.Expect(rayJob.Namespace).To(gomega.Equal("my-namespace")) +} + +func TestGetRayCluster(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + scheme := runtime.NewScheme() + _ = rayv1alpha1.AddToScheme(scheme) + + fakeRayCluster := []client.Object{ + &rayv1alpha1.RayCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-cluster-1", + Namespace: "my-namespace", + }, + }, + } + + fakeClient := NewFakeKubeClientWithScheme(scheme, fakeRayCluster...) + + raycluster := &rayv1alpha1.RayCluster{} + err := fakeClient.Get(context.TODO(), client.ObjectKey{Name: "my-cluster-1", Namespace: "my-namespace"}, raycluster) + g.Expect(err).ToNot(gomega.HaveOccurred()) + + g.Expect(raycluster.Name).To(gomega.Equal("my-cluster-1")) + g.Expect(raycluster.Namespace).To(gomega.Equal("my-namespace")) +} diff --git a/support/route_test.go b/support/route_test.go new file mode 100644 index 0000000..261fa00 --- /dev/null +++ b/support/route_test.go @@ -0,0 +1,40 @@ +package support + +import ( + "context" + "testing" + + "github.com/onsi/gomega" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + routev1 "github.com/openshift/api/route/v1" +) + +func TestGetRoute(t *testing.T) { + + g := gomega.NewGomegaWithT(t) + + scheme := runtime.NewScheme() + _ = routev1.AddToScheme(scheme) + + fakeroute := []client.Object{ + &routev1.Route{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-1", + Namespace: "my-namespace", + }, + }, + } + fakeClient := NewFakeKubeClientWithScheme(scheme, fakeroute...) + + route := &routev1.Route{} + err := fakeClient.Get(context.TODO(), client.ObjectKey{Name: "test-1", Namespace: "my-namespace"}, route) + g.Expect(err).ToNot(gomega.HaveOccurred()) + + g.Expect(route.Name).To(gomega.Equal("test-1")) + g.Expect(route.Namespace).To(gomega.Equal("my-namespace")) + +} diff --git a/support/test.go b/support/test.go index 683b0f2..042c828 100644 --- a/support/test.go +++ b/support/test.go @@ -93,11 +93,13 @@ func (t *T) Ctx() context.Context { func (t *T) Client() Client { t.T().Helper() t.once.client.Do(func() { - c, err := newTestClient() - if err != nil { - t.T().Fatalf("Error creating client: %v", err) + if t.client == nil { + c, err := newTestClient() + if err != nil { + t.T().Fatalf("Error creating client: %v", err) + } + t.client = c } - t.client = c }) return t.client }