1068 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			1068 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			Go
		
	
	
	
| /*
 | |
| Copyright 2022 The Kruise Authors.
 | |
| 
 | |
| 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 rollouthistory
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"reflect"
 | |
| 	"testing"
 | |
| 
 | |
| 	"github.com/openkruise/kruise-api/apps/pub"
 | |
| 	kruisev1alpha1 "github.com/openkruise/kruise-api/apps/v1alpha1"
 | |
| 	rolloutapi "github.com/openkruise/rollouts/api"
 | |
| 	rolloutv1alpha1 "github.com/openkruise/rollouts/api/v1alpha1"
 | |
| 	corev1 "k8s.io/api/core/v1"
 | |
| 	networkingv1 "k8s.io/api/networking/v1"
 | |
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | |
| 	"k8s.io/apimachinery/pkg/runtime"
 | |
| 	"k8s.io/apimachinery/pkg/types"
 | |
| 	"k8s.io/apimachinery/pkg/util/intstr"
 | |
| 	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
 | |
| 	utilpointer "k8s.io/utils/pointer"
 | |
| 	ctrl "sigs.k8s.io/controller-runtime"
 | |
| 	"sigs.k8s.io/controller-runtime/pkg/client"
 | |
| 	"sigs.k8s.io/controller-runtime/pkg/client/fake"
 | |
| 	"sigs.k8s.io/gateway-api/apis/v1alpha2"
 | |
| )
 | |
| 
 | |
| func init() {
 | |
| 	scheme = runtime.NewScheme()
 | |
| 	_ = clientgoscheme.AddToScheme(scheme)
 | |
| 	_ = kruisev1alpha1.AddToScheme(scheme)
 | |
| 	_ = rolloutapi.AddToScheme(scheme)
 | |
| 	_ = v1alpha2.AddToScheme(scheme)
 | |
| }
 | |
| 
 | |
| var (
 | |
| 	scheme *runtime.Scheme
 | |
| 
 | |
| 	rollouthistoryDemo = rolloutv1alpha1.RolloutHistory{
 | |
| 		TypeMeta: metav1.TypeMeta{
 | |
| 			Kind:       "RolloutHistory",
 | |
| 			APIVersion: "rollouts.kruise.io/v1alpha1",
 | |
| 		},
 | |
| 		ObjectMeta: metav1.ObjectMeta{
 | |
| 			Name:      "rollouthistory-demo",
 | |
| 			Namespace: "default",
 | |
| 			Labels: map[string]string{
 | |
| 				rolloutIDLabel:   "1",
 | |
| 				rolloutNameLabel: "rollout-demo",
 | |
| 			},
 | |
| 		},
 | |
| 		Spec: rolloutv1alpha1.RolloutHistorySpec{
 | |
| 			Rollout: rolloutv1alpha1.RolloutInfo{
 | |
| 				RolloutID: "1",
 | |
| 				NameAndSpecData: rolloutv1alpha1.NameAndSpecData{
 | |
| 					Name: "rollout-demo",
 | |
| 				},
 | |
| 			},
 | |
| 			Service: rolloutv1alpha1.ServiceInfo{
 | |
| 				NameAndSpecData: rolloutv1alpha1.NameAndSpecData{
 | |
| 					Name: "service-demo",
 | |
| 				},
 | |
| 			},
 | |
| 			TrafficRouting: rolloutv1alpha1.TrafficRoutingInfo{
 | |
| 				Ingress: &rolloutv1alpha1.IngressInfo{
 | |
| 					NameAndSpecData: rolloutv1alpha1.NameAndSpecData{
 | |
| 						Name: "ingress-demo",
 | |
| 					},
 | |
| 				},
 | |
| 				HTTPRoute: &rolloutv1alpha1.HTTPRouteInfo{
 | |
| 					NameAndSpecData: rolloutv1alpha1.NameAndSpecData{
 | |
| 						Name: "HTTPRoute-demo",
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 			Workload: rolloutv1alpha1.WorkloadInfo{
 | |
| 				TypeMeta: metav1.TypeMeta{
 | |
| 					APIVersion: "apps.kruise.io/v1alpha1",
 | |
| 					Kind:       "CloneSet",
 | |
| 				},
 | |
| 				NameAndSpecData: rolloutv1alpha1.NameAndSpecData{
 | |
| 					Name: "workload-demo",
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 		Status: rolloutv1alpha1.RolloutHistoryStatus{
 | |
| 			Phase: "",
 | |
| 			CanarySteps: []rolloutv1alpha1.CanaryStepInfo{
 | |
| 				{
 | |
| 					CanaryStepIndex: 1,
 | |
| 					Pods: []rolloutv1alpha1.Pod{
 | |
| 						{
 | |
| 							Name:     "pod-1",
 | |
| 							IP:       "1.2.3.4",
 | |
| 							NodeName: "local",
 | |
| 						},
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	rolloutDemo1 = rolloutv1alpha1.Rollout{
 | |
| 		TypeMeta: metav1.TypeMeta{
 | |
| 			Kind:       "Rollout",
 | |
| 			APIVersion: "rollouts.kruise.io/v1alpha1",
 | |
| 		},
 | |
| 		ObjectMeta: metav1.ObjectMeta{
 | |
| 			Name:      "rollout-demo",
 | |
| 			Namespace: "default",
 | |
| 			Labels:    map[string]string{},
 | |
| 		},
 | |
| 		Spec: rolloutv1alpha1.RolloutSpec{
 | |
| 			ObjectRef: rolloutv1alpha1.ObjectRef{
 | |
| 				WorkloadRef: &rolloutv1alpha1.WorkloadRef{
 | |
| 					APIVersion: "apps.kruise.io/v1alpha1",
 | |
| 					Kind:       "CloneSet",
 | |
| 					Name:       "workload-demo",
 | |
| 				},
 | |
| 			},
 | |
| 			DeprecatedRolloutID: "1",
 | |
| 			Strategy: rolloutv1alpha1.RolloutStrategy{
 | |
| 				Canary: &rolloutv1alpha1.CanaryStrategy{
 | |
| 					Steps: []rolloutv1alpha1.CanaryStep{
 | |
| 						{
 | |
| 							TrafficRoutingStrategy: rolloutv1alpha1.TrafficRoutingStrategy{
 | |
| 								Weight: utilpointer.Int32(5),
 | |
| 							},
 | |
| 							Pause: rolloutv1alpha1.RolloutPause{
 | |
| 								Duration: utilpointer.Int32(0),
 | |
| 							},
 | |
| 						},
 | |
| 						{
 | |
| 							TrafficRoutingStrategy: rolloutv1alpha1.TrafficRoutingStrategy{
 | |
| 								Weight: utilpointer.Int32(40),
 | |
| 							},
 | |
| 							Pause: rolloutv1alpha1.RolloutPause{},
 | |
| 						},
 | |
| 						{
 | |
| 							TrafficRoutingStrategy: rolloutv1alpha1.TrafficRoutingStrategy{
 | |
| 								Weight: utilpointer.Int32(100),
 | |
| 							},
 | |
| 							Pause: rolloutv1alpha1.RolloutPause{
 | |
| 								Duration: utilpointer.Int32(0),
 | |
| 							},
 | |
| 						},
 | |
| 					},
 | |
| 					TrafficRoutings: []rolloutv1alpha1.TrafficRoutingRef{
 | |
| 						{
 | |
| 							Service: "service-demo",
 | |
| 							Ingress: &rolloutv1alpha1.IngressTrafficRouting{
 | |
| 								ClassType: "nginx",
 | |
| 								Name:      "ingress-demo",
 | |
| 							},
 | |
| 							Gateway: &rolloutv1alpha1.GatewayTrafficRouting{
 | |
| 								HTTPRouteName: utilpointer.String("HTTPRoute-demo"),
 | |
| 							},
 | |
| 						},
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	cloneSetDemo = kruisev1alpha1.CloneSet{
 | |
| 		TypeMeta: metav1.TypeMeta{
 | |
| 			APIVersion: "apps.kruise.io/v1alpha1",
 | |
| 			Kind:       "CloneSet",
 | |
| 		},
 | |
| 		ObjectMeta: metav1.ObjectMeta{
 | |
| 			Name:      "workload-demo",
 | |
| 			Namespace: "default",
 | |
| 			Labels: map[string]string{
 | |
| 				"app": "echoserver",
 | |
| 			},
 | |
| 		},
 | |
| 		Spec: kruisev1alpha1.CloneSetSpec{
 | |
| 			UpdateStrategy: kruisev1alpha1.CloneSetUpdateStrategy{
 | |
| 				Type: "InPlaceIfPossible",
 | |
| 				InPlaceUpdateStrategy: &pub.InPlaceUpdateStrategy{
 | |
| 					GracePeriodSeconds: 1,
 | |
| 				},
 | |
| 			},
 | |
| 			Replicas: utilpointer.Int32(5),
 | |
| 			Selector: &metav1.LabelSelector{
 | |
| 				MatchLabels: map[string]string{
 | |
| 					"app": "echoserver",
 | |
| 				},
 | |
| 			},
 | |
| 			Template: corev1.PodTemplateSpec{
 | |
| 				ObjectMeta: metav1.ObjectMeta{
 | |
| 					Labels: map[string]string{
 | |
| 						"app": "echoserver",
 | |
| 					},
 | |
| 				},
 | |
| 				Spec: corev1.PodSpec{
 | |
| 					Containers: []corev1.Container{
 | |
| 						{
 | |
| 							Name:            "echoserver",
 | |
| 							Image:           "cilium/echoserver:1.10.1",
 | |
| 							ImagePullPolicy: "IfNotPresent",
 | |
| 							Ports: []corev1.ContainerPort{
 | |
| 								{
 | |
| 									ContainerPort: 8080,
 | |
| 								},
 | |
| 							},
 | |
| 							Env: []corev1.EnvVar{
 | |
| 								{
 | |
| 									Name:  "PORT",
 | |
| 									Value: "8080",
 | |
| 								},
 | |
| 							},
 | |
| 						},
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	serviceDemo = corev1.Service{
 | |
| 		TypeMeta: metav1.TypeMeta{
 | |
| 			Kind:       "Service",
 | |
| 			APIVersion: "v1",
 | |
| 		},
 | |
| 		ObjectMeta: metav1.ObjectMeta{
 | |
| 			Name:      "service-demo",
 | |
| 			Namespace: "default",
 | |
| 			Labels: map[string]string{
 | |
| 				"app": "echoserver",
 | |
| 			},
 | |
| 		},
 | |
| 		Spec: corev1.ServiceSpec{
 | |
| 			Ports: []corev1.ServicePort{
 | |
| 				{
 | |
| 					Port:       int32(80),
 | |
| 					TargetPort: intstr.IntOrString{IntVal: int32(8080)},
 | |
| 					Name:       "http",
 | |
| 					Protocol:   "TCP",
 | |
| 				},
 | |
| 			},
 | |
| 			Selector: map[string]string{
 | |
| 				"app": "echoserver",
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	ingressDemo = networkingv1.Ingress{
 | |
| 		TypeMeta: metav1.TypeMeta{
 | |
| 			APIVersion: "networking.k8s.io/v1",
 | |
| 			Kind:       "Ingress",
 | |
| 		},
 | |
| 		ObjectMeta: metav1.ObjectMeta{
 | |
| 			Name:      "ingress-demo",
 | |
| 			Namespace: "default",
 | |
| 			Annotations: map[string]string{
 | |
| 				"kubernetes.io/ingress.class": "nginx",
 | |
| 			},
 | |
| 		},
 | |
| 		Spec: networkingv1.IngressSpec{
 | |
| 			Rules: []networkingv1.IngressRule{
 | |
| 				{
 | |
| 					Host: "echoserver.example.com",
 | |
| 					IngressRuleValue: networkingv1.IngressRuleValue{
 | |
| 						HTTP: &networkingv1.HTTPIngressRuleValue{
 | |
| 							Paths: []networkingv1.HTTPIngressPath{
 | |
| 								{
 | |
| 									Path:     "/apis/echo",
 | |
| 									PathType: (*networkingv1.PathType)(utilpointer.String("Exact")),
 | |
| 									Backend: networkingv1.IngressBackend{
 | |
| 										Service: &networkingv1.IngressServiceBackend{
 | |
| 											Name: "service-demo",
 | |
| 											Port: networkingv1.ServiceBackendPort{
 | |
| 												Number: int32(80),
 | |
| 											},
 | |
| 										},
 | |
| 									},
 | |
| 								},
 | |
| 							},
 | |
| 						},
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	httpRouteDemo = v1alpha2.HTTPRoute{
 | |
| 		TypeMeta: metav1.TypeMeta{
 | |
| 			APIVersion: "gateway.networking.k8s.io/v1alpha2",
 | |
| 			Kind:       "HTTPRoute",
 | |
| 		},
 | |
| 		ObjectMeta: metav1.ObjectMeta{
 | |
| 			Name:      "HTTPRoute-demo",
 | |
| 			Namespace: "default",
 | |
| 		},
 | |
| 		Spec: v1alpha2.HTTPRouteSpec{
 | |
| 			CommonRouteSpec: v1alpha2.CommonRouteSpec{
 | |
| 				ParentRefs: []v1alpha2.ParentReference{
 | |
| 					{
 | |
| 						Name: "demo-lb",
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	podDemo = corev1.Pod{
 | |
| 		TypeMeta: metav1.TypeMeta{
 | |
| 			APIVersion: "v1",
 | |
| 			Kind:       "Pod",
 | |
| 		},
 | |
| 		ObjectMeta: metav1.ObjectMeta{
 | |
| 			Name:      "pod-demo",
 | |
| 			Namespace: "default",
 | |
| 			Labels: map[string]string{
 | |
| 				rolloutv1alpha1.RolloutBatchIDLabel: "1",
 | |
| 				rolloutv1alpha1.RolloutIDLabel:      "1",
 | |
| 			},
 | |
| 		},
 | |
| 		Spec: corev1.PodSpec{
 | |
| 			NodeName: "local",
 | |
| 		},
 | |
| 	}
 | |
| )
 | |
| 
 | |
| func TestReconcile(t *testing.T) {
 | |
| 	cases := []struct {
 | |
| 		name                 string
 | |
| 		req                  ctrl.Request
 | |
| 		getPods              func() []*corev1.Pod
 | |
| 		getService           func() []*corev1.Service
 | |
| 		getWorkload          func() []*kruisev1alpha1.CloneSet
 | |
| 		getIngress           func() []*networkingv1.Ingress
 | |
| 		getHTTPRoute         func() []*v1alpha2.HTTPRoute
 | |
| 		getRollout           func() []*rolloutv1alpha1.Rollout
 | |
| 		getRolloutHistory    func() []*rolloutv1alpha1.RolloutHistory
 | |
| 		expectRolloutHistory func() []*rolloutv1alpha1.RolloutHistory
 | |
| 	}{
 | |
| 		{
 | |
| 			name: "test1, create a new rolloutHistory for rollout",
 | |
| 			req: ctrl.Request{
 | |
| 				NamespacedName: types.NamespacedName{
 | |
| 					Namespace: "default",
 | |
| 					Name:      "rollout-demo",
 | |
| 				},
 | |
| 			},
 | |
| 			getPods: func() []*corev1.Pod {
 | |
| 				pods := []*corev1.Pod{}
 | |
| 				return pods
 | |
| 			},
 | |
| 			getService: func() []*corev1.Service {
 | |
| 				services := []*corev1.Service{}
 | |
| 				return services
 | |
| 			},
 | |
| 			getWorkload: func() []*kruisev1alpha1.CloneSet {
 | |
| 				workloads := []*kruisev1alpha1.CloneSet{}
 | |
| 				return workloads
 | |
| 			},
 | |
| 			getIngress: func() []*networkingv1.Ingress {
 | |
| 				ingresses := []*networkingv1.Ingress{}
 | |
| 				return ingresses
 | |
| 			},
 | |
| 			getHTTPRoute: func() []*v1alpha2.HTTPRoute {
 | |
| 				httpRoutes := []*v1alpha2.HTTPRoute{}
 | |
| 				return httpRoutes
 | |
| 			},
 | |
| 			getRollout: func() []*rolloutv1alpha1.Rollout {
 | |
| 				rollout := rolloutDemo1.DeepCopy()
 | |
| 				rollout.Status = rolloutv1alpha1.RolloutStatus{
 | |
| 					CanaryStatus: &rolloutv1alpha1.CanaryStatus{
 | |
| 						ObservedRolloutID: "1",
 | |
| 					},
 | |
| 					Phase: rolloutv1alpha1.RolloutPhaseProgressing,
 | |
| 				}
 | |
| 				return []*rolloutv1alpha1.Rollout{rollout}
 | |
| 			},
 | |
| 			getRolloutHistory: func() []*rolloutv1alpha1.RolloutHistory {
 | |
| 				rollouthistories := []*rolloutv1alpha1.RolloutHistory{}
 | |
| 				return rollouthistories
 | |
| 			},
 | |
| 			expectRolloutHistory: func() []*rolloutv1alpha1.RolloutHistory {
 | |
| 				rollouthistory := rollouthistoryDemo.DeepCopy()
 | |
| 				rollouthistory.Spec = rolloutv1alpha1.RolloutHistorySpec{}
 | |
| 				rollouthistory.Status = rolloutv1alpha1.RolloutHistoryStatus{}
 | |
| 				return []*rolloutv1alpha1.RolloutHistory{rollouthistory}
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			name: "test2, completed a rolloutHistory for rollout",
 | |
| 			req: ctrl.Request{
 | |
| 				NamespacedName: types.NamespacedName{
 | |
| 					Namespace: "default",
 | |
| 					Name:      "rollout-demo",
 | |
| 				},
 | |
| 			},
 | |
| 			getPods: func() []*corev1.Pod {
 | |
| 				pod1 := podDemo.DeepCopy()
 | |
| 				pod1.Name = "pod1"
 | |
| 				pod1.Spec.NodeName = "local"
 | |
| 				pod1.Status = corev1.PodStatus{
 | |
| 					PodIP: "1.2.3.1",
 | |
| 				}
 | |
| 				pod1.Labels = map[string]string{
 | |
| 					rolloutv1alpha1.RolloutBatchIDLabel: "1",
 | |
| 					rolloutv1alpha1.RolloutIDLabel:      "2",
 | |
| 					"app":                               "echoserver",
 | |
| 				}
 | |
| 
 | |
| 				pod2 := podDemo.DeepCopy()
 | |
| 				pod2.Name = "pod2"
 | |
| 				pod2.Spec.NodeName = "local"
 | |
| 				pod2.Status = corev1.PodStatus{
 | |
| 					PodIP: "1.2.3.2",
 | |
| 				}
 | |
| 				pod2.Labels = map[string]string{
 | |
| 					rolloutv1alpha1.RolloutBatchIDLabel: "2",
 | |
| 					rolloutv1alpha1.RolloutIDLabel:      "2",
 | |
| 					"app":                               "echoserver",
 | |
| 				}
 | |
| 
 | |
| 				pod3 := podDemo.DeepCopy()
 | |
| 				pod3.Name = "pod3"
 | |
| 				pod3.Spec.NodeName = "local"
 | |
| 				pod3.Status = corev1.PodStatus{
 | |
| 					PodIP: "1.2.3.3",
 | |
| 				}
 | |
| 				pod3.Labels = map[string]string{
 | |
| 					rolloutv1alpha1.RolloutBatchIDLabel: "3",
 | |
| 					rolloutv1alpha1.RolloutIDLabel:      "2",
 | |
| 					"app":                               "echoserver",
 | |
| 				}
 | |
| 
 | |
| 				pod4 := podDemo.DeepCopy()
 | |
| 				pod4.Name = "pod4"
 | |
| 				pod4.Spec.NodeName = "local"
 | |
| 				pod4.Status = corev1.PodStatus{
 | |
| 					PodIP: "1.2.3.4",
 | |
| 				}
 | |
| 				pod4.Labels = map[string]string{
 | |
| 					rolloutv1alpha1.RolloutBatchIDLabel: "3",
 | |
| 					rolloutv1alpha1.RolloutIDLabel:      "2",
 | |
| 					"app":                               "echoserver",
 | |
| 				}
 | |
| 
 | |
| 				pod5 := podDemo.DeepCopy()
 | |
| 				pod5.Name = "pod5"
 | |
| 				pod5.Spec.NodeName = "local"
 | |
| 				pod5.Status = corev1.PodStatus{
 | |
| 					PodIP: "1.2.3.5",
 | |
| 				}
 | |
| 				pod5.Labels = map[string]string{
 | |
| 					rolloutv1alpha1.RolloutBatchIDLabel: "3",
 | |
| 					rolloutv1alpha1.RolloutIDLabel:      "2",
 | |
| 					"app":                               "echoserver",
 | |
| 				}
 | |
| 
 | |
| 				return []*corev1.Pod{pod1, pod2, pod3, pod4, pod5}
 | |
| 			},
 | |
| 			getService: func() []*corev1.Service {
 | |
| 				services := []*corev1.Service{serviceDemo.DeepCopy()}
 | |
| 				return services
 | |
| 			},
 | |
| 			getWorkload: func() []*kruisev1alpha1.CloneSet {
 | |
| 				workloads := []*kruisev1alpha1.CloneSet{cloneSetDemo.DeepCopy()}
 | |
| 				return workloads
 | |
| 			},
 | |
| 			getIngress: func() []*networkingv1.Ingress {
 | |
| 				ingresses := []*networkingv1.Ingress{ingressDemo.DeepCopy()}
 | |
| 				return ingresses
 | |
| 			},
 | |
| 			getHTTPRoute: func() []*v1alpha2.HTTPRoute {
 | |
| 				httpRoutes := []*v1alpha2.HTTPRoute{httpRouteDemo.DeepCopy()}
 | |
| 				return httpRoutes
 | |
| 			},
 | |
| 			getRollout: func() []*rolloutv1alpha1.Rollout {
 | |
| 				rollout := rolloutDemo1.DeepCopy()
 | |
| 				rollout.Spec.DeprecatedRolloutID = "2"
 | |
| 				rollout.Status = rolloutv1alpha1.RolloutStatus{
 | |
| 					CanaryStatus: &rolloutv1alpha1.CanaryStatus{
 | |
| 						ObservedRolloutID: "2",
 | |
| 					},
 | |
| 					Phase: rolloutv1alpha1.RolloutPhaseHealthy,
 | |
| 				}
 | |
| 				return []*rolloutv1alpha1.Rollout{rollout}
 | |
| 			},
 | |
| 			getRolloutHistory: func() []*rolloutv1alpha1.RolloutHistory {
 | |
| 				rollouthistory := rollouthistoryDemo.DeepCopy()
 | |
| 				rollouthistory.Labels = map[string]string{
 | |
| 					rolloutIDLabel:   "2",
 | |
| 					rolloutNameLabel: "rollout-demo",
 | |
| 				}
 | |
| 				rollouthistory.Spec = rolloutv1alpha1.RolloutHistorySpec{}
 | |
| 				rollouthistory.Status = rolloutv1alpha1.RolloutHistoryStatus{}
 | |
| 				return []*rolloutv1alpha1.RolloutHistory{rollouthistory}
 | |
| 			},
 | |
| 			expectRolloutHistory: func() []*rolloutv1alpha1.RolloutHistory {
 | |
| 				rollouthistory := rollouthistoryDemo.DeepCopy()
 | |
| 				rollouthistory.Labels = map[string]string{
 | |
| 					rolloutIDLabel:   "2",
 | |
| 					rolloutNameLabel: "rollout-demo",
 | |
| 				}
 | |
| 				rollouthistory.Spec = rolloutv1alpha1.RolloutHistorySpec{
 | |
| 					Rollout: rolloutv1alpha1.RolloutInfo{
 | |
| 						RolloutID: "2",
 | |
| 						NameAndSpecData: rolloutv1alpha1.NameAndSpecData{
 | |
| 							Name: "rollout-demo",
 | |
| 						},
 | |
| 					},
 | |
| 					Workload: rolloutv1alpha1.WorkloadInfo{
 | |
| 						NameAndSpecData: rolloutv1alpha1.NameAndSpecData{
 | |
| 							Name: "workload-demo",
 | |
| 						},
 | |
| 					},
 | |
| 					Service: rolloutv1alpha1.ServiceInfo{
 | |
| 						NameAndSpecData: rolloutv1alpha1.NameAndSpecData{
 | |
| 							Name: "service-demo",
 | |
| 						},
 | |
| 					},
 | |
| 					TrafficRouting: rolloutv1alpha1.TrafficRoutingInfo{
 | |
| 						Ingress: &rolloutv1alpha1.IngressInfo{
 | |
| 							NameAndSpecData: rolloutv1alpha1.NameAndSpecData{
 | |
| 								Name: "ingress-demo",
 | |
| 							},
 | |
| 						},
 | |
| 						HTTPRoute: &rolloutv1alpha1.HTTPRouteInfo{
 | |
| 							NameAndSpecData: rolloutv1alpha1.NameAndSpecData{
 | |
| 								Name: "HTTPRoute-demo",
 | |
| 							},
 | |
| 						},
 | |
| 					},
 | |
| 				}
 | |
| 				rollouthistory.Status = rolloutv1alpha1.RolloutHistoryStatus{
 | |
| 					Phase: rolloutv1alpha1.PhaseCompleted,
 | |
| 					CanarySteps: []rolloutv1alpha1.CanaryStepInfo{
 | |
| 						{
 | |
| 							CanaryStepIndex: 1,
 | |
| 							Pods: []rolloutv1alpha1.Pod{
 | |
| 								{
 | |
| 									Name:     "pod1",
 | |
| 									IP:       "1.2.3.1",
 | |
| 									NodeName: "local",
 | |
| 								},
 | |
| 							},
 | |
| 						},
 | |
| 						{
 | |
| 							CanaryStepIndex: 2,
 | |
| 							Pods: []rolloutv1alpha1.Pod{
 | |
| 								{
 | |
| 									Name:     "pod2",
 | |
| 									IP:       "1.2.3.2",
 | |
| 									NodeName: "local",
 | |
| 								},
 | |
| 							},
 | |
| 						},
 | |
| 						{
 | |
| 							CanaryStepIndex: 3,
 | |
| 							Pods: []rolloutv1alpha1.Pod{
 | |
| 								{
 | |
| 									Name:     "pod3",
 | |
| 									IP:       "1.2.3.3",
 | |
| 									NodeName: "local",
 | |
| 								},
 | |
| 								{
 | |
| 									Name:     "pod4",
 | |
| 									IP:       "1.2.3.4",
 | |
| 									NodeName: "local",
 | |
| 								},
 | |
| 								{
 | |
| 									Name:     "pod5",
 | |
| 									IP:       "1.2.3.5",
 | |
| 									NodeName: "local",
 | |
| 								},
 | |
| 							},
 | |
| 						},
 | |
| 					},
 | |
| 				}
 | |
| 				return []*rolloutv1alpha1.RolloutHistory{rollouthistory}
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			name: "test3, don't create a new rolloutHistory for rollout without rolloutID or ObservedRolloutID",
 | |
| 			req: ctrl.Request{
 | |
| 				NamespacedName: types.NamespacedName{
 | |
| 					Namespace: "default",
 | |
| 					Name:      "rollout-demo",
 | |
| 				},
 | |
| 			},
 | |
| 			getPods: func() []*corev1.Pod {
 | |
| 				pods := []*corev1.Pod{}
 | |
| 				return pods
 | |
| 			},
 | |
| 			getService: func() []*corev1.Service {
 | |
| 				services := []*corev1.Service{}
 | |
| 				return services
 | |
| 			},
 | |
| 			getWorkload: func() []*kruisev1alpha1.CloneSet {
 | |
| 				workloads := []*kruisev1alpha1.CloneSet{}
 | |
| 				return workloads
 | |
| 			},
 | |
| 			getIngress: func() []*networkingv1.Ingress {
 | |
| 				ingresses := []*networkingv1.Ingress{}
 | |
| 				return ingresses
 | |
| 			},
 | |
| 			getHTTPRoute: func() []*v1alpha2.HTTPRoute {
 | |
| 				httpRoutes := []*v1alpha2.HTTPRoute{}
 | |
| 				return httpRoutes
 | |
| 			},
 | |
| 			getRollout: func() []*rolloutv1alpha1.Rollout {
 | |
| 				rollout := rolloutDemo1.DeepCopy()
 | |
| 				rollout.Spec.DeprecatedRolloutID = ""
 | |
| 				rollout.Status = rolloutv1alpha1.RolloutStatus{
 | |
| 					CanaryStatus: &rolloutv1alpha1.CanaryStatus{
 | |
| 						ObservedRolloutID: "",
 | |
| 					},
 | |
| 					Phase: rolloutv1alpha1.RolloutPhaseProgressing,
 | |
| 				}
 | |
| 				return []*rolloutv1alpha1.Rollout{rollout}
 | |
| 			},
 | |
| 			getRolloutHistory: func() []*rolloutv1alpha1.RolloutHistory {
 | |
| 				rollouthistories := []*rolloutv1alpha1.RolloutHistory{}
 | |
| 				return rollouthistories
 | |
| 			},
 | |
| 			expectRolloutHistory: func() []*rolloutv1alpha1.RolloutHistory {
 | |
| 				rollouthistories := []*rolloutv1alpha1.RolloutHistory{}
 | |
| 				return rollouthistories
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			name: "test4, don't create a new rolloutHistory for rollout which doesn't change its rolloutID",
 | |
| 			req: ctrl.Request{
 | |
| 				NamespacedName: types.NamespacedName{
 | |
| 					Namespace: "default",
 | |
| 					Name:      "rollout-demo",
 | |
| 				},
 | |
| 			},
 | |
| 			getPods: func() []*corev1.Pod {
 | |
| 				pods := []*corev1.Pod{}
 | |
| 				return pods
 | |
| 			},
 | |
| 			getService: func() []*corev1.Service {
 | |
| 				services := []*corev1.Service{}
 | |
| 				return services
 | |
| 			},
 | |
| 			getWorkload: func() []*kruisev1alpha1.CloneSet {
 | |
| 				workloads := []*kruisev1alpha1.CloneSet{}
 | |
| 				return workloads
 | |
| 			},
 | |
| 			getIngress: func() []*networkingv1.Ingress {
 | |
| 				ingresses := []*networkingv1.Ingress{}
 | |
| 				return ingresses
 | |
| 			},
 | |
| 			getHTTPRoute: func() []*v1alpha2.HTTPRoute {
 | |
| 				httpRoutes := []*v1alpha2.HTTPRoute{}
 | |
| 				return httpRoutes
 | |
| 			},
 | |
| 			getRollout: func() []*rolloutv1alpha1.Rollout {
 | |
| 				rollout := rolloutDemo1.DeepCopy()
 | |
| 				rollout.Spec.DeprecatedRolloutID = "4"
 | |
| 				rollout.Status = rolloutv1alpha1.RolloutStatus{
 | |
| 					CanaryStatus: &rolloutv1alpha1.CanaryStatus{
 | |
| 						ObservedRolloutID: "4",
 | |
| 					},
 | |
| 					Phase: rolloutv1alpha1.RolloutPhaseProgressing,
 | |
| 				}
 | |
| 				return []*rolloutv1alpha1.Rollout{rollout}
 | |
| 			},
 | |
| 			getRolloutHistory: func() []*rolloutv1alpha1.RolloutHistory {
 | |
| 				rollouthistory := rollouthistoryDemo.DeepCopy()
 | |
| 				rollouthistory.Labels = map[string]string{
 | |
| 					rolloutIDLabel:   "4",
 | |
| 					rolloutNameLabel: "rollout-demo",
 | |
| 				}
 | |
| 				rollouthistory.Spec = rolloutv1alpha1.RolloutHistorySpec{
 | |
| 					Rollout: rolloutv1alpha1.RolloutInfo{
 | |
| 						RolloutID: "4",
 | |
| 						NameAndSpecData: rolloutv1alpha1.NameAndSpecData{
 | |
| 							Name: "rollout-demo",
 | |
| 						},
 | |
| 					},
 | |
| 					Workload: rolloutv1alpha1.WorkloadInfo{
 | |
| 						NameAndSpecData: rolloutv1alpha1.NameAndSpecData{
 | |
| 							Name: "workload-demo",
 | |
| 						},
 | |
| 					},
 | |
| 					Service: rolloutv1alpha1.ServiceInfo{
 | |
| 						NameAndSpecData: rolloutv1alpha1.NameAndSpecData{
 | |
| 							Name: "service-demo",
 | |
| 						},
 | |
| 					},
 | |
| 					TrafficRouting: rolloutv1alpha1.TrafficRoutingInfo{
 | |
| 						Ingress: &rolloutv1alpha1.IngressInfo{
 | |
| 							NameAndSpecData: rolloutv1alpha1.NameAndSpecData{
 | |
| 								Name: "ingress-demo",
 | |
| 							},
 | |
| 						},
 | |
| 						HTTPRoute: &rolloutv1alpha1.HTTPRouteInfo{
 | |
| 							NameAndSpecData: rolloutv1alpha1.NameAndSpecData{
 | |
| 								Name: "HTTPRoute-demo",
 | |
| 							},
 | |
| 						},
 | |
| 					},
 | |
| 				}
 | |
| 				rollouthistory.Status = rolloutv1alpha1.RolloutHistoryStatus{
 | |
| 					Phase: rolloutv1alpha1.PhaseCompleted,
 | |
| 					CanarySteps: []rolloutv1alpha1.CanaryStepInfo{
 | |
| 						{
 | |
| 							CanaryStepIndex: 1,
 | |
| 							Pods: []rolloutv1alpha1.Pod{
 | |
| 								{
 | |
| 									Name:     "pod1",
 | |
| 									IP:       "1.2.3.1",
 | |
| 									NodeName: "local",
 | |
| 								},
 | |
| 							},
 | |
| 						},
 | |
| 						{
 | |
| 							CanaryStepIndex: 2,
 | |
| 							Pods: []rolloutv1alpha1.Pod{
 | |
| 								{
 | |
| 									Name:     "pod2",
 | |
| 									IP:       "1.2.3.2",
 | |
| 									NodeName: "local",
 | |
| 								},
 | |
| 							},
 | |
| 						},
 | |
| 						{
 | |
| 							CanaryStepIndex: 3,
 | |
| 							Pods: []rolloutv1alpha1.Pod{
 | |
| 								{
 | |
| 									Name:     "pod3",
 | |
| 									IP:       "1.2.3.3",
 | |
| 									NodeName: "local",
 | |
| 								},
 | |
| 								{
 | |
| 									Name:     "pod4",
 | |
| 									IP:       "1.2.3.4",
 | |
| 									NodeName: "local",
 | |
| 								},
 | |
| 								{
 | |
| 									Name:     "pod5",
 | |
| 									IP:       "1.2.3.5",
 | |
| 									NodeName: "local",
 | |
| 								},
 | |
| 							},
 | |
| 						},
 | |
| 					},
 | |
| 				}
 | |
| 				return []*rolloutv1alpha1.RolloutHistory{rollouthistory}
 | |
| 			},
 | |
| 			expectRolloutHistory: func() []*rolloutv1alpha1.RolloutHistory {
 | |
| 				rollouthistory := rollouthistoryDemo.DeepCopy()
 | |
| 				rollouthistory.Labels = map[string]string{
 | |
| 					rolloutIDLabel:   "4",
 | |
| 					rolloutNameLabel: "rollout-demo",
 | |
| 				}
 | |
| 				rollouthistory.Spec = rolloutv1alpha1.RolloutHistorySpec{
 | |
| 					Rollout: rolloutv1alpha1.RolloutInfo{
 | |
| 						RolloutID: "4",
 | |
| 						NameAndSpecData: rolloutv1alpha1.NameAndSpecData{
 | |
| 							Name: "rollout-demo",
 | |
| 						},
 | |
| 					},
 | |
| 					Workload: rolloutv1alpha1.WorkloadInfo{
 | |
| 						NameAndSpecData: rolloutv1alpha1.NameAndSpecData{
 | |
| 							Name: "workload-demo",
 | |
| 						},
 | |
| 					},
 | |
| 					Service: rolloutv1alpha1.ServiceInfo{
 | |
| 						NameAndSpecData: rolloutv1alpha1.NameAndSpecData{
 | |
| 							Name: "service-demo",
 | |
| 						},
 | |
| 					},
 | |
| 					TrafficRouting: rolloutv1alpha1.TrafficRoutingInfo{
 | |
| 						Ingress: &rolloutv1alpha1.IngressInfo{
 | |
| 							NameAndSpecData: rolloutv1alpha1.NameAndSpecData{
 | |
| 								Name: "ingress-demo",
 | |
| 							},
 | |
| 						},
 | |
| 						HTTPRoute: &rolloutv1alpha1.HTTPRouteInfo{
 | |
| 							NameAndSpecData: rolloutv1alpha1.NameAndSpecData{
 | |
| 								Name: "HTTPRoute-demo",
 | |
| 							},
 | |
| 						},
 | |
| 					},
 | |
| 				}
 | |
| 				rollouthistory.Status = rolloutv1alpha1.RolloutHistoryStatus{
 | |
| 					Phase: rolloutv1alpha1.PhaseCompleted,
 | |
| 					CanarySteps: []rolloutv1alpha1.CanaryStepInfo{
 | |
| 						{
 | |
| 							CanaryStepIndex: 1,
 | |
| 							Pods: []rolloutv1alpha1.Pod{
 | |
| 								{
 | |
| 									Name:     "pod1",
 | |
| 									IP:       "1.2.3.1",
 | |
| 									NodeName: "local",
 | |
| 								},
 | |
| 							},
 | |
| 						},
 | |
| 						{
 | |
| 							CanaryStepIndex: 2,
 | |
| 							Pods: []rolloutv1alpha1.Pod{
 | |
| 								{
 | |
| 									Name:     "pod2",
 | |
| 									IP:       "1.2.3.2",
 | |
| 									NodeName: "local",
 | |
| 								},
 | |
| 							},
 | |
| 						},
 | |
| 						{
 | |
| 							CanaryStepIndex: 3,
 | |
| 							Pods: []rolloutv1alpha1.Pod{
 | |
| 								{
 | |
| 									Name:     "pod3",
 | |
| 									IP:       "1.2.3.3",
 | |
| 									NodeName: "local",
 | |
| 								},
 | |
| 								{
 | |
| 									Name:     "pod4",
 | |
| 									IP:       "1.2.3.4",
 | |
| 									NodeName: "local",
 | |
| 								},
 | |
| 								{
 | |
| 									Name:     "pod5",
 | |
| 									IP:       "1.2.3.5",
 | |
| 									NodeName: "local",
 | |
| 								},
 | |
| 							},
 | |
| 						},
 | |
| 					},
 | |
| 				}
 | |
| 				return []*rolloutv1alpha1.RolloutHistory{rollouthistory}
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			name: "test5, don't create a new rolloutHistory for rollout if its phase isn't RolloutPhaseProgressing",
 | |
| 			req: ctrl.Request{
 | |
| 				NamespacedName: types.NamespacedName{
 | |
| 					Namespace: "default",
 | |
| 					Name:      "rollout-demo",
 | |
| 				},
 | |
| 			},
 | |
| 			getPods: func() []*corev1.Pod {
 | |
| 				pods := []*corev1.Pod{}
 | |
| 				return pods
 | |
| 			},
 | |
| 			getService: func() []*corev1.Service {
 | |
| 				services := []*corev1.Service{}
 | |
| 				return services
 | |
| 			},
 | |
| 			getWorkload: func() []*kruisev1alpha1.CloneSet {
 | |
| 				workloads := []*kruisev1alpha1.CloneSet{}
 | |
| 				return workloads
 | |
| 			},
 | |
| 			getIngress: func() []*networkingv1.Ingress {
 | |
| 				ingresses := []*networkingv1.Ingress{}
 | |
| 				return ingresses
 | |
| 			},
 | |
| 			getHTTPRoute: func() []*v1alpha2.HTTPRoute {
 | |
| 				httpRoutes := []*v1alpha2.HTTPRoute{}
 | |
| 				return httpRoutes
 | |
| 			},
 | |
| 			getRollout: func() []*rolloutv1alpha1.Rollout {
 | |
| 				rollout := rolloutDemo1.DeepCopy()
 | |
| 				rollout.Spec.DeprecatedRolloutID = "5"
 | |
| 				rollout.Status = rolloutv1alpha1.RolloutStatus{
 | |
| 					CanaryStatus: &rolloutv1alpha1.CanaryStatus{
 | |
| 						ObservedRolloutID: "5",
 | |
| 					},
 | |
| 					Phase: rolloutv1alpha1.RolloutPhaseHealthy,
 | |
| 				}
 | |
| 				return []*rolloutv1alpha1.Rollout{rollout}
 | |
| 			},
 | |
| 			getRolloutHistory: func() []*rolloutv1alpha1.RolloutHistory {
 | |
| 				rollouthistories := []*rolloutv1alpha1.RolloutHistory{}
 | |
| 				return rollouthistories
 | |
| 			},
 | |
| 			expectRolloutHistory: func() []*rolloutv1alpha1.RolloutHistory {
 | |
| 				rollouthistories := []*rolloutv1alpha1.RolloutHistory{}
 | |
| 				return rollouthistories
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for _, cs := range cases {
 | |
| 		t.Run(cs.name, func(t *testing.T) {
 | |
| 			fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithStatusSubresource(&rolloutv1alpha1.RolloutHistory{}).Build()
 | |
| 			for _, obj := range cs.getPods() {
 | |
| 				err := fakeClient.Create(context.TODO(), obj.DeepCopy(), &client.CreateOptions{})
 | |
| 				if err != nil {
 | |
| 					t.Fatalf("create Pod failed: %s", err.Error())
 | |
| 				}
 | |
| 			}
 | |
| 			for _, obj := range cs.getRollout() {
 | |
| 				err := fakeClient.Create(context.TODO(), obj.DeepCopy(), &client.CreateOptions{})
 | |
| 				if err != nil {
 | |
| 					t.Fatalf("create Rollout failed: %s", err.Error())
 | |
| 				}
 | |
| 			}
 | |
| 			for _, obj := range cs.getWorkload() {
 | |
| 				err := fakeClient.Create(context.TODO(), obj.DeepCopy(), &client.CreateOptions{})
 | |
| 				if err != nil {
 | |
| 					t.Fatalf("create Workload failed: %s", err.Error())
 | |
| 				}
 | |
| 			}
 | |
| 			for _, obj := range cs.getService() {
 | |
| 				err := fakeClient.Create(context.TODO(), obj.DeepCopy(), &client.CreateOptions{})
 | |
| 				if err != nil {
 | |
| 					t.Fatalf("create Service failed: %s", err.Error())
 | |
| 				}
 | |
| 			}
 | |
| 			for _, obj := range cs.getIngress() {
 | |
| 				err := fakeClient.Create(context.TODO(), obj.DeepCopy(), &client.CreateOptions{})
 | |
| 				if err != nil {
 | |
| 					t.Fatalf("create Ingress failed: %s", err.Error())
 | |
| 				}
 | |
| 			}
 | |
| 			for _, obj := range cs.getHTTPRoute() {
 | |
| 				err := fakeClient.Create(context.TODO(), obj.DeepCopy(), &client.CreateOptions{})
 | |
| 				if err != nil {
 | |
| 					t.Fatalf("create HTTPRoute failed: %s", err.Error())
 | |
| 				}
 | |
| 			}
 | |
| 			for _, obj := range cs.getRolloutHistory() {
 | |
| 				err := fakeClient.Create(context.TODO(), obj.DeepCopy(), &client.CreateOptions{})
 | |
| 				if err != nil {
 | |
| 					t.Fatalf("create RolloutHistory failed: %s", err.Error())
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			recon := RolloutHistoryReconciler{
 | |
| 				Client: fakeClient,
 | |
| 				Scheme: scheme,
 | |
| 				Finder: newControllerFinder2(fakeClient),
 | |
| 			}
 | |
| 
 | |
| 			// Firstly, update spec, and requeue namespacedName
 | |
| 			_, err := recon.Reconcile(context.TODO(), cs.req)
 | |
| 			if err != nil {
 | |
| 				t.Fatalf("Reconcile failed: %s", err.Error())
 | |
| 			}
 | |
| 
 | |
| 			// Secondly, update spec, and requeue namespacedName
 | |
| 			_, err = recon.Reconcile(context.TODO(), cs.req)
 | |
| 			if err != nil {
 | |
| 				t.Fatalf("Reconcile failed: %s", err.Error())
 | |
| 			}
 | |
| 
 | |
| 			if !checkRolloutHistoryInfoEqual(fakeClient, t, cs.expectRolloutHistory()) {
 | |
| 				t.Fatalf("Reconcile failed")
 | |
| 			}
 | |
| 
 | |
| 			if !checkRolloutHistoryNum(fakeClient, t, cs.expectRolloutHistory()) {
 | |
| 				t.Fatalf("RolloutHistory generated invalid: %s", err.Error())
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func checkRolloutHistoryNum(c client.WithWatch, t *testing.T, expect []*rolloutv1alpha1.RolloutHistory) bool {
 | |
| 	rollouthistories := &rolloutv1alpha1.RolloutHistoryList{}
 | |
| 	err := c.List(context.TODO(), rollouthistories, &client.ListOptions{}, client.InNamespace("default"))
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("get rollouthistories failed: %s", err.Error())
 | |
| 	}
 | |
| 	if len(rollouthistories.Items) != len(expect) {
 | |
| 		return false
 | |
| 	}
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| func checkRolloutHistoryInfoEqual(c client.WithWatch, t *testing.T, expect []*rolloutv1alpha1.RolloutHistory) bool {
 | |
| 	for i := range expect {
 | |
| 		obj := expect[i]
 | |
| 		rollouthistories := &rolloutv1alpha1.RolloutHistoryList{}
 | |
| 		err := c.List(context.TODO(), rollouthistories, &client.ListOptions{}, client.InNamespace(obj.Namespace))
 | |
| 		if err != nil {
 | |
| 			t.Fatalf("get rollouthistories failed: %s", err.Error())
 | |
| 		}
 | |
| 		// in cases, there will be just one rollouthistory
 | |
| 		if len(rollouthistories.Items) != 1 {
 | |
| 			t.Fatalf("create rollouthistory failed: %s", err.Error())
 | |
| 		}
 | |
| 		rollouthistory := rollouthistories.Items[0]
 | |
| 		// compare Label
 | |
| 		if !reflect.DeepEqual(obj.ObjectMeta.Labels, rollouthistory.ObjectMeta.Labels) {
 | |
| 			t.Fatalf("diff rollouthistory label failed: %s", err.Error())
 | |
| 			return false
 | |
| 		}
 | |
| 		// compare Spec
 | |
| 		if !checkRolloutHistorySpec(&obj.Spec, &rollouthistory.Spec) {
 | |
| 			t.Fatalf("diff rollouthistory spec failed: %s", err.Error())
 | |
| 			return false
 | |
| 		}
 | |
| 		// compare status
 | |
| 		// in the first reconcile, there is only spec updated
 | |
| 		if !checkRolloutHistoryStatus(&obj.Status, &rollouthistory.Status) {
 | |
| 			t.Fatalf("diff rollouthistory status failed: %s", err.Error())
 | |
| 			return false
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| func checkRolloutHistorySpec(spec1 *rolloutv1alpha1.RolloutHistorySpec, spec2 *rolloutv1alpha1.RolloutHistorySpec) bool {
 | |
| 	// spec1 and spec2 may be empty when rollouthistory is not completed
 | |
| 	if reflect.DeepEqual(spec1, spec2) {
 | |
| 		return true
 | |
| 	}
 | |
| 	// just compare those fields
 | |
| 	if spec1.Rollout.Name != spec2.Rollout.Name ||
 | |
| 		spec1.Service.Name != spec2.Service.Name ||
 | |
| 		spec1.Workload.Name != spec2.Workload.Name ||
 | |
| 		spec1.Rollout.RolloutID != spec2.Rollout.RolloutID ||
 | |
| 		spec1.TrafficRouting.Ingress.Name != spec2.TrafficRouting.Ingress.Name ||
 | |
| 		spec1.TrafficRouting.HTTPRoute.Name != spec2.TrafficRouting.HTTPRoute.Name {
 | |
| 		return false
 | |
| 	}
 | |
| 
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| func checkRolloutHistoryStatus(status1 *rolloutv1alpha1.RolloutHistoryStatus, status2 *rolloutv1alpha1.RolloutHistoryStatus) bool {
 | |
| 	// in the first reconcile, there is only spec updated
 | |
| 	// status1 and status2 may be empty when rollouthistory is not completed
 | |
| 	if reflect.DeepEqual(status1, status2) {
 | |
| 		return true
 | |
| 	}
 | |
| 	// just compare those fields
 | |
| 	if status1.Phase != status2.Phase ||
 | |
| 		len(status1.CanarySteps) != len(status2.CanarySteps) {
 | |
| 		return false
 | |
| 	}
 | |
| 	// compare canarySteps, including CanaryStepIndex and pods for each canaryStep
 | |
| 	for i := 0; i < len(status1.CanarySteps); i++ {
 | |
| 		step1 := status1.CanarySteps[i]
 | |
| 		step2 := status2.CanarySteps[i]
 | |
| 		if step1.CanaryStepIndex != step2.CanaryStepIndex {
 | |
| 			return false
 | |
| 		}
 | |
| 		if len(step1.Pods) != len(step2.Pods) {
 | |
| 			return false
 | |
| 		}
 | |
| 		for j := 0; j < len(step1.Pods); j++ {
 | |
| 			if step1.Pods[j].IP != step2.Pods[j].IP ||
 | |
| 				step1.Pods[j].Name != step2.Pods[j].Name ||
 | |
| 				step1.Pods[j].NodeName != step2.Pods[j].NodeName {
 | |
| 				return false
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return true
 | |
| }
 |