| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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 broker |
| |
| import ( |
| "context" |
| "math/rand" |
| "reflect" |
| "strconv" |
| "testing" |
| |
| rocketmqv1alpha1 "github.com/apache/rocketmq-operator/pkg/apis/rocketmq/v1alpha1" |
| |
| appsv1 "k8s.io/api/apps/v1" |
| corev1 "k8s.io/api/core/v1" |
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
| "k8s.io/apimachinery/pkg/runtime" |
| "k8s.io/apimachinery/pkg/types" |
| "k8s.io/client-go/kubernetes/scheme" |
| "sigs.k8s.io/controller-runtime/pkg/client/fake" |
| "sigs.k8s.io/controller-runtime/pkg/reconcile" |
| logf "sigs.k8s.io/controller-runtime/pkg/runtime/log" |
| ) |
| |
| // TestBrokerController runs ReconcileBroker.Reconcile() against a |
| // fake client that tracks a Broker object. |
| func TestBrokerController(t *testing.T) { |
| // Set the logger to development mode for verbose logs. |
| logf.SetLogger(logf.ZapLogger(true)) |
| |
| var ( |
| name = "rocketmq-operator" |
| namespace = "broker" |
| replicas int32 = 3 |
| ) |
| |
| // A Broker resource with metadata and spec. |
| broker := &rocketmqv1alpha1.Broker{ |
| ObjectMeta: metav1.ObjectMeta{ |
| Name: name, |
| Namespace: namespace, |
| }, |
| Spec: rocketmqv1alpha1.BrokerSpec{ |
| Size: replicas, // Set desired number of Broker replicas. |
| }, |
| } |
| // Objects to track in the fake client. |
| objs := []runtime.Object{ |
| broker, |
| } |
| |
| // Register operator types with the runtime scheme. |
| s := scheme.Scheme |
| s.AddKnownTypes(rocketmqv1alpha1.SchemeGroupVersion, broker) |
| // Create a fake client to mock API calls. |
| cl := fake.NewFakeClient(objs...) |
| // Create a ReconcileBroker object with the scheme and fake client. |
| r := &ReconcileBroker{client: cl, scheme: s} |
| |
| // Mock request to simulate Reconcile() being called on an event for a |
| // watched resource . |
| req := reconcile.Request{ |
| NamespacedName: types.NamespacedName{ |
| Name: name, |
| Namespace: namespace, |
| }, |
| } |
| res, err := r.Reconcile(req) |
| if err != nil { |
| t.Fatalf("reconcile: (%v)", err) |
| } |
| // Check the result of reconciliation to make sure it has the desired state. |
| if !res.Requeue { |
| t.Error("reconcile did not requeue request as expected") |
| } |
| |
| // Check if deployment has been created and has the correct size. |
| dep := &appsv1.Deployment{} |
| err = cl.Get(context.TODO(), req.NamespacedName, dep) |
| if err != nil { |
| t.Fatalf("get deployment: (%v)", err) |
| } |
| dsize := *dep.Spec.Replicas |
| if dsize != replicas { |
| t.Errorf("dep size (%d) is not the expected size (%d)", dsize, replicas) |
| } |
| |
| // Create the 3 expected pods in namespace and collect their names to check |
| // later. |
| podLabels := labelsForBroker(name) |
| pod := corev1.Pod{ |
| ObjectMeta: metav1.ObjectMeta{ |
| Namespace: namespace, |
| Labels: podLabels, |
| }, |
| } |
| podNames := make([]string, 3) |
| for i := 0; i < 3; i++ { |
| pod.ObjectMeta.Name = name + ".pod." + strconv.Itoa(rand.Int()) |
| podNames[i] = pod.ObjectMeta.Name |
| if err = cl.Create(context.TODO(), pod.DeepCopy()); err != nil { |
| t.Fatalf("create pod %d: (%v)", i, err) |
| } |
| } |
| |
| // Reconcile again so Reconcile() checks pods and updates the Broker |
| // resources' Status. |
| res, err = r.Reconcile(req) |
| if err != nil { |
| t.Fatalf("reconcile: (%v)", err) |
| } |
| if res != (reconcile.Result{}) { |
| t.Error("reconcile did not return an empty Result") |
| } |
| |
| // Get the updated Broker object. |
| broker = &rocketmqv1alpha1.Broker{} |
| err = r.client.Get(context.TODO(), req.NamespacedName, broker) |
| if err != nil { |
| t.Errorf("get broker: (%v)", err) |
| } |
| |
| // Ensure Reconcile() updated the Broker's Status as expected. |
| nodes := broker.Status.Nodes |
| if !reflect.DeepEqual(podNames, nodes) { |
| t.Errorf("pod names %v did not match expected %v", nodes, podNames) |
| } |
| } |