@@ -2,19 +2,283 @@ package manager
22
33import (
44 "context"
5+ "fmt"
56 "testing"
7+ "time"
68
79 cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
10+ cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
811 testpkg "github.com/cert-manager/cert-manager/pkg/controller/test"
912 "github.com/go-logr/logr/testr"
1013 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1114 "k8s.io/apimachinery/pkg/runtime"
15+ "k8s.io/apimachinery/pkg/util/wait"
1216 coretesting "k8s.io/client-go/testing"
1317
1418 internalapi "github.com/cert-manager/csi-lib/internal/api"
1519 internalapiutil "github.com/cert-manager/csi-lib/internal/api/util"
20+ "github.com/cert-manager/csi-lib/metadata"
21+ "github.com/cert-manager/csi-lib/storage"
22+ testutil "github.com/cert-manager/csi-lib/test/util"
1623)
1724
25+ func TestManager_ManageVolumeImmediate_issueOnceAndSucceed (t * testing.T ) {
26+ ctx := context .Background ()
27+
28+ opts := newDefaultTestOptions (t )
29+ m , err := NewManager (opts )
30+ if err != nil {
31+ t .Fatal (err )
32+ }
33+
34+ // Setup a goroutine to issue one CertificateRequest
35+ stopCh := make (chan struct {})
36+ go testutil .IssueOneRequest (t , opts .Client , defaultTestNamespace , stopCh , selfSignedExampleCertificate , []byte ("ca bytes" ))
37+ defer close (stopCh )
38+
39+ // Register a new volume with the metadata store
40+ store := opts .MetadataReader .(storage.Interface )
41+ meta := metadata.Metadata {
42+ VolumeID : "vol-id" ,
43+ TargetPath : "/fake/path" ,
44+ }
45+ store .RegisterMetadata (meta )
46+ // Ensure we stop managing the volume after the test
47+ defer func () {
48+ store .RemoveVolume (meta .VolumeID )
49+ m .UnmanageVolume (meta .VolumeID )
50+ }()
51+
52+ // Attempt to issue the certificate & put it under management
53+ managed , err := m .ManageVolumeImmediate (ctx , meta .VolumeID )
54+ if ! managed {
55+ t .Errorf ("expected management to have started, but it did not" )
56+ }
57+ if err != nil {
58+ t .Errorf ("expected no error from ManageVolumeImmediate but got: %v" , err )
59+ }
60+
61+ // Assert the certificate is under management
62+ if ! m .IsVolumeReady (meta .VolumeID ) {
63+ t .Errorf ("expected volume to be marked as Ready but it is not" )
64+ }
65+ }
66+
67+ func TestManager_PropagatesRequestConditionMessages (t * testing.T ) {
68+ tests := []struct {
69+ approved string
70+ ready string
71+ expectedError string
72+ }{
73+ {
74+ approved : "" ,
75+ ready : "" ,
76+ expectedError : "waiting for request: request \" certificaterequest-name\" has not yet been approved by approval plugin" ,
77+ },
78+ {
79+ approved : "" ,
80+ ready : "pending" ,
81+ expectedError : "waiting for request: request \" certificaterequest-name\" has not yet been approved by approval plugin" ,
82+ },
83+ {
84+ approved : "" ,
85+ ready : "failed" ,
86+ expectedError : "waiting for request: request \" certificaterequest-name\" has failed: failed" ,
87+ },
88+ //"pending approval, ready == true": {}
89+ {
90+ approved : "denied" ,
91+ ready : "" ,
92+ expectedError : "waiting for request: request \" certificaterequest-name\" has been denied by the approval plugin: denied" ,
93+ },
94+ {
95+ approved : "denied" ,
96+ ready : "pending" ,
97+ expectedError : "waiting for request: request \" certificaterequest-name\" has been denied by the approval plugin: denied" ,
98+ },
99+ {
100+ approved : "denied" ,
101+ ready : "failed" ,
102+ expectedError : "waiting for request: request \" certificaterequest-name\" has been denied by the approval plugin: denied" ,
103+ },
104+ //"denied, ready == true": {},
105+ {
106+ approved : "approved" ,
107+ ready : "" ,
108+ expectedError : "waiting for request: request \" certificaterequest-name\" has no ready condition" ,
109+ },
110+ {
111+ approved : "approved" ,
112+ ready : "pending" ,
113+ expectedError : "waiting for request: request \" certificaterequest-name\" is pending: pending" ,
114+ },
115+ {
116+ approved : "approved" ,
117+ ready : "failed" ,
118+ expectedError : "waiting for request: request \" certificaterequest-name\" has failed: failed" ,
119+ },
120+ //"approved, ready == true": {},
121+ }
122+ for _ , test := range tests {
123+ t .Run (fmt .Sprintf ("approval=%q, readiness=%q" , test .approved , test .ready ), func (t * testing.T ) {
124+ ctx , cancel := context .WithTimeout (context .Background (), time .Second * 3 )
125+ defer cancel ()
126+
127+ opts := newDefaultTestOptions (t )
128+ m , err := NewManager (opts )
129+ if err != nil {
130+ t .Fatal (err )
131+ }
132+ defer m .Stop ()
133+ m .requestNameGenerator = func () string { return "certificaterequest-name" }
134+
135+ // build conditions to set based on test configuration
136+ var conditions []cmapi.CertificateRequestCondition
137+ switch test .approved {
138+ case "" :
139+ case "approved" :
140+ conditions = append (conditions , cmapi.CertificateRequestCondition {Type : cmapi .CertificateRequestConditionApproved , Status : cmmeta .ConditionTrue , Reason : "SetByTest" , Message : "approved" })
141+ case "denied" :
142+ conditions = append (conditions , cmapi.CertificateRequestCondition {Type : cmapi .CertificateRequestConditionDenied , Status : cmmeta .ConditionTrue , Reason : "SetByTest" , Message : "denied" })
143+ }
144+ switch test .ready {
145+ case "" :
146+ case "pending" :
147+ conditions = append (conditions , cmapi.CertificateRequestCondition {Type : cmapi .CertificateRequestConditionReady , Status : cmmeta .ConditionFalse , Reason : cmapi .CertificateRequestReasonPending , Message : "pending" })
148+ case "failed" :
149+ conditions = append (conditions , cmapi.CertificateRequestCondition {Type : cmapi .CertificateRequestConditionReady , Status : cmmeta .ConditionFalse , Reason : cmapi .CertificateRequestReasonFailed , Message : "failed" })
150+ }
151+ // Automatically set the request to be approved & pending once created
152+ go testutil .SetCertificateRequestConditions (ctx , t , opts .Client , defaultTestNamespace , conditions ... )
153+
154+ // Register a new volume with the metadata store
155+ store := opts .MetadataReader .(storage.Interface )
156+ meta := metadata.Metadata {
157+ VolumeID : "vol-id" ,
158+ TargetPath : "/fake/path" ,
159+ }
160+ store .RegisterMetadata (meta )
161+ // Ensure we stop managing the volume after the test
162+ defer func () {
163+ store .RemoveVolume (meta .VolumeID )
164+ m .UnmanageVolume (meta .VolumeID )
165+ }()
166+
167+ // Attempt to issue the certificate & put it under management
168+ managed , err := m .ManageVolumeImmediate (ctx , meta .VolumeID )
169+ if ! managed {
170+ t .Errorf ("expected volume to still be managed after failure" )
171+ }
172+ if err == nil {
173+ t .Errorf ("expected to get an error from ManageVolumeImmediate" )
174+ }
175+ if err .Error () != test .expectedError {
176+ t .Errorf ("expected '%s' but got: %s" , test .expectedError , err .Error ())
177+ }
178+ })
179+ }
180+ }
181+
182+ func TestManager_ResumesManagementOfExistingVolumes (t * testing.T ) {
183+ ctx , cancel := context .WithTimeout (context .Background (), time .Second * 3 )
184+ defer cancel ()
185+
186+ store := storage .NewMemoryFS ()
187+ opts := defaultTestOptions (t , Options {MetadataReader : store })
188+
189+ m , err := NewManager (opts )
190+ if err != nil {
191+ t .Fatal (err )
192+ }
193+
194+ m .requestNameGenerator = func () string { return "certificaterequest-name" }
195+ // Automatically issue the request once created
196+ go testutil .IssueOneRequest (t , opts .Client , defaultTestNamespace , ctx .Done (), selfSignedExampleCertificate , []byte ("ca bytes" ))
197+
198+ // Register a new volume with the metadata store
199+ meta := metadata.Metadata {
200+ VolumeID : "vol-id" ,
201+ TargetPath : "/fake/path" ,
202+ }
203+ _ , err = store .RegisterMetadata (meta )
204+ if err != nil {
205+ t .Fatal (err )
206+ }
207+
208+ // Attempt to issue the certificate & put it under management
209+ managed , err := m .ManageVolumeImmediate (ctx , meta .VolumeID )
210+ if ! managed {
211+ t .Fatalf ("expected volume to be managed" )
212+ }
213+ if err != nil {
214+ t .Fatalf ("unexpected error: %v" , err )
215+ }
216+
217+ // Shutdown the manager
218+ m .Stop ()
219+
220+ m , err = NewManager (opts )
221+ if err != nil {
222+ t .Fatal (err )
223+ }
224+ defer m .Stop ()
225+
226+ if ! m .IsVolumeReady (meta .VolumeID ) {
227+ t .Errorf ("expected volume to be monitored & ready but it is not" )
228+ }
229+ }
230+
231+ func TestManager_ManageVolume_beginsManagingAndProceedsIfNotReady (t * testing.T ) {
232+ ctx , cancel := context .WithCancel (context .Background ())
233+ defer cancel ()
234+
235+ opts := newDefaultTestOptions (t )
236+ m , err := NewManager (opts )
237+ if err != nil {
238+ t .Fatal (err )
239+ }
240+
241+ // Register a new volume with the metadata store
242+ store := opts .MetadataReader .(storage.Interface )
243+ meta := metadata.Metadata {
244+ VolumeID : "vol-id" ,
245+ TargetPath : "/fake/path" ,
246+ }
247+ store .RegisterMetadata (meta )
248+ // Ensure we stop managing the volume after the test
249+ defer func () {
250+ store .RemoveVolume (meta .VolumeID )
251+ m .UnmanageVolume (meta .VolumeID )
252+ }()
253+
254+ // Put the certificate under management
255+ managed := m .ManageVolume (meta .VolumeID )
256+ if ! managed {
257+ t .Errorf ("expected management to have started, but it did not" )
258+ }
259+
260+ if err := wait .PollUntilWithContext (ctx , time .Millisecond * 500 , func (ctx context.Context ) (done bool , err error ) {
261+ reqs , err := opts .Client .CertmanagerV1 ().CertificateRequests ("" ).List (ctx , metav1.ListOptions {})
262+ if err != nil {
263+ return false , err
264+ }
265+ if len (reqs .Items ) == 1 {
266+ return true , nil
267+ }
268+ return false , nil
269+ }); err != nil {
270+ t .Errorf ("failed waiting for CertificateRequest to exist: %v" , err )
271+ }
272+
273+ // Assert the certificate is under management - it won't be ready as no issuer has issued the certificate
274+ if m .IsVolumeReady (meta .VolumeID ) {
275+ t .Errorf ("expected volume to not be Ready but it is" )
276+ }
277+ if _ , ok := m .managedVolumes [meta .VolumeID ]; ! ok {
278+ t .Errorf ("expected volume to be part of managedVolumes map but it is not" )
279+ }
280+ }
281+
18282func TestManager_cleanupStaleRequests (t * testing.T ) {
19283
20284 ctx := context .TODO ()
0 commit comments