Skip to content

Commit 30e3ece

Browse files
author
Lars Maier
authored
Merge pull request #428 from arangodb/bug-fix/limit-requests-resources
Added test for resource rotation.
2 parents dd794d7 + 634d034 commit 30e3ece

File tree

3 files changed

+184
-0
lines changed

3 files changed

+184
-0
lines changed

pkg/apis/deployment/v1alpha/deployment_spec.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,25 @@ func (s DeploymentSpec) GetServerGroupSpec(group ServerGroup) ServerGroupSpec {
162162
}
163163
}
164164

165+
// UpdateServerGroupSpec returns the server group spec (from this
166+
// deployment spec) for the given group.
167+
func (s *DeploymentSpec) UpdateServerGroupSpec(group ServerGroup, gspec ServerGroupSpec) {
168+
switch group {
169+
case ServerGroupSingle:
170+
s.Single = gspec
171+
case ServerGroupAgents:
172+
s.Agents = gspec
173+
case ServerGroupDBServers:
174+
s.DBServers = gspec
175+
case ServerGroupCoordinators:
176+
s.Coordinators = gspec
177+
case ServerGroupSyncMasters:
178+
s.SyncMasters = gspec
179+
case ServerGroupSyncWorkers:
180+
s.SyncWorkers = gspec
181+
}
182+
}
183+
165184
// SetDefaults fills in default values when a field is not specified.
166185
func (s *DeploymentSpec) SetDefaults(deploymentName string) {
167186
if s.GetMode() == "" {

tests/predicates.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ package tests
2525
import (
2626
"fmt"
2727

28+
v1 "k8s.io/api/core/v1"
2829
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha"
30+
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
31+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
32+
"k8s.io/client-go/kubernetes"
2933
)
3034

3135
// deploymentIsReady creates a predicate that returns nil when the deployment is in
@@ -41,3 +45,44 @@ func deploymentIsReady() func(*api.ArangoDeployment) error {
4145
return fmt.Errorf("Expected Ready condition to be set, it is not")
4246
}
4347
}
48+
49+
func resourcesRequireRotation(wanted, given v1.ResourceRequirements) bool {
50+
checkList := func(wanted, given v1.ResourceList) bool {
51+
for k, v := range wanted {
52+
if gv, ok := given[k]; !ok {
53+
return true
54+
} else if v.Cmp(gv) != 0 {
55+
return true
56+
}
57+
}
58+
59+
return false
60+
}
61+
62+
return checkList(wanted.Limits, given.Limits) || checkList(wanted.Requests, given.Requests)
63+
}
64+
65+
func resourcesAsRequested(kubecli kubernetes.Interface, ns string) func(obj *api.ArangoDeployment) error {
66+
return func(obj *api.ArangoDeployment) error {
67+
return obj.ForeachServerGroup(func(group api.ServerGroup, spec api.ServerGroupSpec, status *api.MemberStatusList) error {
68+
69+
for _, m := range *status {
70+
pod, err := kubecli.CoreV1().Pods(ns).Get(m.PodName, metav1.GetOptions{})
71+
if err != nil {
72+
return err
73+
}
74+
75+
c, found := k8sutil.GetContainerByName(pod, k8sutil.ServerContainerName)
76+
if !found {
77+
return fmt.Errorf("Container not found: %s", m.PodName)
78+
}
79+
80+
if resourcesRequireRotation(spec.Resources, c.Resources) {
81+
return fmt.Errorf("Container of Pod %s need rotation", m.PodName)
82+
}
83+
}
84+
85+
return nil
86+
}, nil)
87+
}
88+
}

tests/resources_test.go

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2018 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
// Author Lars Maier
21+
//
22+
23+
package tests
24+
25+
import (
26+
"fmt"
27+
"testing"
28+
29+
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha"
30+
"github.com/arangodb/kube-arangodb/pkg/client"
31+
kubeArangoClient "github.com/arangodb/kube-arangodb/pkg/client"
32+
"github.com/arangodb/kube-arangodb/pkg/util"
33+
"github.com/dchest/uniuri"
34+
"github.com/stretchr/testify/assert"
35+
v1 "k8s.io/api/core/v1"
36+
"k8s.io/apimachinery/pkg/api/resource"
37+
)
38+
39+
func TestResourcesChangeLimitsCluster(t *testing.T) {
40+
longOrSkip(t)
41+
c := client.MustNewInCluster()
42+
kubecli := mustNewKubeClient(t)
43+
deploymentClient := kubeArangoClient.MustNewInCluster()
44+
ns := getNamespace(t)
45+
46+
size500m, _ := resource.ParseQuantity("50m")
47+
size1, _ := resource.ParseQuantity("1")
48+
size100Gi, _ := resource.ParseQuantity("100Gi")
49+
size1Gi, _ := resource.ParseQuantity("1Gi")
50+
size2Gi, _ := resource.ParseQuantity("2Gi")
51+
52+
// Prepare deployment config
53+
depl := newDeployment("test-chng-limits-" + uniuri.NewLen(4))
54+
depl.Spec.Mode = api.NewMode(api.DeploymentModeCluster)
55+
depl.Spec.DBServers.Count = util.NewInt(2)
56+
depl.Spec.Coordinators.Count = util.NewInt(2)
57+
depl.Spec.SetDefaults(depl.GetName()) // this must be last
58+
defer deferedCleanupDeployment(c, depl.GetName(), ns)
59+
60+
// Create deployment
61+
_, err := deploymentClient.DatabaseV1alpha().ArangoDeployments(ns).Create(depl)
62+
defer removeDeployment(deploymentClient, depl.GetName(), ns)
63+
assert.NoError(t, err, "failed to create deplyment: %s", err)
64+
65+
testGroups := []api.ServerGroup{api.ServerGroupCoordinators, api.ServerGroupAgents, api.ServerGroupDBServers}
66+
67+
testCases := []v1.ResourceRequirements{
68+
{
69+
Limits: v1.ResourceList{
70+
v1.ResourceCPU: size1,
71+
},
72+
},
73+
{
74+
Requests: v1.ResourceList{
75+
v1.ResourceCPU: size500m,
76+
},
77+
},
78+
{
79+
Requests: v1.ResourceList{
80+
v1.ResourceCPU: size500m,
81+
v1.ResourceMemory: size1Gi,
82+
},
83+
},
84+
{
85+
Requests: v1.ResourceList{
86+
v1.ResourceCPU: size500m,
87+
v1.ResourceMemory: size2Gi,
88+
},
89+
},
90+
{
91+
Limits: v1.ResourceList{
92+
v1.ResourceCPU: size1,
93+
v1.ResourceMemory: size100Gi,
94+
},
95+
},
96+
}
97+
98+
for _, testgroup := range testGroups {
99+
t.Run(testgroup.AsRole(), func(t *testing.T) {
100+
101+
_, err = waitUntilDeployment(deploymentClient, depl.GetName(), ns, deploymentIsReady())
102+
assert.NoError(t, err, fmt.Sprintf("Deployment not running in time: %s", err))
103+
104+
for i, testCase := range testCases {
105+
t.Run(fmt.Sprintf("case-%d", i+1), func(t *testing.T) {
106+
depl, err = updateDeployment(c, depl.GetName(), ns, func(spec *api.DeploymentSpec) {
107+
gspec := spec.GetServerGroupSpec(testgroup)
108+
gspec.Resources = testCase
109+
spec.UpdateServerGroupSpec(testgroup, gspec)
110+
})
111+
assert.NoError(t, err, fmt.Sprintf("Failed to update deployment: %s", err))
112+
113+
_, err = waitUntilDeployment(deploymentClient, depl.GetName(), ns, resourcesAsRequested(kubecli, ns))
114+
assert.NoError(t, err, fmt.Sprintf("Deployment not rotated in time: %s", err))
115+
})
116+
}
117+
})
118+
}
119+
120+
}

0 commit comments

Comments
 (0)