Commit 722b0a6c authored by Jerzy Szczepkowski's avatar Jerzy Szczepkowski

Unittests for horizontal pod autoscaler controller.

Unittests for horizontal pod autoscaler controller.
parent 400e6856
...@@ -77,6 +77,5 @@ func (c *FakeServices) Watch(label labels.Selector, field fields.Selector, resou ...@@ -77,6 +77,5 @@ func (c *FakeServices) Watch(label labels.Selector, field fields.Selector, resou
} }
func (c *FakeServices) ProxyGet(name, path string, params map[string]string) unversioned.ResponseWrapper { func (c *FakeServices) ProxyGet(name, path string, params map[string]string) unversioned.ResponseWrapper {
c.Fake.Invokes(NewProxyGetAction("services", c.Namespace, name, path, params), nil) return c.Fake.InvokesProxy(NewProxyGetAction("services", c.Namespace, name, path, params))
return nil
} }
...@@ -25,6 +25,7 @@ import ( ...@@ -25,6 +25,7 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/meta"
client "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/yaml" "k8s.io/kubernetes/pkg/util/yaml"
"k8s.io/kubernetes/pkg/watch" "k8s.io/kubernetes/pkg/watch"
...@@ -260,7 +261,7 @@ func (r *SimpleReactor) React(action Action) (bool, runtime.Object, error) { ...@@ -260,7 +261,7 @@ func (r *SimpleReactor) React(action Action) (bool, runtime.Object, error) {
return r.Reaction(action) return r.Reaction(action)
} }
// SimpleWatchReactor is a Reactor. Each reaction function is attached to a given verb,resource tuple. "*" in either field matches everything for that value. // SimpleWatchReactor is a WatchReactor. Each reaction function is attached to a given resource. "*" matches everything for that value.
// For instance, *,pods matches all verbs on pods. This allows for easier composition of reaction functions // For instance, *,pods matches all verbs on pods. This allows for easier composition of reaction functions
type SimpleWatchReactor struct { type SimpleWatchReactor struct {
Resource string Resource string
...@@ -280,3 +281,24 @@ func (r *SimpleWatchReactor) Handles(action Action) bool { ...@@ -280,3 +281,24 @@ func (r *SimpleWatchReactor) Handles(action Action) bool {
func (r *SimpleWatchReactor) React(action Action) (bool, watch.Interface, error) { func (r *SimpleWatchReactor) React(action Action) (bool, watch.Interface, error) {
return r.Reaction(action) return r.Reaction(action)
} }
// SimpleProxyReactor is a ProxyReactor. Each reaction function is attached to a given resource. "*" matches everything for that value.
// For instance, *,pods matches all verbs on pods. This allows for easier composition of reaction functions.
type SimpleProxyReactor struct {
Resource string
Reaction ProxyReactionFunc
}
func (r *SimpleProxyReactor) Handles(action Action) bool {
resourceCovers := r.Resource == "*" || r.Resource == action.GetResource()
if !resourceCovers {
return false
}
return true
}
func (r *SimpleProxyReactor) React(action Action) (bool, client.ResponseWrapper, error) {
return r.Reaction(action)
}
...@@ -54,6 +54,8 @@ type Fake struct { ...@@ -54,6 +54,8 @@ type Fake struct {
ReactionChain []Reactor ReactionChain []Reactor
// WatchReactionChain is the list of watch reactors that will be attempted for every request in the order they are tried // WatchReactionChain is the list of watch reactors that will be attempted for every request in the order they are tried
WatchReactionChain []WatchReactor WatchReactionChain []WatchReactor
// ProxyReactionChain is the list of proxy reactors that will be attempted for every request in the order they are tried
ProxyReactionChain []ProxyReactor
} }
// Reactor is an interface to allow the composition of reaction functions. // Reactor is an interface to allow the composition of reaction functions.
...@@ -72,6 +74,14 @@ type WatchReactor interface { ...@@ -72,6 +74,14 @@ type WatchReactor interface {
React(action Action) (handled bool, ret watch.Interface, err error) React(action Action) (handled bool, ret watch.Interface, err error)
} }
// ProxyReactor is an interface to allow the composition of proxy get functions.
type ProxyReactor interface {
// Handles indicates whether or not this Reactor deals with a given action
Handles(action Action) bool
// React handles a watch action and returns results. It may choose to delegate by indicated handled=false
React(action Action) (handled bool, ret client.ResponseWrapper, err error)
}
// ReactionFunc is a function that returns an object or error for a given Action. If "handled" is false, // ReactionFunc is a function that returns an object or error for a given Action. If "handled" is false,
// then the test client will continue ignore the results and continue to the next ReactionFunc // then the test client will continue ignore the results and continue to the next ReactionFunc
type ReactionFunc func(action Action) (handled bool, ret runtime.Object, err error) type ReactionFunc func(action Action) (handled bool, ret runtime.Object, err error)
...@@ -80,6 +90,10 @@ type ReactionFunc func(action Action) (handled bool, ret runtime.Object, err err ...@@ -80,6 +90,10 @@ type ReactionFunc func(action Action) (handled bool, ret runtime.Object, err err
// then the test client will continue ignore the results and continue to the next ReactionFunc // then the test client will continue ignore the results and continue to the next ReactionFunc
type WatchReactionFunc func(action Action) (handled bool, ret watch.Interface, err error) type WatchReactionFunc func(action Action) (handled bool, ret watch.Interface, err error)
// ProxyReactionFunc is a function that returns a ResponseWrapper interface for a given Action. If "handled" is false,
// then the test client will continue ignore the results and continue to the next ProxyReactionFunc
type ProxyReactionFunc func(action Action) (handled bool, ret client.ResponseWrapper, err error)
// AddReactor appends a reactor to the end of the chain // AddReactor appends a reactor to the end of the chain
func (c *Fake) AddReactor(verb, resource string, reaction ReactionFunc) { func (c *Fake) AddReactor(verb, resource string, reaction ReactionFunc) {
c.ReactionChain = append(c.ReactionChain, &SimpleReactor{verb, resource, reaction}) c.ReactionChain = append(c.ReactionChain, &SimpleReactor{verb, resource, reaction})
...@@ -97,6 +111,11 @@ func (c *Fake) AddWatchReactor(resource string, reaction WatchReactionFunc) { ...@@ -97,6 +111,11 @@ func (c *Fake) AddWatchReactor(resource string, reaction WatchReactionFunc) {
c.WatchReactionChain = append(c.WatchReactionChain, &SimpleWatchReactor{resource, reaction}) c.WatchReactionChain = append(c.WatchReactionChain, &SimpleWatchReactor{resource, reaction})
} }
// AddProxyReactor appends a reactor to the end of the chain
func (c *Fake) AddProxyReactor(resource string, reaction ProxyReactionFunc) {
c.ProxyReactionChain = append(c.ProxyReactionChain, &SimpleProxyReactor{resource, reaction})
}
// Invokes records the provided Action and then invokes the ReactFn (if provided). // Invokes records the provided Action and then invokes the ReactFn (if provided).
// defaultReturnObj is expected to be of the same type a normal call would return. // defaultReturnObj is expected to be of the same type a normal call would return.
func (c *Fake) Invokes(action Action, defaultReturnObj runtime.Object) (runtime.Object, error) { func (c *Fake) Invokes(action Action, defaultReturnObj runtime.Object) (runtime.Object, error) {
...@@ -142,6 +161,28 @@ func (c *Fake) InvokesWatch(action Action) (watch.Interface, error) { ...@@ -142,6 +161,28 @@ func (c *Fake) InvokesWatch(action Action) (watch.Interface, error) {
return nil, fmt.Errorf("unhandled watch: %#v", action) return nil, fmt.Errorf("unhandled watch: %#v", action)
} }
// InvokesProxy records the provided Action and then invokes the ReactFn (if provided).
func (c *Fake) InvokesProxy(action Action) client.ResponseWrapper {
c.Lock()
defer c.Unlock()
c.actions = append(c.actions, action)
for _, reactor := range c.ProxyReactionChain {
if !reactor.Handles(action) {
continue
}
handled, ret, err := reactor.React(action)
if !handled || err != nil {
continue
}
return ret
}
return nil
}
// ClearActions clears the history of actions called on the fake client // ClearActions clears the history of actions called on the fake client
func (c *Fake) ClearActions() { func (c *Fake) ClearActions() {
c.Lock() c.Lock()
......
...@@ -79,8 +79,9 @@ func (a *HorizontalController) reconcileAutoscaler(hpa experimental.HorizontalPo ...@@ -79,8 +79,9 @@ func (a *HorizontalController) reconcileAutoscaler(hpa experimental.HorizontalPo
return fmt.Errorf("failed to query scale subresource for %s: %v", reference, err) return fmt.Errorf("failed to query scale subresource for %s: %v", reference, err)
} }
currentReplicas := scale.Status.Replicas currentReplicas := scale.Status.Replicas
currentConsumption, err := a.metricsClient.ResourceConsumption(hpa.Spec.ScaleRef.Namespace).Get(hpa.Spec.Target.Resource, currentConsumption, err := a.metricsClient.
scale.Status.Selector) ResourceConsumption(hpa.Spec.ScaleRef.Namespace).
Get(hpa.Spec.Target.Resource, scale.Status.Selector)
// TODO: what to do on partial errors (like metrics obtained for 75% of pods). // TODO: what to do on partial errors (like metrics obtained for 75% of pods).
if err != nil { if err != nil {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment