@@ -2,10 +2,12 @@ package certsyncpod
2
2
3
3
import (
4
4
"context"
5
+ "fmt"
5
6
"os"
6
7
"path/filepath"
7
8
"reflect"
8
9
10
+ "github.com/openshift/library-go/pkg/operator/staticpod/internal/dirutils"
9
11
apierrors "k8s.io/apimachinery/pkg/api/errors"
10
12
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11
13
utilerrors "k8s.io/apimachinery/pkg/util/errors"
@@ -17,10 +19,12 @@ import (
17
19
18
20
"github.com/openshift/library-go/pkg/controller/factory"
19
21
"github.com/openshift/library-go/pkg/operator/events"
20
- "github.com/openshift/library-go/pkg/operator/staticpod"
21
22
"github.com/openshift/library-go/pkg/operator/staticpod/controller/installer"
23
+ "github.com/openshift/library-go/pkg/operator/staticpod/internal/atomicdir"
22
24
)
23
25
26
+ const stagingDirUID = "cert-sync"
27
+
24
28
type CertSyncController struct {
25
29
destinationDir string
26
30
namespace string
@@ -60,15 +64,32 @@ func NewCertSyncController(targetDir, targetNamespace string, configmaps, secret
60
64
)
61
65
}
62
66
67
+ func getStagingDir (targetDir string ) string {
68
+ return filepath .Join (targetDir , "staging" , stagingDirUID )
69
+ }
70
+
63
71
func getConfigMapDir (targetDir , configMapName string ) string {
64
72
return filepath .Join (targetDir , "configmaps" , configMapName )
65
73
}
66
74
75
+ func getConfigMapStagingDir (targetDir , secretName string ) string {
76
+ return filepath .Join (getStagingDir (targetDir ), "configmaps" , secretName )
77
+ }
78
+
67
79
func getSecretDir (targetDir , secretName string ) string {
68
80
return filepath .Join (targetDir , "secrets" , secretName )
69
81
}
70
82
83
+ func getSecretStagingDir (targetDir , secretName string ) string {
84
+ return filepath .Join (getStagingDir (targetDir ), "secrets" , secretName )
85
+ }
86
+
71
87
func (c * CertSyncController ) sync (ctx context.Context , syncCtx factory.SyncContext ) error {
88
+ if err := dirutils .RemoveContent (getStagingDir (c .destinationDir )); err != nil {
89
+ c .eventRecorder .Warningf ("CertificateUpdateFailed" , fmt .Sprintf ("Failed to prune staging directory: %v" , err ))
90
+ return err
91
+ }
92
+
72
93
errors := []error {}
73
94
74
95
klog .Infof ("Syncing configmaps: %v" , c .configMaps )
@@ -114,8 +135,9 @@ func (c *CertSyncController) sync(ctx context.Context, syncCtx factory.SyncConte
114
135
}
115
136
116
137
contentDir := getConfigMapDir (c .destinationDir , cm .Name )
138
+ stagingDir := getConfigMapStagingDir (c .destinationDir , cm .Name )
117
139
118
- data := map [string ]string {}
140
+ data := make ( map [string ]string , len ( configMap . Data ))
119
141
for filename := range configMap .Data {
120
142
fullFilename := filepath .Join (contentDir , filename )
121
143
@@ -152,27 +174,11 @@ func (c *CertSyncController) sync(ctx context.Context, syncCtx factory.SyncConte
152
174
continue
153
175
}
154
176
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
- }
177
+ files := make (map [string ][]byte , len (configMap .Data ))
178
+ for k , v := range configMap .Data {
179
+ files [k ] = []byte (v )
174
180
}
175
- c .eventRecorder . Eventf ( "CertificateUpdated" , "Wrote updated configmap: %s/%s " , configMap .Namespace , configMap . Name )
181
+ errors = append ( errors , syncDirectory ( c .eventRecorder , "configmap" , configMap .ObjectMeta , contentDir , 0755 , stagingDir , files , 0644 ) )
176
182
}
177
183
178
184
klog .Infof ("Syncing secrets: %v" , c .secrets )
@@ -219,8 +225,9 @@ func (c *CertSyncController) sync(ctx context.Context, syncCtx factory.SyncConte
219
225
}
220
226
221
227
contentDir := getSecretDir (c .destinationDir , s .Name )
228
+ stagingDir := getSecretStagingDir (c .destinationDir , s .Name )
222
229
223
- data := map [string ][]byte {}
230
+ data := make ( map [string ][]byte , len ( secret . Data ))
224
231
for filename := range secret .Data {
225
232
fullFilename := filepath .Join (contentDir , filename )
226
233
@@ -257,29 +264,22 @@ func (c *CertSyncController) sync(ctx context.Context, syncCtx factory.SyncConte
257
264
continue
258
265
}
259
266
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 )
263
- errors = append (errors , err )
264
- continue
265
- }
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
- }
273
-
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 )
267
+ errors = append (errors , syncDirectory (c .eventRecorder , "secret" , secret .ObjectMeta , contentDir , 0700 , stagingDir , data , 0600 ))
282
268
}
283
-
284
269
return utilerrors .NewAggregate (errors )
285
270
}
271
+
272
+ func syncDirectory (
273
+ eventRecorder events.Recorder ,
274
+ typeName string , o metav1.ObjectMeta ,
275
+ targetDir string , targetDirPerm os.FileMode , stagingDir string ,
276
+ files map [string ][]byte , filePerm os.FileMode ,
277
+ ) error {
278
+ if err := atomicdir .Sync (targetDir , targetDirPerm , stagingDir , files , filePerm ); err != nil {
279
+ err = fmt .Errorf ("failed to sync %s %s/%s (directory %q): %w" , typeName , o .Name , o .Namespace , targetDir , err )
280
+ eventRecorder .Warning ("CertificateUpdateFailed" , err .Error ())
281
+ return err
282
+ }
283
+ eventRecorder .Eventf ("CertificateUpdated" , "Wrote updated %s: %s/%s" , typeName , o .Namespace , o .Name )
284
+ return nil
285
+ }
0 commit comments