func (tc *testCase) prepareTestClient(t *testing.T) *testclient.Fake { namespace := "test-namespace" tc.namespace = namespace podNamePrefix := "test-pod" selector := map[string]string{"name": podNamePrefix} tc.selector = selector fakeClient := &testclient.Fake{} fakeClient.AddReactor("list", "pods", func(action testclient.Action) (handled bool, ret runtime.Object, err error) { obj := &api.PodList{} for i := 0; i < tc.replicas; i++ { podName := fmt.Sprintf("%s-%d", podNamePrefix, i) pod := api.Pod{ Status: api.PodStatus{ Phase: api.PodRunning, }, ObjectMeta: api.ObjectMeta{ Name: podName, Namespace: namespace, Labels: selector, }, } obj.Items = append(obj.Items, pod) } return true, obj, nil }) fakeClient.AddProxyReactor("services", func(action testclient.Action) (handled bool, ret client.ResponseWrapper, err error) { metrics := heapster.MetricResultList{} firstTimestamp := time.Now() var latestTimestamp time.Time for _, reportedMetricPoints := range tc.reportedMetricsPoints { var heapsterMetricPoints []heapster.MetricPoint for _, reportedMetricPoint := range reportedMetricPoints { timestamp := firstTimestamp.Add(time.Duration(reportedMetricPoint.timestamp) * time.Minute) if latestTimestamp.Before(timestamp) { latestTimestamp = timestamp } heapsterMetricPoint := heapster.MetricPoint{timestamp, reportedMetricPoint.level} heapsterMetricPoints = append(heapsterMetricPoints, heapsterMetricPoint) } metric := heapster.MetricResult{ Metrics: heapsterMetricPoints, LatestTimestamp: latestTimestamp, } metrics.Items = append(metrics.Items, metric) } heapsterRawMemResponse, _ := json.Marshal(&metrics) return true, newFakeResponseWrapper(heapsterRawMemResponse), nil }) return fakeClient }
func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset { namespace := "test-namespace" tc.namespace = namespace podNamePrefix := "test-pod" podLabels := map[string]string{"name": podNamePrefix} tc.selector = labels.SelectorFromSet(podLabels) fakeClient := &fake.Clientset{} fakeClient.AddReactor("list", "pods", func(action core.Action) (handled bool, ret runtime.Object, err error) { if tc.podListOverride != nil { return true, tc.podListOverride, nil } obj := &api.PodList{} for i := 0; i < tc.replicas; i++ { podName := fmt.Sprintf("%s-%d", podNamePrefix, i) pod := buildPod(namespace, podName, podLabels, api.PodRunning) obj.Items = append(obj.Items, pod) } return true, obj, nil }) fakeClient.AddProxyReactor("services", func(action core.Action) (handled bool, ret restclient.ResponseWrapper, err error) { metrics := heapster.MetricResultList{} var latestTimestamp time.Time for _, reportedMetricPoints := range tc.reportedMetricsPoints { var heapsterMetricPoints []heapster.MetricPoint for _, reportedMetricPoint := range reportedMetricPoints { timestamp := fixedTimestamp.Add(time.Duration(reportedMetricPoint.timestamp) * time.Minute) if latestTimestamp.Before(timestamp) { latestTimestamp = timestamp } heapsterMetricPoint := heapster.MetricPoint{timestamp, reportedMetricPoint.level, nil} heapsterMetricPoints = append(heapsterMetricPoints, heapsterMetricPoint) } metric := heapster.MetricResult{ Metrics: heapsterMetricPoints, LatestTimestamp: latestTimestamp, } metrics.Items = append(metrics.Items, metric) } heapsterRawMemResponse, _ := json.Marshal(&metrics) return true, newFakeResponseWrapper(heapsterRawMemResponse), nil }) return fakeClient }
func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset { namespace := "test-namespace" hpaName := "test-hpa" rcName := "test-rc" podNamePrefix := "test-pod" tc.scaleUpdated = false tc.statusUpdated = false tc.eventCreated = false fakeClient := &fake.Clientset{} fakeClient.AddReactor("list", "horizontalpodautoscalers", func(action core.Action) (handled bool, ret runtime.Object, err error) { obj := &extensions.HorizontalPodAutoscalerList{ Items: []extensions.HorizontalPodAutoscaler{ { ObjectMeta: api.ObjectMeta{ Name: hpaName, Namespace: namespace, SelfLink: "experimental/v1/namespaces/" + namespace + "/horizontalpodautoscalers/" + hpaName, }, Spec: extensions.HorizontalPodAutoscalerSpec{ ScaleRef: extensions.SubresourceReference{ Kind: "replicationController", Name: rcName, Subresource: "scale", }, MinReplicas: &tc.minReplicas, MaxReplicas: tc.maxReplicas, }, Status: extensions.HorizontalPodAutoscalerStatus{ CurrentReplicas: tc.initialReplicas, DesiredReplicas: tc.initialReplicas, }, }, }, } if tc.CPUTarget > 0.0 { obj.Items[0].Spec.CPUUtilization = &extensions.CPUTargetUtilization{TargetPercentage: tc.CPUTarget} } if tc.cmTarget != nil { b, err := json.Marshal(tc.cmTarget) if err != nil { t.Fatalf("Failed to marshal cm: %v", err) } obj.Items[0].Annotations = make(map[string]string) obj.Items[0].Annotations[HpaCustomMetricsTargetAnnotationName] = string(b) } return true, obj, nil }) fakeClient.AddReactor("get", "replicationController", func(action core.Action) (handled bool, ret runtime.Object, err error) { obj := &extensions.Scale{ ObjectMeta: api.ObjectMeta{ Name: rcName, Namespace: namespace, }, Spec: extensions.ScaleSpec{ Replicas: tc.initialReplicas, }, Status: extensions.ScaleStatus{ Replicas: tc.initialReplicas, Selector: map[string]string{"name": podNamePrefix}, }, } return true, obj, nil }) fakeClient.AddReactor("list", "pods", func(action core.Action) (handled bool, ret runtime.Object, err error) { obj := &api.PodList{} for i := 0; i < len(tc.reportedCPURequests); i++ { podName := fmt.Sprintf("%s-%d", podNamePrefix, i) pod := api.Pod{ Status: api.PodStatus{ Phase: api.PodRunning, }, ObjectMeta: api.ObjectMeta{ Name: podName, Namespace: namespace, Labels: map[string]string{ "name": podNamePrefix, }, }, Spec: api.PodSpec{ Containers: []api.Container{ { Resources: api.ResourceRequirements{ Requests: api.ResourceList{ api.ResourceCPU: tc.reportedCPURequests[i], }, }, }, }, }, } obj.Items = append(obj.Items, pod) } return true, obj, nil }) fakeClient.AddProxyReactor("services", func(action core.Action) (handled bool, ret client.ResponseWrapper, err error) { timestamp := time.Now() metrics := heapster.MetricResultList{} for _, level := range tc.reportedLevels { metric := heapster.MetricResult{ Metrics: []heapster.MetricPoint{{timestamp, level, nil}}, LatestTimestamp: timestamp, } metrics.Items = append(metrics.Items, metric) } heapsterRawMemResponse, _ := json.Marshal(&metrics) return true, newFakeResponseWrapper(heapsterRawMemResponse), nil }) fakeClient.AddReactor("update", "replicationController", func(action core.Action) (handled bool, ret runtime.Object, err error) { obj := action.(testclient.UpdateAction).GetObject().(*extensions.Scale) replicas := action.(testclient.UpdateAction).GetObject().(*extensions.Scale).Spec.Replicas assert.Equal(t, tc.desiredReplicas, replicas) tc.scaleUpdated = true return true, obj, nil }) fakeClient.AddReactor("update", "horizontalpodautoscalers", func(action core.Action) (handled bool, ret runtime.Object, err error) { obj := action.(testclient.UpdateAction).GetObject().(*extensions.HorizontalPodAutoscaler) assert.Equal(t, namespace, obj.Namespace) assert.Equal(t, hpaName, obj.Name) assert.Equal(t, tc.desiredReplicas, obj.Status.DesiredReplicas) tc.statusUpdated = true return true, obj, nil }) fakeClient.AddReactor("*", "events", func(action core.Action) (handled bool, ret runtime.Object, err error) { obj := action.(testclient.CreateAction).GetObject().(*api.Event) if tc.verifyEvents { assert.Equal(t, "SuccessfulRescale", obj.Reason) assert.Equal(t, fmt.Sprintf("New size: %d", tc.desiredReplicas), obj.Message) } tc.eventCreated = true return true, obj, nil }) return fakeClient }
func (tc *testCase) prepareTestClient(t *testing.T) *testclient.Fake { namespace := "test-namespace" hpaName := "test-hpa" rcName := "test-rc" podNamePrefix := "test-pod" tc.scaleUpdated = false tc.eventCreated = false fakeClient := &testclient.Fake{} fakeClient.AddReactor("list", "horizontalpodautoscalers", func(action testclient.Action) (handled bool, ret runtime.Object, err error) { obj := &extensions.HorizontalPodAutoscalerList{ Items: []extensions.HorizontalPodAutoscaler{ { ObjectMeta: api.ObjectMeta{ Name: hpaName, Namespace: namespace, SelfLink: "experimental/v1/namespaces/" + namespace + "/horizontalpodautoscalers/" + hpaName, }, Spec: extensions.HorizontalPodAutoscalerSpec{ ScaleRef: &extensions.SubresourceReference{ Kind: "replicationController", Name: rcName, Namespace: namespace, Subresource: "scale", }, MinReplicas: tc.minReplicas, MaxReplicas: tc.maxReplicas, Target: extensions.ResourceConsumption{Resource: tc.targetResource, Quantity: tc.targetLevel}, }, }, }, } return true, obj, nil }) fakeClient.AddReactor("get", "replicationController", func(action testclient.Action) (handled bool, ret runtime.Object, err error) { obj := &extensions.Scale{ ObjectMeta: api.ObjectMeta{ Name: rcName, Namespace: namespace, }, Spec: extensions.ScaleSpec{ Replicas: tc.initialReplicas, }, Status: extensions.ScaleStatus{ Replicas: tc.initialReplicas, Selector: map[string]string{"name": podNamePrefix}, }, } return true, obj, nil }) fakeClient.AddReactor("list", "pods", func(action testclient.Action) (handled bool, ret runtime.Object, err error) { obj := &api.PodList{} for i := 0; i < tc.initialReplicas; i++ { podName := fmt.Sprintf("%s-%d", podNamePrefix, i) pod := api.Pod{ Status: api.PodStatus{ Phase: api.PodRunning, }, ObjectMeta: api.ObjectMeta{ Name: podName, Namespace: namespace, Labels: map[string]string{ "name": podNamePrefix, }, }, } obj.Items = append(obj.Items, pod) } return true, obj, nil }) fakeClient.AddProxyReactor("services", func(action testclient.Action) (handled bool, ret client.ResponseWrapper, err error) { timestamp := time.Now() metrics := heapster.MetricResultList{} for _, level := range tc.reportedLevels { metric := heapster.MetricResult{ Metrics: []heapster.MetricPoint{{timestamp, level}}, LatestTimestamp: timestamp, } metrics.Items = append(metrics.Items, metric) } heapsterRawMemResponse, _ := json.Marshal(&metrics) return true, newFakeResponseWrapper(heapsterRawMemResponse), nil }) fakeClient.AddReactor("update", "replicationController", func(action testclient.Action) (handled bool, ret runtime.Object, err error) { obj := action.(testclient.UpdateAction).GetObject().(*extensions.Scale) replicas := action.(testclient.UpdateAction).GetObject().(*extensions.Scale).Spec.Replicas assert.Equal(t, tc.desiredReplicas, replicas) tc.scaleUpdated = true return true, obj, nil }) fakeClient.AddReactor("update", "horizontalpodautoscalers", func(action testclient.Action) (handled bool, ret runtime.Object, err error) { obj := action.(testclient.UpdateAction).GetObject().(*extensions.HorizontalPodAutoscaler) assert.Equal(t, namespace, obj.Namespace) assert.Equal(t, hpaName, obj.Name) assert.Equal(t, tc.desiredReplicas, obj.Status.DesiredReplicas) return true, obj, nil }) fakeClient.AddReactor("*", "events", func(action testclient.Action) (handled bool, ret runtime.Object, err error) { obj := action.(testclient.CreateAction).GetObject().(*api.Event) if tc.verifyEvents { assert.Equal(t, "SuccessfulRescale", obj.Reason) assert.Equal(t, fmt.Sprintf("New size: %d", tc.desiredReplicas), obj.Message) } tc.eventCreated = true return true, obj, nil }) return fakeClient }
func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset { namespace := "test-namespace" hpaName := "test-hpa" podNamePrefix := "test-pod" selector := &unversioned.LabelSelector{ MatchLabels: map[string]string{"name": podNamePrefix}, } tc.Lock() tc.scaleUpdated = false tc.statusUpdated = false tc.eventCreated = false tc.processed = make(chan string, 100) tc.computeCPUCurrent() // TODO(madhusudancs): HPA only supports resources in extensions/v1beta1 right now. Add // tests for "v1" replicationcontrollers when HPA adds support for cross-group scale. if tc.resource == nil { tc.resource = &fakeResource{ name: "test-rc", apiVersion: "extensions/v1beta1", kind: "replicationcontrollers", } } tc.Unlock() fakeClient := &fake.Clientset{} fakeClient.AddReactor("list", "horizontalpodautoscalers", func(action core.Action) (handled bool, ret runtime.Object, err error) { tc.Lock() defer tc.Unlock() obj := &extensions.HorizontalPodAutoscalerList{ Items: []extensions.HorizontalPodAutoscaler{ { ObjectMeta: api.ObjectMeta{ Name: hpaName, Namespace: namespace, SelfLink: "experimental/v1/namespaces/" + namespace + "/horizontalpodautoscalers/" + hpaName, }, Spec: extensions.HorizontalPodAutoscalerSpec{ ScaleRef: extensions.SubresourceReference{ Kind: tc.resource.kind, Name: tc.resource.name, APIVersion: tc.resource.apiVersion, Subresource: "scale", }, MinReplicas: &tc.minReplicas, MaxReplicas: tc.maxReplicas, }, Status: extensions.HorizontalPodAutoscalerStatus{ CurrentReplicas: tc.initialReplicas, DesiredReplicas: tc.initialReplicas, }, }, }, } if tc.CPUTarget > 0.0 { obj.Items[0].Spec.CPUUtilization = &extensions.CPUTargetUtilization{TargetPercentage: tc.CPUTarget} } if tc.cmTarget != nil { b, err := json.Marshal(tc.cmTarget) if err != nil { t.Fatalf("Failed to marshal cm: %v", err) } obj.Items[0].Annotations = make(map[string]string) obj.Items[0].Annotations[HpaCustomMetricsTargetAnnotationName] = string(b) } return true, obj, nil }) fakeClient.AddReactor("get", "replicationcontrollers", func(action core.Action) (handled bool, ret runtime.Object, err error) { tc.Lock() defer tc.Unlock() obj := &extensions.Scale{ ObjectMeta: api.ObjectMeta{ Name: tc.resource.name, Namespace: namespace, }, Spec: extensions.ScaleSpec{ Replicas: tc.initialReplicas, }, Status: extensions.ScaleStatus{ Replicas: tc.initialReplicas, Selector: selector, }, } return true, obj, nil }) fakeClient.AddReactor("get", "deployments", func(action core.Action) (handled bool, ret runtime.Object, err error) { tc.Lock() defer tc.Unlock() obj := &extensions.Scale{ ObjectMeta: api.ObjectMeta{ Name: tc.resource.name, Namespace: namespace, }, Spec: extensions.ScaleSpec{ Replicas: tc.initialReplicas, }, Status: extensions.ScaleStatus{ Replicas: tc.initialReplicas, Selector: selector, }, } return true, obj, nil }) fakeClient.AddReactor("get", "replicasets", func(action core.Action) (handled bool, ret runtime.Object, err error) { tc.Lock() defer tc.Unlock() obj := &extensions.Scale{ ObjectMeta: api.ObjectMeta{ Name: tc.resource.name, Namespace: namespace, }, Spec: extensions.ScaleSpec{ Replicas: tc.initialReplicas, }, Status: extensions.ScaleStatus{ Replicas: tc.initialReplicas, Selector: selector, }, } return true, obj, nil }) fakeClient.AddReactor("list", "pods", func(action core.Action) (handled bool, ret runtime.Object, err error) { tc.Lock() defer tc.Unlock() obj := &api.PodList{} for i := 0; i < len(tc.reportedCPURequests); i++ { podName := fmt.Sprintf("%s-%d", podNamePrefix, i) pod := api.Pod{ Status: api.PodStatus{ Phase: api.PodRunning, }, ObjectMeta: api.ObjectMeta{ Name: podName, Namespace: namespace, Labels: map[string]string{ "name": podNamePrefix, }, }, Spec: api.PodSpec{ Containers: []api.Container{ { Resources: api.ResourceRequirements{ Requests: api.ResourceList{ api.ResourceCPU: tc.reportedCPURequests[i], }, }, }, }, }, } obj.Items = append(obj.Items, pod) } return true, obj, nil }) fakeClient.AddProxyReactor("services", func(action core.Action) (handled bool, ret restclient.ResponseWrapper, err error) { tc.Lock() defer tc.Unlock() timestamp := time.Now() metrics := heapster.MetricResultList{} for _, level := range tc.reportedLevels { metric := heapster.MetricResult{ Metrics: []heapster.MetricPoint{{timestamp, level, nil}}, LatestTimestamp: timestamp, } metrics.Items = append(metrics.Items, metric) } heapsterRawMemResponse, _ := json.Marshal(&metrics) return true, newFakeResponseWrapper(heapsterRawMemResponse), nil }) fakeClient.AddReactor("update", "replicationcontrollers", func(action core.Action) (handled bool, ret runtime.Object, err error) { tc.Lock() defer tc.Unlock() obj := action.(testclient.UpdateAction).GetObject().(*extensions.Scale) replicas := action.(testclient.UpdateAction).GetObject().(*extensions.Scale).Spec.Replicas assert.Equal(t, tc.desiredReplicas, replicas) tc.scaleUpdated = true return true, obj, nil }) fakeClient.AddReactor("update", "deployments", func(action core.Action) (handled bool, ret runtime.Object, err error) { tc.Lock() defer tc.Unlock() obj := action.(testclient.UpdateAction).GetObject().(*extensions.Scale) replicas := action.(testclient.UpdateAction).GetObject().(*extensions.Scale).Spec.Replicas assert.Equal(t, tc.desiredReplicas, replicas) tc.scaleUpdated = true return true, obj, nil }) fakeClient.AddReactor("update", "replicasets", func(action core.Action) (handled bool, ret runtime.Object, err error) { tc.Lock() defer tc.Unlock() obj := action.(testclient.UpdateAction).GetObject().(*extensions.Scale) replicas := action.(testclient.UpdateAction).GetObject().(*extensions.Scale).Spec.Replicas assert.Equal(t, tc.desiredReplicas, replicas) tc.scaleUpdated = true return true, obj, nil }) fakeClient.AddReactor("update", "horizontalpodautoscalers", func(action core.Action) (handled bool, ret runtime.Object, err error) { tc.Lock() defer tc.Unlock() obj := action.(testclient.UpdateAction).GetObject().(*extensions.HorizontalPodAutoscaler) assert.Equal(t, namespace, obj.Namespace) assert.Equal(t, hpaName, obj.Name) assert.Equal(t, tc.desiredReplicas, obj.Status.DesiredReplicas) if tc.verifyCPUCurrent { assert.NotNil(t, obj.Status.CurrentCPUUtilizationPercentage) assert.Equal(t, tc.CPUCurrent, *obj.Status.CurrentCPUUtilizationPercentage) } tc.statusUpdated = true // Every time we reconcile HPA object we are updating status. tc.processed <- obj.Name return true, obj, nil }) fakeClient.AddReactor("*", "events", func(action core.Action) (handled bool, ret runtime.Object, err error) { tc.Lock() defer tc.Unlock() obj := action.(testclient.CreateAction).GetObject().(*api.Event) if tc.verifyEvents { assert.Equal(t, "SuccessfulRescale", obj.Reason) assert.Equal(t, fmt.Sprintf("New size: %d; reason: CPU utilization above target", tc.desiredReplicas), obj.Message) } tc.eventCreated = true return true, obj, nil }) fakeWatch := watch.NewFake() fakeClient.AddWatchReactor("*", core.DefaultWatchReactor(fakeWatch, nil)) return fakeClient }