@@ -115,7 +115,7 @@ func (c *CertSyncController) sync(ctx context.Context, syncCtx factory.SyncConte
115
115
116
116
contentDir := getConfigMapDir (c .destinationDir , cm .Name )
117
117
118
- data := map [string ]string {}
118
+ data := make ( map [string ]string , len ( configMap . Data ))
119
119
for filename := range configMap .Data {
120
120
fullFilename := filepath .Join (contentDir , filename )
121
121
@@ -152,27 +152,7 @@ func (c *CertSyncController) sync(ctx context.Context, syncCtx factory.SyncConte
152
152
continue
153
153
}
154
154
155
- klog .Infof ("Creating directory %q ..." , contentDir )
156
- if err := os .MkdirAll (contentDir , 0755 ); err != nil && ! os .IsExist (err ) {
157
- c .eventRecorder .Warningf ("CertificateUpdateFailed" , "Failed creating directory for configmap: %s/%s: %v" , configMap .Namespace , configMap .Name , err )
158
- errors = append (errors , err )
159
- continue
160
- }
161
- for filename , content := range configMap .Data {
162
- fullFilename := filepath .Join (contentDir , filename )
163
- // if the existing is the same, do nothing
164
- if reflect .DeepEqual (data [fullFilename ], content ) {
165
- continue
166
- }
167
-
168
- klog .Infof ("Writing configmap manifest %q ..." , fullFilename )
169
- if err := staticpod .WriteFileAtomic ([]byte (content ), 0644 , fullFilename ); err != nil {
170
- c .eventRecorder .Warningf ("CertificateUpdateFailed" , "Failed writing file for configmap: %s/%s: %v" , configMap .Namespace , configMap .Name , err )
171
- errors = append (errors , err )
172
- continue
173
- }
174
- }
175
- c .eventRecorder .Eventf ("CertificateUpdated" , "Wrote updated configmap: %s/%s" , configMap .Namespace , configMap .Name )
155
+ errors = append (errors , writeFiles (& realFS , c .eventRecorder , configMap .Namespace , configMap .Name , "configmap" , contentDir , data , 0644 )... )
176
156
}
177
157
178
158
klog .Infof ("Syncing secrets: %v" , c .secrets )
@@ -220,7 +200,7 @@ func (c *CertSyncController) sync(ctx context.Context, syncCtx factory.SyncConte
220
200
221
201
contentDir := getSecretDir (c .destinationDir , s .Name )
222
202
223
- data := map [string ][]byte {}
203
+ data := make ( map [string ][]byte , len ( secret . Data ))
224
204
for filename := range secret .Data {
225
205
fullFilename := filepath .Join (contentDir , filename )
226
206
@@ -257,29 +237,80 @@ func (c *CertSyncController) sync(ctx context.Context, syncCtx factory.SyncConte
257
237
continue
258
238
}
259
239
260
- klog .Infof ("Creating directory %q ..." , contentDir )
261
- if err := os .MkdirAll (contentDir , 0755 ); err != nil && ! os .IsExist (err ) {
262
- c .eventRecorder .Warningf ("CertificateUpdateFailed" , "Failed creating directory for secret: %s/%s: %v" , secret .Namespace , secret .Name , err )
240
+ errors = append (errors , writeFiles (& realFS , c .eventRecorder , secret .Namespace , secret .Name , "secret" , contentDir , data , 0600 )... )
241
+ }
242
+
243
+ return utilerrors .NewAggregate (errors )
244
+ }
245
+
246
+ type fileSystem struct {
247
+ MkdirAll func (path string , perm os.FileMode ) error
248
+ MkdirTemp func (dir , pattern string ) (string , error )
249
+ RemoveAll func (path string ) error
250
+ WriteFile func (name string , data []byte , perm os.FileMode ) error
251
+ SwapDirectoriesAtomic func (dirA , dirB string ) error
252
+ }
253
+
254
+ var realFS = fileSystem {
255
+ MkdirAll : os .MkdirAll ,
256
+ MkdirTemp : os .MkdirTemp ,
257
+ RemoveAll : os .RemoveAll ,
258
+ WriteFile : os .WriteFile ,
259
+ SwapDirectoriesAtomic : staticpod .SwapDirectoriesAtomic ,
260
+ }
261
+
262
+ func writeFiles [C string | []byte ](
263
+ fs * fileSystem , eventRecorder events.Recorder ,
264
+ objectNamespace , objectName , kind string ,
265
+ contentDir string , files map [string ]C , filePerm os.FileMode ,
266
+ ) []error {
267
+ var errors []error
268
+
269
+ // We are going to atomically swap the new data directory for the old one.
270
+ // In case the target directory does not exist, create it so that the directory not existing is not a special case.
271
+ klog .Infof ("Ensuring directory %q exists ..." , contentDir )
272
+ if err := fs .MkdirAll (contentDir , 0755 ); err != nil && ! os .IsExist (err ) {
273
+ eventRecorder .Warningf ("CertificateUpdateFailed" ,
274
+ "Failed creating content directory for %s: %s/%s: %v" , kind , objectNamespace , objectName , err )
275
+ errors = append (errors , err )
276
+ return errors
277
+ }
278
+
279
+ // Create a tmp source directory to be swapped.
280
+ srcDir , err := fs .MkdirTemp (filepath .Dir (contentDir ), filepath .Base (contentDir )+ "-*" )
281
+ if err != nil {
282
+ eventRecorder .Warningf ("CertificateUpdateFailed" ,
283
+ "Failed to create source %s directory for %s/%s: %v" , kind , objectNamespace , objectName , err )
284
+ errors = append (errors , err )
285
+ return errors
286
+ }
287
+ defer fs .RemoveAll (srcDir )
288
+
289
+ // Populate the tmp directory with files.
290
+ for filename , content := range files {
291
+ fullFilename := filepath .Join (srcDir , filename )
292
+ klog .Infof ("Writing %s manifest %q ..." , kind , fullFilename )
293
+
294
+ if err := fs .WriteFile (fullFilename , []byte (content ), filePerm ); err != nil {
295
+ eventRecorder .Warningf ("CertificateUpdateFailed" ,
296
+ "Failed writing file for %s: %s/%s: %v" , kind , objectNamespace , objectName , err )
263
297
errors = append (errors , err )
264
298
continue
265
299
}
266
- for filename , content := range secret .Data {
267
- // TODO fix permissions
268
- fullFilename := filepath .Join (contentDir , filename )
269
- // if the existing is the same, do nothing
270
- if reflect .DeepEqual (data [fullFilename ], content ) {
271
- continue
272
- }
300
+ }
301
+ if len (errors ) > 0 {
302
+ return errors
303
+ }
273
304
274
- klog .Infof ("Writing secret manifest %q ..." , fullFilename )
275
- if err := staticpod .WriteFileAtomic (content , 0600 , fullFilename ); err != nil {
276
- c .eventRecorder .Warningf ("CertificateUpdateFailed" , "Failed writing file for secret: %s/%s: %v" , secret .Namespace , secret .Name , err )
277
- errors = append (errors , err )
278
- continue
279
- }
280
- }
281
- c .eventRecorder .Eventf ("CertificateUpdated" , "Wrote updated secret: %s/%s" , secret .Namespace , secret .Name )
305
+ // Swap directories atomically.
306
+ if err := fs .SwapDirectoriesAtomic (contentDir , srcDir ); err != nil {
307
+ eventRecorder .Warningf ("CertificateUpdateFailed" ,
308
+ "Failed to enable new %s directory for %s/%s: %v" , kind , objectNamespace , objectName , err )
309
+ errors = append (errors , err )
310
+ return errors
282
311
}
283
312
284
- return utilerrors .NewAggregate (errors )
313
+ eventRecorder .Eventf ("CertificateUpdated" ,
314
+ "Wrote updated %s: %s/%s" , kind , objectNamespace , objectName )
315
+ return nil
285
316
}
0 commit comments