Skip to content

Commit 1092164

Browse files
committed
Added serviceAccountName tests
1 parent b26d8c7 commit 1092164

File tree

2 files changed

+305
-1
lines changed

2 files changed

+305
-1
lines changed

manifests/templates/test/rbac.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ rules:
1010
resources: ["nodes"]
1111
verbs: ["list"]
1212
- apiGroups: [""]
13-
resources: ["pods", "services", "persistentvolumes", "persistentvolumeclaims", "secrets"]
13+
resources: ["pods", "services", "persistentvolumes", "persistentvolumeclaims", "secrets", "serviceaccounts"]
1414
verbs: ["*"]
1515
- apiGroups: ["apps"]
1616
resources: ["daemonsets"]

tests/service_account_test.go

+304
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
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 Ewout Prangsma
21+
//
22+
23+
package tests
24+
25+
import (
26+
"context"
27+
"strings"
28+
"testing"
29+
30+
"github.com/dchest/uniuri"
31+
"github.com/stretchr/testify/assert"
32+
"k8s.io/api/core/v1"
33+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
34+
"k8s.io/client-go/kubernetes"
35+
36+
driver "github.com/arangodb/go-driver"
37+
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha"
38+
"github.com/arangodb/kube-arangodb/pkg/client"
39+
"github.com/arangodb/kube-arangodb/pkg/util"
40+
)
41+
42+
// TestServiceAccountSingle tests the creating of a single server deployment
43+
// with default settings using a custom service account.
44+
func TestServiceAccountSingle(t *testing.T) {
45+
longOrSkip(t)
46+
c := client.MustNewInCluster()
47+
kubecli := mustNewKubeClient(t)
48+
ns := getNamespace(t)
49+
50+
// Prepare service account
51+
namePrefix := "test-sa-sng-"
52+
saName := mustCreateServiceAccount(kubecli, namePrefix, ns, t)
53+
defer deleteServiceAccount(kubecli, saName, ns)
54+
55+
// Prepare deployment config
56+
depl := newDeployment(namePrefix + uniuri.NewLen(4))
57+
depl.Spec.Mode = api.NewMode(api.DeploymentModeSingle)
58+
depl.Spec.Single.ServiceAccountName = util.NewString(saName)
59+
60+
// Create deployment
61+
_, err := c.DatabaseV1alpha().ArangoDeployments(ns).Create(depl)
62+
if err != nil {
63+
t.Fatalf("Create deployment failed: %v", err)
64+
}
65+
// Prepare cleanup
66+
defer removeDeployment(c, depl.GetName(), ns)
67+
68+
// Wait for deployment to be ready
69+
apiObject, err := waitUntilDeployment(c, depl.GetName(), ns, deploymentIsReady())
70+
if err != nil {
71+
t.Fatalf("Deployment not running in time: %v", err)
72+
}
73+
74+
// Create a database client
75+
ctx := context.Background()
76+
client := mustNewArangodDatabaseClient(ctx, kubecli, apiObject, t)
77+
78+
// Wait for single server available
79+
if err := waitUntilVersionUp(client, nil); err != nil {
80+
t.Fatalf("Single server not running returning version in time: %v", err)
81+
}
82+
83+
// Check service account name
84+
checkMembersUsingServiceAccount(kubecli, ns, apiObject.Status.Members.Single, saName, t)
85+
86+
// Check server role
87+
assert.NoError(t, client.SynchronizeEndpoints(ctx))
88+
role, err := client.ServerRole(ctx)
89+
assert.NoError(t, err)
90+
assert.Equal(t, driver.ServerRoleSingle, role)
91+
}
92+
93+
// TestServiceAccountActiveFailover tests the creating of a ActiveFailover server deployment
94+
// with default settings using a custom service account.
95+
func TestServiceAccountActiveFailover(t *testing.T) {
96+
longOrSkip(t)
97+
c := client.MustNewInCluster()
98+
kubecli := mustNewKubeClient(t)
99+
ns := getNamespace(t)
100+
101+
// Prepare service account
102+
namePrefix := "test-sa-rs-"
103+
saName := mustCreateServiceAccount(kubecli, namePrefix, ns, t)
104+
defer deleteServiceAccount(kubecli, saName, ns)
105+
106+
// Prepare deployment config
107+
depl := newDeployment(namePrefix + uniuri.NewLen(4))
108+
depl.Spec.Mode = api.NewMode(api.DeploymentModeActiveFailover)
109+
depl.Spec.Single.ServiceAccountName = util.NewString(saName)
110+
depl.Spec.Agents.ServiceAccountName = util.NewString(saName)
111+
112+
// Create deployment
113+
_, err := c.DatabaseV1alpha().ArangoDeployments(ns).Create(depl)
114+
if err != nil {
115+
t.Fatalf("Create deployment failed: %v", err)
116+
}
117+
// Prepare cleanup
118+
defer removeDeployment(c, depl.GetName(), ns)
119+
120+
// Wait for deployment to be ready
121+
apiObject, err := waitUntilDeployment(c, depl.GetName(), ns, deploymentIsReady())
122+
if err != nil {
123+
t.Fatalf("Deployment not running in time: %v", err)
124+
}
125+
126+
// Create a database client
127+
ctx := context.Background()
128+
client := mustNewArangodDatabaseClient(ctx, kubecli, apiObject, t)
129+
130+
// Wait for single server available
131+
if err := waitUntilVersionUp(client, nil); err != nil {
132+
t.Fatalf("ActiveFailover servers not running returning version in time: %v", err)
133+
}
134+
135+
// Check service account name
136+
checkMembersUsingServiceAccount(kubecli, ns, apiObject.Status.Members.Single, saName, t)
137+
checkMembersUsingServiceAccount(kubecli, ns, apiObject.Status.Members.Agents, saName, t)
138+
139+
// Check server role
140+
assert.NoError(t, client.SynchronizeEndpoints(ctx))
141+
role, err := client.ServerRole(ctx)
142+
assert.NoError(t, err)
143+
assert.Equal(t, driver.ServerRoleSingleActive, role)
144+
}
145+
146+
// TestServiceAccountCluster tests the creating of a cluster deployment
147+
// with default settings using a custom service account.
148+
func TestServiceAccountCluster(t *testing.T) {
149+
longOrSkip(t)
150+
c := client.MustNewInCluster()
151+
kubecli := mustNewKubeClient(t)
152+
ns := getNamespace(t)
153+
154+
// Prepare service account
155+
namePrefix := "test-sa-cls-"
156+
saName := mustCreateServiceAccount(kubecli, namePrefix, ns, t)
157+
defer deleteServiceAccount(kubecli, saName, ns)
158+
159+
// Prepare deployment config
160+
depl := newDeployment(namePrefix + uniuri.NewLen(4))
161+
depl.Spec.Mode = api.NewMode(api.DeploymentModeCluster)
162+
depl.Spec.Agents.ServiceAccountName = util.NewString(saName)
163+
depl.Spec.DBServers.ServiceAccountName = util.NewString(saName)
164+
depl.Spec.Coordinators.ServiceAccountName = util.NewString(saName)
165+
166+
// Create deployment
167+
_, err := c.DatabaseV1alpha().ArangoDeployments(ns).Create(depl)
168+
if err != nil {
169+
t.Fatalf("Create deployment failed: %v", err)
170+
}
171+
// Prepare cleanup
172+
defer removeDeployment(c, depl.GetName(), ns)
173+
174+
// Wait for deployment to be ready
175+
apiObject, err := waitUntilDeployment(c, depl.GetName(), ns, deploymentIsReady())
176+
if err != nil {
177+
t.Fatalf("Deployment not running in time: %v", err)
178+
}
179+
180+
// Create a database client
181+
ctx := context.Background()
182+
client := mustNewArangodDatabaseClient(ctx, kubecli, apiObject, t)
183+
184+
// Wait for cluster to be available
185+
if err := waitUntilVersionUp(client, nil); err != nil {
186+
t.Fatalf("Cluster not running returning version in time: %v", err)
187+
}
188+
189+
// Check service account name
190+
checkMembersUsingServiceAccount(kubecli, ns, apiObject.Status.Members.Agents, saName, t)
191+
checkMembersUsingServiceAccount(kubecli, ns, apiObject.Status.Members.Coordinators, saName, t)
192+
checkMembersUsingServiceAccount(kubecli, ns, apiObject.Status.Members.DBServers, saName, t)
193+
194+
// Check server role
195+
assert.NoError(t, client.SynchronizeEndpoints(ctx))
196+
role, err := client.ServerRole(ctx)
197+
assert.NoError(t, err)
198+
assert.Equal(t, driver.ServerRoleCoordinator, role)
199+
}
200+
201+
// TestServiceAccountClusterWithSync tests the creating of a cluster deployment
202+
// with default settings and sync enabled using a custom service account.
203+
func TestServiceAccountClusterWithSync(t *testing.T) {
204+
longOrSkip(t)
205+
img := getEnterpriseImageOrSkip(t)
206+
c := client.MustNewInCluster()
207+
kubecli := mustNewKubeClient(t)
208+
ns := getNamespace(t)
209+
210+
// Prepare service account
211+
namePrefix := "test-sa-cls-sync-"
212+
saName := mustCreateServiceAccount(kubecli, namePrefix, ns, t)
213+
defer deleteServiceAccount(kubecli, saName, ns)
214+
215+
// Prepare deployment config
216+
depl := newDeployment(namePrefix + uniuri.NewLen(4))
217+
depl.Spec.Mode = api.NewMode(api.DeploymentModeCluster)
218+
depl.Spec.Image = util.NewString(img)
219+
depl.Spec.Sync.Enabled = util.NewBool(true)
220+
depl.Spec.Agents.ServiceAccountName = util.NewString(saName)
221+
depl.Spec.DBServers.ServiceAccountName = util.NewString(saName)
222+
depl.Spec.Coordinators.ServiceAccountName = util.NewString(saName)
223+
depl.Spec.SyncMasters.ServiceAccountName = util.NewString(saName)
224+
depl.Spec.SyncWorkers.ServiceAccountName = util.NewString(saName)
225+
226+
// Create deployment
227+
_, err := c.DatabaseV1alpha().ArangoDeployments(ns).Create(depl)
228+
if err != nil {
229+
t.Fatalf("Create deployment failed: %v", err)
230+
}
231+
// Prepare cleanup
232+
defer removeDeployment(c, depl.GetName(), ns)
233+
234+
// Wait for deployment to be ready
235+
apiObject, err := waitUntilDeployment(c, depl.GetName(), ns, deploymentIsReady())
236+
if err != nil {
237+
t.Fatalf("Deployment not running in time: %v", err)
238+
}
239+
240+
// Create a database client
241+
ctx := context.Background()
242+
client := mustNewArangodDatabaseClient(ctx, kubecli, apiObject, t)
243+
244+
// Wait for cluster to be available
245+
if err := waitUntilVersionUp(client, nil); err != nil {
246+
t.Fatalf("Cluster not running returning version in time: %v", err)
247+
}
248+
249+
// Create a syncmaster client
250+
syncClient := mustNewArangoSyncClient(ctx, kubecli, apiObject, t)
251+
252+
// Wait for syncmasters to be available
253+
if err := waitUntilSyncVersionUp(syncClient, nil); err != nil {
254+
t.Fatalf("SyncMasters not running returning version in time: %v", err)
255+
}
256+
257+
// Check service account name
258+
checkMembersUsingServiceAccount(kubecli, ns, apiObject.Status.Members.Agents, saName, t)
259+
checkMembersUsingServiceAccount(kubecli, ns, apiObject.Status.Members.Coordinators, saName, t)
260+
checkMembersUsingServiceAccount(kubecli, ns, apiObject.Status.Members.DBServers, saName, t)
261+
checkMembersUsingServiceAccount(kubecli, ns, apiObject.Status.Members.SyncMasters, saName, t)
262+
checkMembersUsingServiceAccount(kubecli, ns, apiObject.Status.Members.SyncWorkers, saName, t)
263+
264+
// Check server role
265+
assert.NoError(t, client.SynchronizeEndpoints(ctx))
266+
role, err := client.ServerRole(ctx)
267+
assert.NoError(t, err)
268+
assert.Equal(t, driver.ServerRoleCoordinator, role)
269+
}
270+
271+
// mustCreateServiceAccount creates an empty service account with random name and returns
272+
// its name. On error, the test is failed.
273+
func mustCreateServiceAccount(kubecli kubernetes.Interface, namePrefix, ns string, t *testing.T) string {
274+
s := v1.ServiceAccount{
275+
ObjectMeta: metav1.ObjectMeta{
276+
Name: strings.ToLower(namePrefix + uniuri.NewLen(4)),
277+
},
278+
}
279+
if _, err := kubecli.CoreV1().ServiceAccounts(ns).Create(&s); err != nil {
280+
t.Fatalf("Failed to create service account: %v", err)
281+
}
282+
return s.GetName()
283+
}
284+
285+
// deleteServiceAccount deletes a service account with given name in given namespace.
286+
func deleteServiceAccount(kubecli kubernetes.Interface, name, ns string) error {
287+
if err := kubecli.CoreV1().ServiceAccounts(ns).Delete(name, &metav1.DeleteOptions{}); err != nil {
288+
return maskAny(err)
289+
}
290+
return nil
291+
}
292+
293+
// checkMembersUsingServiceAccount checks the serviceAccountName of the pods of all members
294+
// to ensure that is equal to the given serviceAccountName.
295+
func checkMembersUsingServiceAccount(kubecli kubernetes.Interface, ns string, members []api.MemberStatus, serviceAccountName string, t *testing.T) {
296+
pods := kubecli.CoreV1().Pods(ns)
297+
for _, m := range members {
298+
if p, err := pods.Get(m.PodName, metav1.GetOptions{}); err != nil {
299+
t.Errorf("Failed to get pod for member '%s': %v", m.ID, err)
300+
} else if p.Spec.ServiceAccountName != serviceAccountName {
301+
t.Errorf("Expected pod '%s' to have serviceAccountName '%s', got '%s'", p.GetName(), serviceAccountName, p.Spec.ServiceAccountName)
302+
}
303+
}
304+
}

0 commit comments

Comments
 (0)