From 7271220b10ab0ad59a095d0ed46d08353977e87a Mon Sep 17 00:00:00 2001 From: Slawomir Chylek Date: Fri, 19 Jan 2018 15:22:49 +0100 Subject: [PATCH] recommender_mock removed --- .../recommender_mock/caching_recommender.go | 84 ---------------- .../caching_recommender_test.go | 94 ------------------ .../recommender_mock/ttl_cache.go | 97 ------------------- .../recommender_mock/ttl_cache_test.go | 63 ------------ 4 files changed, 338 deletions(-) delete mode 100644 vertical-pod-autoscaler/recommender_mock/caching_recommender.go delete mode 100644 vertical-pod-autoscaler/recommender_mock/caching_recommender_test.go delete mode 100644 vertical-pod-autoscaler/recommender_mock/ttl_cache.go delete mode 100644 vertical-pod-autoscaler/recommender_mock/ttl_cache_test.go diff --git a/vertical-pod-autoscaler/recommender_mock/caching_recommender.go b/vertical-pod-autoscaler/recommender_mock/caching_recommender.go deleted file mode 100644 index 7826a9c7a1..0000000000 --- a/vertical-pod-autoscaler/recommender_mock/caching_recommender.go +++ /dev/null @@ -1,84 +0,0 @@ -/* -Copyright 2017 The Kubernetes 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 recommender - -import ( - "crypto/sha1" - "fmt" - "runtime" - "time" - - "k8s.io/autoscaler/vertical-pod-autoscaler/apimock" - - apiv1 "k8s.io/api/core/v1" - hashutil "k8s.io/kubernetes/pkg/util/hash" -) - -// CachingRecommender provides VPA recommendations for pods. -// VPA responses are cached. -type CachingRecommender interface { - // Get returns VPA recommendation for given pod - Get(spec *apiv1.PodSpec) (*apimock.Recommendation, error) -} - -type cachingRecommenderImpl struct { - api apimock.RecommenderAPI - cache *TTLCache -} - -// NewCachingRecommender creates CachingRecommender with given cache TTL -func NewCachingRecommender(ttl time.Duration, api apimock.RecommenderAPI) CachingRecommender { - ca := NewTTLCache(ttl) - ca.StartCacheGC(ttl) - - result := &cachingRecommenderImpl{api: api, cache: ca} - // We need to stop background cacheGC worker if cachingRecommenderImpl gets destryed. - // If we forget this, background go routine will forever run and hold a reference to TTLCache object. - runtime.SetFinalizer(result, stopChacheGC) - - return result -} - -// Get returns VPA recommendation for the given pod. If recommendation is not in cache, sends request to RecommenderAPI -func (c *cachingRecommenderImpl) Get(spec *apiv1.PodSpec) (*apimock.Recommendation, error) { - cacheKey := getCacheKey(spec) - if cacheKey != nil { - if cached := c.cache.Get(cacheKey); cached != nil { - return cached.(*apimock.Recommendation), nil - } - } - - response, err := c.api.GetRecommendation(spec) - if err != nil { - return nil, fmt.Errorf("error fetching recommendation %v", err) - } - if response != nil && cacheKey != nil { - c.cache.Set(cacheKey, response) - } - return response, nil -} - -func getCacheKey(spec *apiv1.PodSpec) *string { - podTemplateSpecHasher := sha1.New() - hashutil.DeepHashObject(podTemplateSpecHasher, *spec) - result := string(podTemplateSpecHasher.Sum(make([]byte, 0))) - return &result -} - -func stopChacheGC(c *cachingRecommenderImpl) { - c.cache.StopCacheGC() -} diff --git a/vertical-pod-autoscaler/recommender_mock/caching_recommender_test.go b/vertical-pod-autoscaler/recommender_mock/caching_recommender_test.go deleted file mode 100644 index 9318ab08f3..0000000000 --- a/vertical-pod-autoscaler/recommender_mock/caching_recommender_test.go +++ /dev/null @@ -1,94 +0,0 @@ -/* -Copyright 2017 The Kubernetes 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 recommender - -import ( - "fmt" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/test" -) - -func TestGetWithCache(t *testing.T) { - apiMock := &test.RecommenderAPIMock{} - rec := test.Recommendation("test", "", "") - pod := test.BuildTestPod("test", "", "", "", nil, nil) - apiMock.On("GetRecommendation", &pod.Spec).Return(rec, nil) - recommender := NewCachingRecommender(10*time.Second, apiMock) - - result, err := recommender.Get(&pod.Spec) - - assert.Equal(t, rec, result) - assert.Equal(t, nil, err) - - // test get from cache - for i := 0; i < 5; i++ { - result, err = recommender.Get(&pod.Spec) - } - apiMock.AssertNumberOfCalls(t, "GetRecommendation", 1) -} - -func TestGetCacheExpired(t *testing.T) { - apiMock := &test.RecommenderAPIMock{} - rec := test.Recommendation("test", "", "") - pod := test.BuildTestPod("test", "", "", "", nil, nil) - apiMock.On("GetRecommendation", &pod.Spec).Return(rec, nil) - recommender := NewCachingRecommender(time.Second, apiMock) - - result, err := recommender.Get(&pod.Spec) - assert.Equal(t, rec, result) - assert.Equal(t, nil, err) - - <-time.After(2 * time.Second) - - result, err = recommender.Get(&pod.Spec) - apiMock.AssertNumberOfCalls(t, "GetRecommendation", 2) - -} - -func TestNoRec(t *testing.T) { - apiMock := &test.RecommenderAPIMock{} - pod := test.BuildTestPod("test", "", "", "", nil, nil) - apiMock.On("GetRecommendation", &pod.Spec).Return(nil, nil) - recommender := NewCachingRecommender(time.Second, apiMock) - - result, err := recommender.Get(&pod.Spec) - assert.Nil(t, result) - assert.Nil(t, err) - - // check nil response not chached - result, err = recommender.Get(&pod.Spec) - apiMock.AssertNumberOfCalls(t, "GetRecommendation", 2) -} - -func TestError(t *testing.T) { - apiMock := &test.RecommenderAPIMock{} - pod := test.BuildTestPod("test", "", "", "", nil, nil) - err := fmt.Errorf("Expected Fail") - apiMock.On("GetRecommendation", &pod.Spec).Return(nil, err) - recommender := NewCachingRecommender(time.Second, apiMock) - - result, err := recommender.Get(&pod.Spec) - assert.Nil(t, result) - assert.Error(t, err) - - // check error response not chached - result, err = recommender.Get(&pod.Spec) - apiMock.AssertNumberOfCalls(t, "GetRecommendation", 2) -} diff --git a/vertical-pod-autoscaler/recommender_mock/ttl_cache.go b/vertical-pod-autoscaler/recommender_mock/ttl_cache.go deleted file mode 100644 index b955f96fa1..0000000000 --- a/vertical-pod-autoscaler/recommender_mock/ttl_cache.go +++ /dev/null @@ -1,97 +0,0 @@ -/* -Copyright 2017 The Kubernetes 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 recommender - -import ( - "sync" - "time" -) - -// TTLCache represents cache with ttl -type TTLCache struct { - ttl time.Duration - mutex sync.RWMutex - items map[string]*cachedValue - stopGC chan struct{} -} - -type cachedValue struct { - value interface{} - expirationTime time.Time -} - -// NewTTLCache reates TTLCache for given TTL -func NewTTLCache(ttl time.Duration) *TTLCache { - return &TTLCache{ - ttl: ttl, - items: make(map[string]*cachedValue), - stopGC: make(chan struct{})} -} - -func (r *cachedValue) isFresh() bool { - return r.expirationTime.After(time.Now()) -} - -// Get Returns value present in cache for given cache key, or nil if key is not found or value TTL has expired. -func (c *TTLCache) Get(cacheKey *string) interface{} { - c.mutex.RLock() - defer c.mutex.RUnlock() - value, found := c.items[*cacheKey] - if found && value.isFresh() { - return value.value - } - return nil -} - -// Set adds given value for given key -func (c *TTLCache) Set(cacheKey *string, value interface{}) { - c.mutex.Lock() - defer c.mutex.Unlock() - c.items[*cacheKey] = &cachedValue{value: value, expirationTime: time.Now().Add(c.ttl)} -} - -func (c *TTLCache) cleanup() { - c.mutex.Lock() - defer c.mutex.Unlock() - for key, item := range c.items { - if !item.isFresh() { - delete(c.items, key) - } - } -} - -// StartCacheGC starts background garbage collector worker which on every time interval removes expired cache entries -// If StartCacheGC was called, in order to properly remove cache object, call StopCacheGC. -// Otherwise TTLCache will never be garbage collected since background worker holds reference to it. -func (c *TTLCache) StartCacheGC(interval time.Duration) { - ticker := time.Tick(interval) - go (func() { - for { - select { - case <-ticker: - c.cleanup() - case <-c.stopGC: - return - } - } - })() -} - -// StopCacheGC stops background cache garbage collector -func (c *TTLCache) StopCacheGC() { - c.stopGC <- struct{}{} -} diff --git a/vertical-pod-autoscaler/recommender_mock/ttl_cache_test.go b/vertical-pod-autoscaler/recommender_mock/ttl_cache_test.go deleted file mode 100644 index 31efbe0f21..0000000000 --- a/vertical-pod-autoscaler/recommender_mock/ttl_cache_test.go +++ /dev/null @@ -1,63 +0,0 @@ -/* -Copyright 2017 The Kubernetes 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 recommender - -import ( - "github.com/stretchr/testify/assert" - "testing" - "time" -) - -func TestGet(t *testing.T) { - cache := NewTTLCache(5 * time.Second) - cacheKey := "hello" - result := cache.Get(&cacheKey) - assert.Nil(t, result, "Result should be nil") - - cache.Set(&cacheKey, "world") - result = cache.Get(&cacheKey) - assert.Equal(t, "world", result) -} - -func TestExpiration(t *testing.T) { - cache := NewTTLCache(5 * time.Second) - key1 := "A" - key2 := "B" - key3 := "C" - - cache.Set(&key1, "1") - cache.Set(&key2, "2") - cache.Set(&key3, "3") - cache.StartCacheGC(time.Second) - - <-time.After(2 * time.Second) - assert.Equal(t, "1", cache.Get(&key1)) - cache.Set(&key1, "1") - - <-time.After(3 * time.Second) - assert.Equal(t, "1", cache.Get(&key1)) - assert.Nil(t, cache.Get(&key2)) - assert.Nil(t, cache.Get(&key3)) - - <-time.After(5 * time.Second) - assert.Nil(t, cache.Get(&key1)) - - cache.StopCacheGC() - cache.Set(&key1, "1") - <-time.After(6 * time.Second) - assert.Nil(t, cache.Get(&key1)) -}