Skip to content

Commit 6284a0d

Browse files
authored
Merge pull request #42 from munnerz/block-publish-if-ready-to-request
Make NodePublishVolume blocking if a volume is already ready to request
2 parents 7dfb05b + 3d518a1 commit 6284a0d

File tree

2 files changed

+76
-1
lines changed

2 files changed

+76
-1
lines changed

manager/manager.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ func (m *Manager) ManageVolumeImmediate(ctx context.Context, volumeID string) (m
557557
}
558558

559559
// Only attempt issuance immediately if there isn't already an issued certificate
560-
if meta.NextIssuanceTime == nil {
560+
if meta.NextIssuanceTime == nil || meta.NextIssuanceTime.IsZero() {
561561
// If issuance fails, immediately return without retrying so the caller can decide
562562
// how to proceed depending on the context this method was called within.
563563
if err := m.issue(ctx, volumeID); err != nil {

test/integration/ready_to_request_test.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,81 @@ import (
4040
testutil "github.com/cert-manager/csi-lib/test/util"
4141
)
4242

43+
// Tests to ensure that if a certificate is immediately ready to be requested when NodePublishVolume
44+
// is called, the call will be blocking until the volume is actually ready.
45+
func Test_PublishCallBlocksIfReadyToRequestDespiteContinueOnNotReadyTrue(t *testing.T) {
46+
store := storage.NewMemoryFS()
47+
clock := fakeclock.NewFakeClock(time.Now())
48+
49+
opts, cl, stop := testdriver.Run(t, testdriver.Options{
50+
Store: store,
51+
Clock: clock,
52+
ContinueOnNotReady: true,
53+
ReadyToRequest: manager.AlwaysReadyToRequest,
54+
GeneratePrivateKey: func(meta metadata.Metadata) (crypto.PrivateKey, error) {
55+
return nil, nil
56+
},
57+
GenerateRequest: func(meta metadata.Metadata) (*manager.CertificateRequestBundle, error) {
58+
return &manager.CertificateRequestBundle{
59+
Namespace: "certificaterequest-namespace",
60+
}, nil
61+
},
62+
SignRequest: func(meta metadata.Metadata, key crypto.PrivateKey, request *x509.CertificateRequest) (csr []byte, err error) {
63+
return []byte{}, nil
64+
},
65+
WriteKeypair: func(meta metadata.Metadata, key crypto.PrivateKey, chain []byte, ca []byte) error {
66+
store.WriteFiles(meta, map[string][]byte{
67+
"ca": ca,
68+
"cert": chain,
69+
})
70+
nextIssuanceTime := clock.Now().Add(time.Hour)
71+
meta.NextIssuanceTime = &nextIssuanceTime
72+
return store.WriteMetadata(meta.VolumeID, meta)
73+
},
74+
})
75+
defer stop()
76+
77+
// Setup a routine to issue/sign the request IF it is created
78+
stopCh := make(chan struct{})
79+
go testutil.IssueAllRequests(t, opts.Client, "certificaterequest-namespace", stopCh, selfSignedExampleCertificate, []byte("ca bytes"))
80+
defer close(stopCh)
81+
82+
tmpDir, err := os.MkdirTemp("", "*")
83+
if err != nil {
84+
t.Fatal(err)
85+
}
86+
defer os.RemoveAll(tmpDir)
87+
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
88+
defer cancel()
89+
// This call will block until an issuance is successfully completed.
90+
_, err = cl.NodePublishVolume(ctx, &csi.NodePublishVolumeRequest{
91+
VolumeId: "test-vol",
92+
VolumeContext: map[string]string{
93+
"csi.storage.k8s.io/ephemeral": "true",
94+
"csi.storage.k8s.io/pod.name": "the-pod-name",
95+
"csi.storage.k8s.io/pod.namespace": "the-pod-namespace",
96+
},
97+
TargetPath: tmpDir,
98+
Readonly: true,
99+
})
100+
if err != nil {
101+
t.Fatal(err)
102+
}
103+
104+
// We don't wait at all after the NodePublishVolume call, as it should have blocked
105+
// above meaning the read should immediately succeed.
106+
files, err := store.ReadFiles("test-vol")
107+
if err != nil {
108+
t.Error(err)
109+
}
110+
if !reflect.DeepEqual(files["ca"], []byte("ca bytes")) {
111+
t.Errorf("unexpected CA data: %v", files["ca"])
112+
}
113+
if !reflect.DeepEqual(files["cert"], selfSignedExampleCertificate) {
114+
t.Errorf("unexpected certificate data: %v", files["cert"])
115+
}
116+
}
117+
43118
func Test_CompletesIfNotReadyToRequest_ContinueOnNotReadyEnabled(t *testing.T) {
44119
store := storage.NewMemoryFS()
45120
clock := fakeclock.NewFakeClock(time.Now())

0 commit comments

Comments
 (0)