@@ -23,13 +23,18 @@ import (
23
23
"net/http"
24
24
"os"
25
25
"path/filepath"
26
+ "strings"
26
27
"time"
27
28
28
29
"github.com/containers/image/v5/types"
29
30
"github.com/go-logr/logr"
30
31
"github.com/spf13/pflag"
32
+ corev1 "k8s.io/api/core/v1"
31
33
apiextensionsv1client "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1"
34
+ "k8s.io/apimachinery/pkg/fields"
32
35
k8slabels "k8s.io/apimachinery/pkg/labels"
36
+ k8stypes "k8s.io/apimachinery/pkg/types"
37
+ apimachineryrand "k8s.io/apimachinery/pkg/util/rand"
33
38
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
34
39
_ "k8s.io/client-go/plugin/pkg/client/auth"
35
40
"k8s.io/klog/v2"
67
72
defaultSystemNamespace = "olmv1-system"
68
73
)
69
74
70
- const authFilePath = "/etc/ operator-controller/auth.json "
75
+ const authFilePrefix = "operator-controller-global-pull-secrets "
71
76
72
77
// podNamespace checks whether the controller is running in a Pod vs.
73
78
// being run locally by inspecting the namespace file that gets mounted
@@ -90,6 +95,7 @@ func main() {
90
95
operatorControllerVersion bool
91
96
systemNamespace string
92
97
caCertDir string
98
+ globalPullSecret string
93
99
)
94
100
flag .StringVar (& metricsAddr , "metrics-bind-address" , ":8080" , "The address the metric endpoint binds to." )
95
101
flag .StringVar (& probeAddr , "health-probe-bind-address" , ":8081" , "The address the probe endpoint binds to." )
@@ -100,6 +106,7 @@ func main() {
100
106
flag .StringVar (& cachePath , "cache-path" , "/var/cache" , "The local directory path used for filesystem based caching" )
101
107
flag .BoolVar (& operatorControllerVersion , "version" , false , "Prints operator-controller version information" )
102
108
flag .StringVar (& systemNamespace , "system-namespace" , "" , "Configures the namespace that gets used to deploy system resources." )
109
+ flag .StringVar (& globalPullSecret , "global-pull-secret" , "" , "The <namespace>/<name> of the global pull secret that is going to be used to pull bundle images." )
103
110
104
111
klog .InitFlags (flag .CommandLine )
105
112
@@ -116,27 +123,51 @@ func main() {
116
123
117
124
setupLog .Info ("starting up the controller" , "version info" , version .String ())
118
125
126
+ authFilePath := filepath .Join (os .TempDir (), fmt .Sprintf ("%s-%s.json" , authFilePrefix , apimachineryrand .String (8 )))
127
+ var globalPullSecretKey * k8stypes.NamespacedName
128
+ if globalPullSecret != "" {
129
+ secretParts := strings .Split (globalPullSecret , "/" )
130
+ if len (secretParts ) != 2 {
131
+ setupLog .Error (fmt .Errorf ("incorrect number of components" ), "value of global-pull-secret should be of the format <namespace>/<name>" )
132
+ os .Exit (1 )
133
+ }
134
+ globalPullSecretKey = & k8stypes.NamespacedName {Name : secretParts [1 ], Namespace : secretParts [0 ]}
135
+ }
136
+
119
137
if systemNamespace == "" {
120
138
systemNamespace = podNamespace ()
121
139
}
122
140
123
141
setupLog .Info ("set up manager" )
142
+ cacheOptions := crcache.Options {
143
+ ByObject : map [client.Object ]crcache.ByObject {
144
+ & ocv1alpha1.ClusterExtension {}: {Label : k8slabels .Everything ()},
145
+ & catalogd.ClusterCatalog {}: {Label : k8slabels .Everything ()},
146
+ },
147
+ DefaultNamespaces : map [string ]crcache.Config {
148
+ systemNamespace : {LabelSelector : k8slabels .Everything ()},
149
+ },
150
+ DefaultLabelSelector : k8slabels .Nothing (),
151
+ }
152
+ if globalPullSecretKey != nil {
153
+ cacheOptions .ByObject [& corev1.Secret {}] = crcache.ByObject {
154
+ Namespaces : map [string ]crcache.Config {
155
+ globalPullSecretKey .Namespace : {
156
+ LabelSelector : k8slabels .Everything (),
157
+ FieldSelector : fields .SelectorFromSet (map [string ]string {
158
+ "metadata.name" : globalPullSecretKey .Name ,
159
+ }),
160
+ },
161
+ },
162
+ }
163
+ }
124
164
mgr , err := ctrl .NewManager (ctrl .GetConfigOrDie (), ctrl.Options {
125
165
Scheme : scheme .Scheme ,
126
166
Metrics : server.Options {BindAddress : metricsAddr },
127
167
HealthProbeBindAddress : probeAddr ,
128
168
LeaderElection : enableLeaderElection ,
129
169
LeaderElectionID : "9c4404e7.operatorframework.io" ,
130
- Cache : crcache.Options {
131
- ByObject : map [client.Object ]crcache.ByObject {
132
- & ocv1alpha1.ClusterExtension {}: {Label : k8slabels .Everything ()},
133
- & catalogd.ClusterCatalog {}: {Label : k8slabels .Everything ()},
134
- },
135
- DefaultNamespaces : map [string ]crcache.Config {
136
- systemNamespace : {LabelSelector : k8slabels .Everything ()},
137
- },
138
- DefaultLabelSelector : k8slabels .Nothing (),
139
- },
170
+ Cache : cacheOptions ,
140
171
// LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily
141
172
// when the Manager ends. This requires the binary to immediately end when the
142
173
// Manager is stopped, otherwise, this setting is unsafe. Setting this significantly
@@ -191,12 +222,21 @@ func main() {
191
222
192
223
unpacker := & source.ContainersImageRegistry {
193
224
BaseCachePath : filepath .Join (cachePath , "unpack" ),
194
- SourceContext : & types.SystemContext {
195
- DockerCertPath : caCertDir ,
196
- OCICertPath : caCertDir ,
197
- AuthFilePath : authFilePathIfPresent (setupLog ),
198
- },
199
- }
225
+ SourceContextFunc : func (logger logr.Logger ) (* types.SystemContext , error ) {
226
+ srcContext := & types.SystemContext {
227
+ DockerCertPath : caCertDir ,
228
+ OCICertPath : caCertDir ,
229
+ }
230
+ if _ , err := os .Stat (authFilePath ); err == nil && globalPullSecretKey != nil {
231
+ logger .Info ("using available authentication information for pulling image" )
232
+ srcContext .AuthFilePath = authFilePath
233
+ } else if os .IsNotExist (err ) {
234
+ logger .Info ("no authentication information found for pulling image, proceeding without auth" )
235
+ } else {
236
+ return nil , fmt .Errorf ("could not stat auth file, error: %w" , err )
237
+ }
238
+ return srcContext , nil
239
+ }}
200
240
201
241
clusterExtensionFinalizers := crfinalizer .NewFinalizers ()
202
242
if err := clusterExtensionFinalizers .Register (controllers .ClusterExtensionCleanupUnpackCacheFinalizer , finalizers .FinalizerFunc (func (ctx context.Context , obj client.Object ) (crfinalizer.Result , error ) {
@@ -281,6 +321,19 @@ func main() {
281
321
os .Exit (1 )
282
322
}
283
323
324
+ if globalPullSecretKey != nil {
325
+ setupLog .Info ("creating SecretSyncer controller for watching secret" , "Secret" , globalPullSecret )
326
+ err := (& controllers.PullSecretReconciler {
327
+ Client : mgr .GetClient (),
328
+ AuthFilePath : authFilePath ,
329
+ SecretKey : * globalPullSecretKey ,
330
+ }).SetupWithManager (mgr )
331
+ if err != nil {
332
+ setupLog .Error (err , "unable to create controller" , "controller" , "SecretSyncer" )
333
+ os .Exit (1 )
334
+ }
335
+ }
336
+
284
337
//+kubebuilder:scaffold:builder
285
338
286
339
if err := mgr .AddHealthzCheck ("healthz" , healthz .Ping ); err != nil {
@@ -298,18 +351,8 @@ func main() {
298
351
setupLog .Error (err , "problem running manager" )
299
352
os .Exit (1 )
300
353
}
301
- }
302
-
303
- func authFilePathIfPresent (logger logr.Logger ) string {
304
- _ , err := os .Stat (authFilePath )
305
- if os .IsNotExist (err ) {
306
- logger .Info ("auth file not found, skipping configuration of global auth file" , "path" , authFilePath )
307
- return ""
308
- }
309
- if err != nil {
310
- logger .Error (err , "unable to access auth file path" , "path" , authFilePath )
354
+ if err := os .Remove (authFilePath ); err != nil {
355
+ setupLog .Error (err , "failed to cleanup temporary auth file" )
311
356
os .Exit (1 )
312
357
}
313
- logger .Info ("auth file found, configuring globally for image registry interactions" , "path" , authFilePath )
314
- return authFilePath
315
358
}
0 commit comments