Skip to content

Commit 0c76ff5

Browse files
committed
test: add table-driven tests for PullSecrets with edge case coverage
Signed-off-by: Rohan Kumar <[email protected]>
1 parent 09765a5 commit 0c76ff5

File tree

1 file changed

+167
-0
lines changed

1 file changed

+167
-0
lines changed
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
package workspace
2+
3+
import (
4+
"github.com/devfile/devworkspace-operator/pkg/dwerrors"
5+
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
6+
"github.com/devfile/devworkspace-operator/pkg/provision/sync"
7+
"k8s.io/apimachinery/pkg/runtime"
8+
"sigs.k8s.io/controller-runtime/pkg/client"
9+
"testing"
10+
"time"
11+
12+
"github.com/devfile/devworkspace-operator/pkg/constants"
13+
corev1 "k8s.io/api/core/v1"
14+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
15+
"sigs.k8s.io/controller-runtime/pkg/client/fake"
16+
17+
"github.com/stretchr/testify/assert"
18+
)
19+
20+
func TestPullSecrets_TableDriven(t *testing.T) {
21+
namespace := "test-ns"
22+
serviceAccountName := "test-sa"
23+
24+
tests := []struct {
25+
name string
26+
objects []client.Object
27+
setupInfra func()
28+
expectedError error
29+
expectedSecrets []string // expected PullSecret names
30+
}{
31+
{
32+
name: "ServiceAccount not found",
33+
objects: []client.Object{}, // No SA created
34+
setupInfra: func() {
35+
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
36+
},
37+
expectedError: nil,
38+
expectedSecrets: []string{},
39+
},
40+
{
41+
name: "Secret with incorrect type is skipped",
42+
objects: []client.Object{
43+
&corev1.ServiceAccount{
44+
ObjectMeta: metav1.ObjectMeta{
45+
Name: serviceAccountName,
46+
Namespace: namespace,
47+
},
48+
},
49+
&corev1.Secret{
50+
ObjectMeta: metav1.ObjectMeta{
51+
Name: "bad-secret",
52+
Namespace: namespace,
53+
Labels: map[string]string{
54+
constants.DevWorkspacePullSecretLabel: "true",
55+
},
56+
},
57+
Type: corev1.SecretTypeOpaque, // Not a docker config type
58+
},
59+
},
60+
setupInfra: func() {
61+
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
62+
},
63+
expectedError: nil,
64+
expectedSecrets: []string{},
65+
},
66+
{
67+
name: "RetryError when OpenShift SA is too new with no secrets",
68+
objects: []client.Object{
69+
&corev1.ServiceAccount{
70+
ObjectMeta: metav1.ObjectMeta{
71+
Name: serviceAccountName,
72+
Namespace: namespace,
73+
CreationTimestamp: metav1.NewTime(time.Now()), // Recent
74+
},
75+
},
76+
},
77+
setupInfra: func() {
78+
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
79+
},
80+
expectedError: &dwerrors.RetryError{},
81+
expectedSecrets: nil,
82+
},
83+
{
84+
name: "Non-OpenShift: no retry even if SA is recent with no secrets",
85+
objects: []client.Object{
86+
&corev1.ServiceAccount{
87+
ObjectMeta: metav1.ObjectMeta{
88+
Name: serviceAccountName,
89+
Namespace: namespace,
90+
CreationTimestamp: metav1.NewTime(time.Now()),
91+
},
92+
},
93+
},
94+
setupInfra: func() {
95+
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
96+
},
97+
expectedError: nil,
98+
expectedSecrets: []string{},
99+
},
100+
{
101+
name: "Multiple SA + labeled secrets merged and sorted",
102+
objects: []client.Object{
103+
&corev1.ServiceAccount{
104+
ObjectMeta: metav1.ObjectMeta{
105+
Name: serviceAccountName,
106+
Namespace: namespace,
107+
CreationTimestamp: metav1.NewTime(time.Now().Add(-10 * time.Minute)),
108+
},
109+
ImagePullSecrets: []corev1.LocalObjectReference{
110+
{Name: "z-sa-secret"},
111+
},
112+
},
113+
&corev1.Secret{
114+
ObjectMeta: metav1.ObjectMeta{
115+
Name: "a-labeled-secret",
116+
Namespace: namespace,
117+
Labels: map[string]string{
118+
constants.DevWorkspacePullSecretLabel: "true",
119+
},
120+
},
121+
Type: corev1.SecretTypeDockerConfigJson,
122+
},
123+
},
124+
setupInfra: func() {
125+
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
126+
},
127+
expectedError: nil,
128+
expectedSecrets: []string{"a-labeled-secret", "z-sa-secret"},
129+
},
130+
}
131+
132+
for _, tt := range tests {
133+
t.Run(tt.name, func(t *testing.T) {
134+
// Given
135+
scheme := runtime.NewScheme()
136+
assert.NoError(t, corev1.AddToScheme(scheme))
137+
tt.setupInfra()
138+
139+
fakeClient := fake.NewClientBuilder().
140+
WithScheme(scheme).
141+
WithObjects(tt.objects...).
142+
Build()
143+
144+
clusterAPI := sync.ClusterAPI{
145+
Client: fakeClient,
146+
}
147+
148+
// When
149+
result, err := PullSecrets(clusterAPI, serviceAccountName, namespace)
150+
151+
// Then
152+
if tt.expectedError != nil {
153+
assert.Error(t, err)
154+
assert.IsType(t, tt.expectedError, err)
155+
return
156+
}
157+
158+
assert.NoError(t, err)
159+
assert.NotNil(t, result)
160+
actualNames := []string{}
161+
for _, ps := range result.PullSecrets {
162+
actualNames = append(actualNames, ps.Name)
163+
}
164+
assert.Equal(t, tt.expectedSecrets, actualNames)
165+
})
166+
}
167+
}

0 commit comments

Comments
 (0)