diff --git a/Makefile b/Makefile index 0232d0e6..29187fcb 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # Image URL to use all building/pushing image targets # ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. -ENVTEST_K8S_VERSION = 1.23 +ENVTEST_K8S_VERSION = 1.25 # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) ifeq (,$(shell go env GOBIN)) @@ -81,7 +81,7 @@ vet: ## Run go vet against code. .PHONY: test test: manifests generate fmt vet envtest ## Run tests. - @KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" GOFLAGS="-mod=vendor" go test ./... -coverprofile=coverage.data -timeout 30m || return 1 + @KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" GOFLAGS="-mod=vendor" go test ./pkg/... -coverprofile=coverage.data -timeout 30m || return 1 @go tool cover -func=coverage.data ##@ Build diff --git a/pkg/controllers_test.go b/pkg/controllers_test.go new file mode 100644 index 00000000..da16b449 --- /dev/null +++ b/pkg/controllers_test.go @@ -0,0 +1,120 @@ +package pkg + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "k8s.io/apimachinery/pkg/api/meta" + controllerruntime "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + v1 "github.com/StarRocks/starrocks-kubernetes-operator/pkg/apis/starrocks/v1" + "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils/fake" +) + +func TestSetupClusterReconciler(t *testing.T) { + type args struct { + mgr controllerruntime.Manager + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "test setup cluster reconciler", + args: args{ + mgr: func() controllerruntime.Manager { + env := fake.NewEnvironment(fake.WithClusterCRD()) + defer func() { + err := env.Stop() + assert.Nil(t, err) + }() + return fake.NewManager(env) + }(), + }, + wantErr: false, + }, + } + + v1.Register() + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := SetupClusterReconciler(tt.args.mgr); (err != nil) != tt.wantErr { + t.Errorf("SetupClusterReconciler() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestSetupWarehouseReconciler(t *testing.T) { + env1 := fake.NewEnvironment(fake.WithClusterCRD()) + env2 := fake.NewEnvironment(fake.WithClusterCRD(), fake.WithWarehouseCRD()) + defer func() { + err := env1.Stop() + assert.Nil(t, err) + err = env2.Stop() + assert.Nil(t, err) + }() + + type args struct { + mgr controllerruntime.Manager + ctx context.Context + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "test setup warehouse reconciler with no warehouse CRD", + args: args{ + mgr: func() controllerruntime.Manager { + env1 = fake.NewEnvironment(fake.WithClusterCRD()) + return fake.NewManager(env1) + }(), + ctx: context.Background(), + }, + wantErr: false, + }, + { + name: "test setup warehouse reconciler with warehouse CRD", + args: args{ + mgr: func() controllerruntime.Manager { + return fake.NewManager(env2) + }(), + ctx: context.Background(), + }, + wantErr: false, + }, + } + + v1.Register() + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := SetupWarehouseReconciler(tt.args.ctx, tt.args.mgr); (err != nil) != tt.wantErr { + t.Errorf("SetupWarehouseReconciler() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +type Reader struct { + hasWarehouseCRD bool +} + +func (r Reader) Get(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { + return nil +} + +func (r Reader) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error { + if r.hasWarehouseCRD { + return nil + } + return &meta.NoKindMatchError{} +} + +var _ client.Reader = &Reader{} diff --git a/pkg/k8sutils/fake.go b/pkg/k8sutils/fake/fake_k8s_client.go similarity index 99% rename from pkg/k8sutils/fake.go rename to pkg/k8sutils/fake/fake_k8s_client.go index 89eeefb0..a5eccd93 100644 --- a/pkg/k8sutils/fake.go +++ b/pkg/k8sutils/fake/fake_k8s_client.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package k8sutils +package fake import ( "context" diff --git a/pkg/k8sutils/fake/fake_kubebuiler_manager.go b/pkg/k8sutils/fake/fake_kubebuiler_manager.go new file mode 100644 index 00000000..b11ca4bd --- /dev/null +++ b/pkg/k8sutils/fake/fake_kubebuiler_manager.go @@ -0,0 +1,111 @@ +package fake + +import ( + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/envtest" + "sigs.k8s.io/controller-runtime/pkg/manager" + + v1 "github.com/StarRocks/starrocks-kubernetes-operator/pkg/apis/starrocks/v1" +) + +type WithCRD func() *apiextensionsv1.CustomResourceDefinition + +var ( + clusterCRD = &apiextensionsv1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "starrocksclusters.starrocks.com", + }, + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ + Group: "starrocks.com", + Names: apiextensionsv1.CustomResourceDefinitionNames{ + Plural: "starrocksclusters", + Singular: "starrockscluster", + Kind: "StarRocksCluster", + }, + Scope: apiextensionsv1.NamespaceScoped, + Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ + { + Name: "v1", + Served: true, + Storage: true, + Schema: &apiextensionsv1.CustomResourceValidation{ + OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{ + Type: "object", + }, + }, + }, + }, + }, + } + + warehouseCRD = &apiextensionsv1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "starrockswarehouses.starrocks.com", + }, + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ + Group: "starrocks.com", + Names: apiextensionsv1.CustomResourceDefinitionNames{ + Plural: "starrockswarehouses", + Singular: "starrockswarehouse", + Kind: "StarRocksWarehouse", + }, + Scope: apiextensionsv1.NamespaceScoped, + Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ + { + Name: "v1", + Served: true, + Storage: true, + Schema: &apiextensionsv1.CustomResourceValidation{ + OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{ + Type: "object", + }, + }, + }, + }, + }, + } +) + +// NewEnvironment is used to create a fake manager, code inspired from pkg/manager/internal/integration/manager_test.go +// see https://github.com/kubernetes-sigs/controller-runtime/blob/main/pkg/manager/internal/integration/manager_test.go +// for more information +func NewEnvironment(crds ...WithCRD) *envtest.Environment { + env := &envtest.Environment{ + Scheme: v1.Scheme, + CRDInstallOptions: envtest.CRDInstallOptions{}, + } + for i := range crds { + env.CRDInstallOptions.CRDs = append(env.CRDInstallOptions.CRDs, crds[i]()) + } + return env +} + +func WithClusterCRD() WithCRD { + return func() *apiextensionsv1.CustomResourceDefinition { + return clusterCRD + } +} + +func WithWarehouseCRD() WithCRD { + return func() *apiextensionsv1.CustomResourceDefinition { + return warehouseCRD + } +} + +func NewManager(env *envtest.Environment) ctrl.Manager { + _, err := env.Start() + if err != nil { + panic(err) + } + + mgr, err := manager.New(env.Config, manager.Options{ + MetricsBindAddress: "0", + Scheme: v1.Scheme, + }) + if err != nil { + panic(err) + } + return mgr +} diff --git a/pkg/k8sutils/k8sutils_test.go b/pkg/k8sutils/k8sutils_test.go index c1ee5247..a095e288 100644 --- a/pkg/k8sutils/k8sutils_test.go +++ b/pkg/k8sutils/k8sutils_test.go @@ -33,6 +33,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/scheme" srapi "github.com/StarRocks/starrocks-kubernetes-operator/pkg/apis/starrocks/v1" + "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils/fake" ) var ( @@ -71,7 +72,7 @@ func Test_DeleteAutoscaler(t *testing.T) { }, } - k8sClient := NewFakeClient(sch, &v1autoscaler, &v2autoscaler, &v2beta2Autoscaler) + k8sClient := fake.NewFakeClient(sch, &v1autoscaler, &v2autoscaler, &v2beta2Autoscaler) // confirm the v1.autoscaler exist. var cv1autoscaler v1.HorizontalPodAutoscaler cerr := k8sClient.Get(context.Background(), types.NamespacedName{Name: "test", Namespace: "default"}, &cv1autoscaler) @@ -120,7 +121,7 @@ func Test_getValueFromConfigmap(t *testing.T) { { name: "get value from configmap", args: args{ - k8sClient: NewFakeClient(sch, &corev1.ConfigMap{ + k8sClient: fake.NewFakeClient(sch, &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "test", Namespace: "default", @@ -167,7 +168,7 @@ func Test_getValueFromSecret(t *testing.T) { { name: "get value from secret", args: args{ - k8sClient: NewFakeClient(sch, &corev1.Secret{ + k8sClient: fake.NewFakeClient(sch, &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: "test", Namespace: "default", @@ -213,7 +214,7 @@ func TestGetEnvVarValue(t *testing.T) { { name: "get value", args: args{ - k8sClient: NewFakeClient(sch), + k8sClient: fake.NewFakeClient(sch), namespace: "default", envVar: corev1.EnvVar{ Name: "test", @@ -226,7 +227,7 @@ func TestGetEnvVarValue(t *testing.T) { { name: "get value from configmap", args: args{ - k8sClient: NewFakeClient(sch, + k8sClient: fake.NewFakeClient(sch, &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "test", @@ -255,7 +256,7 @@ func TestGetEnvVarValue(t *testing.T) { { name: "get value from secret", args: args{ - k8sClient: NewFakeClient(sch, + k8sClient: fake.NewFakeClient(sch, &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: "test", diff --git a/pkg/k8sutils/load/load_test.go b/pkg/k8sutils/load/load_test.go new file mode 100644 index 00000000..c200bd1c --- /dev/null +++ b/pkg/k8sutils/load/load_test.go @@ -0,0 +1,40 @@ +package load + +import ( + "reflect" + "testing" + + v1 "github.com/StarRocks/starrocks-kubernetes-operator/pkg/apis/starrocks/v1" + "github.com/StarRocks/starrocks-kubernetes-operator/pkg/common/resource_utils" +) + +func TestSelector(t *testing.T) { + type args struct { + clusterName string + spec v1.SpecInterface + } + tests := []struct { + name string + args args + want resource_utils.Labels + }{ + { + name: "test selector", + args: args{ + clusterName: "kube-starrocks", + spec: (*v1.StarRocksFeProxySpec)(nil), + }, + want: map[string]string{ + "app.kubernetes.io/component": "fe-proxy", + "app.starrocks.ownerreference/name": "kube-starrocks-fe-proxy", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := Selector(tt.args.clusterName, tt.args.spec); !reflect.DeepEqual(got, tt.want) { + t.Errorf("Selector() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/starrockscluster_controller_test.go b/pkg/starrockscluster_controller_test.go index c86a1eaf..600f5b56 100644 --- a/pkg/starrockscluster_controller_test.go +++ b/pkg/starrockscluster_controller_test.go @@ -32,7 +32,7 @@ import ( srapi "github.com/StarRocks/starrocks-kubernetes-operator/pkg/apis/starrocks/v1" rutils "github.com/StarRocks/starrocks-kubernetes-operator/pkg/common/resource_utils" - "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils" + "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils/fake" "github.com/StarRocks/starrocks-kubernetes-operator/pkg/sub_controller" "github.com/StarRocks/starrocks-kubernetes-operator/pkg/sub_controller/cn" "github.com/StarRocks/starrocks-kubernetes-operator/pkg/sub_controller/fe" @@ -41,7 +41,7 @@ import ( func newStarRocksClusterController(objects ...runtime.Object) *StarRocksClusterReconciler { srcController := &StarRocksClusterReconciler{} srcController.Recorder = record.NewFakeRecorder(10) - srcController.Client = k8sutils.NewFakeClient(srapi.Scheme, objects...) + srcController.Client = fake.NewFakeClient(srapi.Scheme, objects...) srcController.Scs = []sub_controller.ClusterSubController{fe.New(srcController.Client), cn.New(srcController.Client)} return srcController } diff --git a/pkg/starrockswarehouse_controller_test.go b/pkg/starrockswarehouse_controller_test.go index 2e7bdd69..a1d160db 100644 --- a/pkg/starrockswarehouse_controller_test.go +++ b/pkg/starrockswarehouse_controller_test.go @@ -14,7 +14,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" v1 "github.com/StarRocks/starrocks-kubernetes-operator/pkg/apis/starrocks/v1" - "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils" + "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils/fake" "github.com/StarRocks/starrocks-kubernetes-operator/pkg/sub_controller" "github.com/StarRocks/starrocks-kubernetes-operator/pkg/sub_controller/cn" ) @@ -24,7 +24,7 @@ func init() { } func newStarRocksWarehouseController(objects ...runtime.Object) *StarRocksWarehouseReconciler { - client := k8sutils.NewFakeClient(v1.Scheme, objects...) + client := fake.NewFakeClient(v1.Scheme, objects...) warehouseController := &StarRocksWarehouseReconciler{ recorder: record.NewFakeRecorder(10), Client: client, diff --git a/pkg/sub_controller/be/be_controller_test.go b/pkg/sub_controller/be/be_controller_test.go index b287fd2b..1b39f0a1 100644 --- a/pkg/sub_controller/be/be_controller_test.go +++ b/pkg/sub_controller/be/be_controller_test.go @@ -33,7 +33,7 @@ import ( srapi "github.com/StarRocks/starrocks-kubernetes-operator/pkg/apis/starrocks/v1" rutils "github.com/StarRocks/starrocks-kubernetes-operator/pkg/common/resource_utils" - "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils" + "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils/fake" "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils/load" "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils/templates/service" ) @@ -104,7 +104,7 @@ func Test_ClearResources(t *testing.T) { }, } - bc := New(k8sutils.NewFakeClient(sch, src, &st, &svc, &ssvc)) + bc := New(fake.NewFakeClient(sch, src, &st, &svc, &ssvc)) err := bc.ClearResources(context.Background(), src) require.Equal(t, nil, err) @@ -163,7 +163,7 @@ func Test_Sync(t *testing.T) { }}, } - bc := New(k8sutils.NewFakeClient(sch, src, &ep)) + bc := New(fake.NewFakeClient(sch, src, &ep)) err := bc.SyncCluster(context.Background(), src) require.Equal(t, nil, err) err = bc.UpdateClusterStatus(context.Background(), src) diff --git a/pkg/sub_controller/cn/cn_controller_test.go b/pkg/sub_controller/cn/cn_controller_test.go index 9eae2920..30e3370d 100644 --- a/pkg/sub_controller/cn/cn_controller_test.go +++ b/pkg/sub_controller/cn/cn_controller_test.go @@ -33,7 +33,7 @@ import ( srapi "github.com/StarRocks/starrocks-kubernetes-operator/pkg/apis/starrocks/v1" rutils "github.com/StarRocks/starrocks-kubernetes-operator/pkg/common/resource_utils" - "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils" + "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils/fake" "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils/load" "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils/templates/object" "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils/templates/service" @@ -96,7 +96,7 @@ func Test_ClearResources(t *testing.T) { Namespace: "default", }, } - cc := New(k8sutils.NewFakeClient(sch, &src, &st, &svc, &ssvc)) + cc := New(fake.NewFakeClient(sch, &src, &st, &svc, &ssvc)) err := cc.ClearResources(context.Background(), &src) require.Equal(t, nil, err) @@ -145,7 +145,7 @@ func Test_Sync(t *testing.T) { }}, } - cc := New(k8sutils.NewFakeClient(sch, src, &ep)) + cc := New(fake.NewFakeClient(sch, src, &ep)) err := cc.SyncCluster(context.Background(), src) require.Equal(t, nil, err) err = cc.UpdateClusterStatus(context.Background(), src) @@ -186,7 +186,7 @@ func TestCnController_UpdateStatus(t *testing.T) { { name: "update the status of cluster", fields: fields{ - k8sClient: k8sutils.NewFakeClient(sch, + k8sClient: fake.NewFakeClient(sch, &appv1.StatefulSet{ ObjectMeta: metav1.ObjectMeta{ Name: "test-cn", diff --git a/pkg/sub_controller/fe/fe_controller_test.go b/pkg/sub_controller/fe/fe_controller_test.go index 66266285..3e307c9f 100644 --- a/pkg/sub_controller/fe/fe_controller_test.go +++ b/pkg/sub_controller/fe/fe_controller_test.go @@ -37,6 +37,7 @@ import ( srapi "github.com/StarRocks/starrocks-kubernetes-operator/pkg/apis/starrocks/v1" rutils "github.com/StarRocks/starrocks-kubernetes-operator/pkg/common/resource_utils" "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils" + "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils/fake" "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils/load" "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils/templates/service" ) @@ -112,7 +113,7 @@ func Test_ClearResources(t *testing.T) { Spec: corev1.ServiceSpec{}, } - fc := New(k8sutils.NewFakeClient(sch, src, svc, ssvc)) + fc := New(fake.NewFakeClient(sch, src, svc, ssvc)) err := fc.ClearResources(context.Background(), src) require.Equal(t, nil, err) @@ -158,7 +159,7 @@ func Test_SyncDeploy(t *testing.T) { }, } - fc := New(k8sutils.NewFakeClient(sch, src)) + fc := New(fake.NewFakeClient(sch, src)) err := fc.SyncCluster(context.Background(), src) require.Equal(t, nil, err)