@@ -2,76 +2,283 @@ package e2e
2
2
3
3
import (
4
4
"context"
5
+ "fmt"
6
+ "net"
5
7
"testing"
8
+ "time"
6
9
10
+ certv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
7
11
"github.com/stretchr/testify/assert"
8
- "k8s.io/apimachinery/pkg/api/errors"
12
+ appsv1 "k8s.io/api/apps/v1"
13
+ corev1 "k8s.io/api/core/v1"
14
+ k8serrors "k8s.io/apimachinery/pkg/api/errors"
15
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
16
+ "sigs.k8s.io/e2e-framework/klient"
17
+ "sigs.k8s.io/e2e-framework/klient/k8s"
18
+ "sigs.k8s.io/e2e-framework/klient/k8s/resources"
19
+ "sigs.k8s.io/e2e-framework/klient/wait"
20
+ "sigs.k8s.io/e2e-framework/klient/wait/conditions"
9
21
"sigs.k8s.io/e2e-framework/pkg/envconf"
10
22
"sigs.k8s.io/e2e-framework/pkg/features"
11
23
24
+ apiextensionsV1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
25
+
26
+ ecv1alpha1 "go.etcd.io/etcd-operator/api/v1alpha1"
12
27
"go.etcd.io/etcd-operator/pkg/certificate/cert_manager"
13
28
interfaces "go.etcd.io/etcd-operator/pkg/certificate/interfaces"
14
29
)
15
30
31
+ const cmIssuerName = "selfsigned"
32
+ const etcdClusterName = "etcd-cluster-test"
33
+ const size = 3
34
+
16
35
func TestCertManagerProvider (t * testing.T ) {
17
36
feature := features .New ("Cert-Manager Certificate" ).WithLabel ("app" , "cert-manager" )
18
37
38
+ // TODO: pick these from testdata yamls
39
+ etcdCluster := & ecv1alpha1.EtcdCluster {
40
+ TypeMeta : metav1.TypeMeta {
41
+ APIVersion : "operator.etcd.io/v1alpha1" ,
42
+ Kind : "EtcdCluster" ,
43
+ },
44
+ ObjectMeta : metav1.ObjectMeta {
45
+ Name : etcdClusterName ,
46
+ Namespace : namespace ,
47
+ },
48
+ Spec : ecv1alpha1.EtcdClusterSpec {
49
+ Size : size ,
50
+ Version : "v3.5.18" ,
51
+ TLS : & ecv1alpha1.TLSCertificate {
52
+ Provider : "cert-manager" ,
53
+ ProviderCfg : & ecv1alpha1.ProviderConfig {
54
+ CertManagerCfg : & ecv1alpha1.ProviderCertManagerConfig {
55
+ CommonName : "etcd.etcd-operator-system" ,
56
+ Organization : []string {"etcd-operator" },
57
+ DNSNames : []string {"etcd.etcd-operator-system" },
58
+ IPs : []net.IP {net .ParseIP ("192.168.0.5" )},
59
+ Duration : 2160 ,
60
+ IssuerName : "selfsigned" ,
61
+ IssuerKind : "ClusterIssuer" ,
62
+ },
63
+ },
64
+ },
65
+ },
66
+ }
67
+
68
+ cmIssuer := & certv1.ClusterIssuer {
69
+ TypeMeta : metav1.TypeMeta {
70
+ Kind : "ClusterIssuer" ,
71
+ },
72
+ ObjectMeta : metav1.ObjectMeta {
73
+ Name : "selfsigned" ,
74
+ },
75
+ Spec : certv1.IssuerSpec {
76
+ IssuerConfig : certv1.IssuerConfig {
77
+ SelfSigned : & certv1.SelfSignedIssuer {},
78
+ }},
79
+ }
80
+
19
81
feature .Setup (
20
82
func (ctx context.Context , t * testing.T , cfg * envconf.Config ) context.Context {
21
83
client := cfg .Client ()
22
- cmProvider := cert_manager .New (client .Resources ().GetControllerRuntimeClient ())
23
- _ , getCertConfigErr := cmProvider .GetCertificateConfig (ctx , "test-cert-secret" , cfg .Namespace ())
24
- if errors .IsNotFound (getCertConfigErr ) {
25
- t .Log (getCertConfigErr )
26
- } else {
27
- t .Fatal (getCertConfigErr )
84
+ _ = appsv1 .AddToScheme (client .Resources ().GetScheme ())
85
+ _ = corev1 .AddToScheme (client .Resources ().GetScheme ())
86
+ _ = certv1 .AddToScheme (client .Resources ().GetScheme ())
87
+ _ = apiextensionsV1 .AddToScheme (client .Resources ().GetScheme ())
88
+ _ = ecv1alpha1 .AddToScheme (client .Resources ().GetScheme ())
89
+
90
+ var issuer certv1.ClusterIssuer
91
+ if err := client .Resources ().Get (ctx , cmIssuerName , "" , & issuer ); err != nil {
92
+ if k8serrors .IsNotFound (err ) {
93
+ t .Logf ("No cert-manager selfsigned issuer found, creating clusterIssuer: %s" , cmIssuerName )
94
+ // Create cert-manager issuer
95
+ if err := client .Resources ().Create (ctx , cmIssuer ); err != nil {
96
+ t .Fatalf ("unable to craete cert-manager selfsigned issuer: %s" , err )
97
+ }
98
+ } else {
99
+ t .Fatalf ("Failed to get cert-manager selfsigned issuer: %s" , cmIssuerName )
100
+ }
28
101
}
29
- cmConfig := & interfaces.Config {
30
- AltNames : interfaces.AltNames {
31
- DNSNames : []string {"test.com" },
32
- },
33
- ExtraConfig : map [string ]interface {}{
34
- "issuerName" : "test-issuer" ,
35
- "issuerKind" : "Issuer" ,
36
- },
102
+
103
+ name := "etcdclusters.operator.etcd.io"
104
+ var crd apiextensionsV1.CustomResourceDefinition
105
+ if err := client .Resources ().Get (ctx , name , "" , & crd ); err != nil {
106
+ t .Fatalf ("Failed due to error: %s" , err )
107
+ }
108
+
109
+ if crd .Spec .Group != "operator.etcd.io" {
110
+ t .Fatalf ("Expected crd group to be operator.etcd.io, got %s" , crd .Spec .Group )
37
111
}
38
- err := cmProvider .EnsureCertificateSecret (ctx , "test-cert-secret" , cfg .Namespace (), cmConfig )
39
- if err != nil {
112
+
113
+ // Create the etcd cluster resource
114
+ if err := client .Resources ().Create (ctx , etcdCluster ); err != nil {
115
+ t .Fatalf ("unable to create an etcd cluster resource of size 1: %s" , err )
116
+ }
117
+
118
+ if err := wait .For (
119
+ conditions .New (client .Resources ()).ResourceMatch (etcdCluster , func (object k8s.Object ) bool {
120
+ return true
121
+ }),
122
+ wait .WithTimeout (3 * time .Minute ),
123
+ wait .WithInterval (30 * time .Second ),
124
+ ); err != nil {
40
125
t .Fatal (err )
41
126
}
42
127
return ctx
43
128
})
44
129
45
- feature .Assess ("Validate certificate secret " ,
130
+ feature .Assess ("Check for client certificates " ,
46
131
func (ctx context.Context , t * testing.T , cfg * envconf.Config ) context.Context {
47
132
client := cfg .Client ()
48
- cmProvider := cert_manager .New (client .Resources ().GetControllerRuntimeClient ())
49
- valid , err := cmProvider .ValidateCertificateSecret (ctx , "test-cert-secret" , cfg .Namespace (), & interfaces.Config {})
50
- if err != nil {
51
- t .Fatal (err )
52
- }
53
- assert .True (t , valid )
133
+ validateCertificates (ctx , client , t , "client" )
134
+ return ctx
135
+ })
136
+
137
+ feature .Assess ("Check for server certificates" ,
138
+ func (ctx context.Context , t * testing.T , cfg * envconf.Config ) context.Context {
139
+ client := cfg .Client ()
140
+ validateCertificates (ctx , client , t , "server" )
141
+ return ctx
142
+ })
143
+
144
+ feature .Assess ("Check for peer certificates" ,
145
+ func (ctx context.Context , t * testing.T , cfg * envconf.Config ) context.Context {
146
+ client := cfg .Client ()
147
+ validateCertificates (ctx , client , t , "peer" )
54
148
return ctx
55
149
})
56
150
57
151
feature .Teardown (
58
152
func (ctx context.Context , t * testing.T , cfg * envconf.Config ) context.Context {
59
153
client := cfg .Client ()
60
- cmProvider := cert_manager .New (client .Resources ().GetControllerRuntimeClient ())
61
- deleteSecretErr := cmProvider .DeleteCertificateSecret (ctx , "test-cert-secret" , cfg .Namespace ())
62
- if errors .IsNotFound (deleteSecretErr ) {
63
- t .Log (deleteSecretErr )
154
+ deleteCertificates (ctx , client , t , "client" )
155
+ deleteCertificates (ctx , client , t , "server" )
156
+ deleteCertificates (ctx , client , t , "peer" )
157
+ return ctx
158
+ })
159
+
160
+ _ = testEnv .Test (t , feature .Feature ())
161
+ }
162
+
163
+ func validateCertificates (ctx context.Context , client klient.Client , t * testing.T , certType string ) {
164
+ cmProvider := cert_manager .New (client .Resources ().GetControllerRuntimeClient ())
165
+ podList := corev1.PodList {}
166
+ cmCert := certv1.Certificate {}
167
+ // Check if the certificate type is Client
168
+ if certType == "client" {
169
+ cmCertName := fmt .Sprintf ("%s-%s-tls" , etcdClusterName , certType )
170
+ certErr := client .Resources ().Get (ctx , cmCertName , namespace , & cmCert )
171
+ if certErr != nil {
172
+ if k8serrors .IsNotFound (certErr ) {
173
+ t .Fatalf ("No %s certificate found: %s" , cmCertName , certErr )
64
174
} else {
65
- t .Fatal (deleteSecretErr )
175
+ t .Logf ("Failed to get %s certificate: %s" , certErr , cmCertName )
176
+ t .Fatal (certErr )
177
+ }
178
+ }
179
+ // Check if the secret created is a valid secret
180
+ valid , secretErr := cmProvider .ValidateCertificateSecret (ctx , cmCertName , namespace , & interfaces.Config {})
181
+ if secretErr != nil {
182
+ t .Logf ("Invalid secret: %s" , cmCertName )
183
+ t .Fatal (secretErr )
184
+ } else {
185
+ if ! valid {
186
+ t .Fatalf ("No secret %s found" , cmCertName )
187
+ }
188
+ }
189
+ } else {
190
+ // If the certificate type is Server or Peer, check for each member
191
+ labelSelector := fmt .Sprintf ("app=%s" , etcdClusterName )
192
+ err := client .Resources ().List (ctx , & podList , resources .WithLabelSelector (labelSelector ))
193
+ if err != nil {
194
+ t .Log ("Failed to get StatefulSet pods" )
195
+ t .Fatal (err )
196
+ }
197
+ for _ , pod := range podList .Items {
198
+ cmCertName := fmt .Sprintf ("%s-%s-tls" , pod .Name , certType )
199
+ certErr := client .Resources ().Get (ctx , cmCertName , namespace , & cmCert )
200
+ if certErr != nil {
201
+ if k8serrors .IsNotFound (certErr ) {
202
+ t .Fatalf ("No %s certificate found: %s" , cmCertName , certErr )
203
+ } else {
204
+ t .Logf ("Failed to get %s certificate: %s" , certType , cmCertName )
205
+ t .Fatal (certErr )
206
+ }
66
207
}
67
- deleteCertErr := cmProvider .RevokeCertificate (ctx , "test-cert-secret" , cfg .Namespace ())
68
- if errors .IsNotFound (deleteCertErr ) {
69
- t .Log (deleteCertErr )
208
+ valid , secretErr := cmProvider .ValidateCertificateSecret (ctx , cmCertName , namespace , & interfaces.Config {})
209
+ if secretErr != nil {
210
+ t .Logf ("Invalid secret: %s" , cmCertName )
211
+ t .Fatal (secretErr )
70
212
} else {
71
- t .Fatal (deleteCertErr )
213
+ if ! valid {
214
+ t .Fatalf ("No secret %s found" , cmCertName )
215
+ }
72
216
}
73
- return ctx
74
- })
217
+ assert .True (t , valid )
218
+ }
219
+ }
220
+ }
75
221
76
- _ = testEnv .Test (t , feature .Feature ())
222
+ func deleteCertificates (ctx context.Context , client klient.Client , t * testing.T , certType string ) {
223
+ cmProvider := cert_manager .New (client .Resources ().GetControllerRuntimeClient ())
224
+ podList := corev1.PodList {}
225
+ cmCert := certv1.Certificate {}
226
+ cmSecret := corev1.Secret {}
227
+ // Check if the certificate type is Client
228
+ if certType == "client" {
229
+ cmCertName := fmt .Sprintf ("%s-%s-tls" , etcdClusterName , certType )
230
+ deleteErr := cmProvider .RevokeCertificate (ctx , cmCertName , namespace )
231
+ if deleteErr != nil {
232
+ t .Fatalf ("Failed to remvoke certificate: %s" , deleteErr )
233
+ }
234
+ // Check if certificate has been deleted successfully
235
+ certErr := client .Resources ().Get (ctx , cmCertName , namespace , & cmCert )
236
+ if certErr != nil {
237
+ if k8serrors .IsNotFound (certErr ) {
238
+ t .Logf ("No %s certificate to delete: %s" , cmCertName , certErr )
239
+ } else {
240
+ t .Logf ("Failed to get %s certificate for deletion: %s" , certErr , cmCertName )
241
+ }
242
+ }
243
+ // Check if secret has been deleted successfully
244
+ secretErr := client .Resources ().Get (ctx , cmCertName , namespace , & cmSecret )
245
+ if secretErr != nil {
246
+ if k8serrors .IsNotFound (secretErr ) {
247
+ t .Logf ("No %s secret to delete: %s" , cmCertName , secretErr )
248
+ } else {
249
+ t .Logf ("Failed to get %s secret for deletion: %s" , secretErr , cmCertName )
250
+ }
251
+ }
252
+ } else {
253
+ // If the certificate type is Server or Peer, check for each member
254
+ labelSelector := fmt .Sprintf ("app=%s" , etcdClusterName )
255
+ err := client .Resources ().List (ctx , & podList , resources .WithLabelSelector (labelSelector ))
256
+ if err != nil {
257
+ t .Log ("Failed to get StatefulSet pods" )
258
+ }
259
+ for _ , pod := range podList .Items {
260
+ cmCertName := fmt .Sprintf ("%s-%s-tls" , pod .Name , certType )
261
+ deleteErr := cmProvider .RevokeCertificate (ctx , cmCertName , namespace )
262
+ if deleteErr != nil {
263
+ t .Fatalf ("Failed to remvoke certificate: %s" , deleteErr )
264
+ }
265
+ // Check if certificate has been deleted successfully
266
+ certErr := client .Resources ().Get (ctx , cmCertName , namespace , & cmCert )
267
+ if certErr != nil {
268
+ if k8serrors .IsNotFound (certErr ) {
269
+ t .Logf ("No %s certificate to delete: %s" , cmCertName , certErr )
270
+ }
271
+ t .Logf ("Failed to get %s certificate for deletion: %s" , certType , cmCertName )
272
+ }
273
+ // Check if secret has been deleted successfully
274
+ secretErr := client .Resources ().Get (ctx , cmCertName , namespace , & cmSecret )
275
+ if secretErr != nil {
276
+ if k8serrors .IsNotFound (secretErr ) {
277
+ t .Logf ("No %s secret to delete: %s" , cmCertName , secretErr )
278
+ } else {
279
+ t .Logf ("Failed to get %s secret for deletion: %s" , secretErr , cmCertName )
280
+ }
281
+ }
282
+ }
283
+ }
77
284
}
0 commit comments