@@ -23,11 +23,11 @@ import (
23
23
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
24
24
"k8s.io/client-go/informers"
25
25
"k8s.io/client-go/tools/cache"
26
+ "k8s.io/client-go/tools/clientcmd"
26
27
"k8s.io/client-go/util/workqueue"
27
28
28
29
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/reference"
29
30
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
30
- "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client"
31
31
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned"
32
32
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/informers/externalversions"
33
33
olmerrors "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/errors"
@@ -39,6 +39,7 @@ import (
39
39
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorlister"
40
40
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
41
41
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/queueinformer"
42
+ "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/scoped"
42
43
"github.com/operator-framework/operator-lifecycle-manager/pkg/metrics"
43
44
)
44
45
@@ -75,6 +76,8 @@ type Operator struct {
75
76
resolver resolver.Resolver
76
77
reconciler reconciler.RegistryReconcilerFactory
77
78
csvProvidedAPIsIndexer map [string ]cache.Indexer
79
+ clientAttenuator * scoped.ClientAttenuator
80
+ serviceAccountQuerier * scoped.UserDefinedServiceAccountQuerier
78
81
}
79
82
80
83
// NewOperator creates a new Catalog Operator.
@@ -84,8 +87,13 @@ func NewOperator(ctx context.Context, kubeconfigPath string, clock utilclock.Clo
84
87
watchedNamespaces = []string {metav1 .NamespaceAll }
85
88
}
86
89
90
+ config , err := clientcmd .BuildConfigFromFlags ("" , kubeconfigPath )
91
+ if err != nil {
92
+ return nil , err
93
+ }
94
+
87
95
// Create a new client for OLM types (CRs)
88
- crClient , err := client . NewClient ( kubeconfigPath )
96
+ crClient , err := versioned . NewForConfig ( config )
89
97
if err != nil {
90
98
return nil , err
91
99
}
@@ -114,6 +122,8 @@ func NewOperator(ctx context.Context, kubeconfigPath string, clock utilclock.Clo
114
122
catsrcQueueSet : queueinformer .NewEmptyResourceQueueSet (),
115
123
subQueueSet : queueinformer .NewEmptyResourceQueueSet (),
116
124
csvProvidedAPIsIndexer : map [string ]cache.Indexer {},
125
+ serviceAccountQuerier : scoped .NewUserDefinedServiceAccountQuerier (logger , crClient ),
126
+ clientAttenuator : scoped .NewClientAttenuator (logger , config , opClient , crClient ),
117
127
}
118
128
op .reconciler = reconciler .NewRegistryReconcilerFactory (lister , opClient , configmapRegistryImage , op .now )
119
129
@@ -1037,6 +1047,18 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1037
1047
return err
1038
1048
}
1039
1049
1050
+ // Does the namespace have an operator group that specifies a user defined
1051
+ // service account? If so, then we should use a scoped client for plan
1052
+ // execution.
1053
+ getter := o .serviceAccountQuerier .NamespaceQuerier (namespace )
1054
+ kubeclient , crclient , err := o .clientAttenuator .AttenuateClient (getter )
1055
+ if err != nil {
1056
+ o .logger .Errorf ("failed to get a client for plan execution- %v" , err )
1057
+ return err
1058
+ }
1059
+
1060
+ ensurer := newStepEnsurer (kubeclient , crclient )
1061
+
1040
1062
for i , step := range plan .Status .Plan {
1041
1063
switch step .Status {
1042
1064
case v1alpha1 .StepStatusPresent , v1alpha1 .StepStatusCreated :
@@ -1112,16 +1134,14 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1112
1134
1113
1135
// Attempt to create the CSV.
1114
1136
csv .SetNamespace (namespace )
1115
- _ , err = o .client .OperatorsV1alpha1 ().ClusterServiceVersions (csv .GetNamespace ()).Create (& csv )
1116
- if k8serrors .IsAlreadyExists (err ) {
1117
- // If it already existed, mark the step as Present.
1118
- plan .Status .Plan [i ].Status = v1alpha1 .StepStatusPresent
1119
- } else if err != nil {
1120
- return errorwrap .Wrapf (err , "error creating csv %s" , csv .GetName ())
1121
- } else {
1122
- // If no error occurred, mark the step as Created.
1123
- plan .Status .Plan [i ].Status = v1alpha1 .StepStatusCreated
1137
+
1138
+ status , err := ensurer .EnsureClusterServiceVersion (& csv )
1139
+ if err != nil {
1140
+ return err
1124
1141
}
1142
+
1143
+ plan .Status .Plan [i ].Status = status
1144
+
1125
1145
case v1alpha1 .SubscriptionKind :
1126
1146
// Marshal the manifest into a subscription instance.
1127
1147
var sub v1alpha1.Subscription
@@ -1139,47 +1159,22 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1139
1159
1140
1160
// Attempt to create the Subscription
1141
1161
sub .SetNamespace (namespace )
1142
- _ , err = o .client .OperatorsV1alpha1 ().Subscriptions (sub .GetNamespace ()).Create (& sub )
1143
- if k8serrors .IsAlreadyExists (err ) {
1144
- // If it already existed, mark the step as Present.
1145
- plan .Status .Plan [i ].Status = v1alpha1 .StepStatusPresent
1146
- } else if err != nil {
1147
- return errorwrap .Wrapf (err , "error creating subscription %s" , sub .GetName ())
1148
- } else {
1149
- // If no error occurred, mark the step as Created.
1150
- plan .Status .Plan [i ].Status = v1alpha1 .StepStatusCreated
1151
- }
1152
- case secretKind :
1153
- // TODO: this will confuse bundle users that include secrets in their bundles - this only handles pull secrets
1154
- // Get the pre-existing secret.
1155
- secret , err := o .opClient .KubernetesInterface ().CoreV1 ().Secrets (o .namespace ).Get (step .Resource .Name , metav1.GetOptions {})
1156
- if k8serrors .IsNotFound (err ) {
1157
- return fmt .Errorf ("secret %s does not exist" , step .Resource .Name )
1158
- } else if err != nil {
1159
- return errorwrap .Wrapf (err , "error getting pull secret from olm namespace %s" , secret .GetName ())
1162
+
1163
+ status , err := ensurer .EnsureSubscription (& sub )
1164
+ if err != nil {
1165
+ return err
1160
1166
}
1161
1167
1162
- // Set the namespace to the InstallPlan's namespace and attempt to
1163
- // create a new secret.
1164
- secret .SetNamespace (namespace )
1165
- _ , err = o .opClient .KubernetesInterface ().CoreV1 ().Secrets (plan .Namespace ).Create (& corev1.Secret {
1166
- ObjectMeta : metav1.ObjectMeta {
1167
- Name : secret .Name ,
1168
- Namespace : plan .Namespace ,
1169
- },
1170
- Data : secret .Data ,
1171
- Type : secret .Type ,
1172
- })
1173
- if k8serrors .IsAlreadyExists (err ) {
1174
- // If it already existed, mark the step as Present.
1175
- plan .Status .Plan [i ].Status = v1alpha1 .StepStatusPresent
1176
- } else if err != nil {
1168
+ plan .Status .Plan [i ].Status = status
1169
+
1170
+ case secretKind :
1171
+ status , err := ensurer .EnsureSecret (o .namespace , plan .GetNamespace (), step .Resource .Name )
1172
+ if err != nil {
1177
1173
return err
1178
- } else {
1179
- // If no error occured, mark the step as Created.
1180
- plan .Status .Plan [i ].Status = v1alpha1 .StepStatusCreated
1181
1174
}
1182
1175
1176
+ plan .Status .Plan [i ].Status = status
1177
+
1183
1178
case clusterRoleKind :
1184
1179
// Marshal the manifest into a ClusterRole instance.
1185
1180
var cr rbacv1.ClusterRole
@@ -1188,23 +1183,13 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1188
1183
return errorwrap .Wrapf (err , "error parsing step manifest: %s" , step .Resource .Name )
1189
1184
}
1190
1185
1191
- // Attempt to create the ClusterRole.
1192
- _ , err = o .opClient .KubernetesInterface ().RbacV1 ().ClusterRoles ().Create (& cr )
1193
- if k8serrors .IsAlreadyExists (err ) {
1194
- // if we're updating, point owner to the newest csv
1195
- cr .Labels [ownerutil .OwnerKey ] = step .Resolving
1196
- _ , err = o .opClient .UpdateClusterRole (& cr )
1197
- if err != nil {
1198
- return errorwrap .Wrapf (err , "error updating clusterrole %s" , cr .GetName ())
1199
- }
1200
- // If it already existed, mark the step as Present.
1201
- plan .Status .Plan [i ].Status = v1alpha1 .StepStatusPresent
1202
- } else if err != nil {
1203
- return errorwrap .Wrapf (err , "error creating clusterrole %s" , cr .GetName ())
1204
- } else {
1205
- // If no error occurred, mark the step as Created.
1206
- plan .Status .Plan [i ].Status = v1alpha1 .StepStatusCreated
1186
+ status , err := ensurer .EnsureClusterRole (& cr , step )
1187
+ if err != nil {
1188
+ return err
1207
1189
}
1190
+
1191
+ plan .Status .Plan [i ].Status = status
1192
+
1208
1193
case clusterRoleBindingKind :
1209
1194
// Marshal the manifest into a RoleBinding instance.
1210
1195
var rb rbacv1.ClusterRoleBinding
@@ -1213,25 +1198,13 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1213
1198
return errorwrap .Wrapf (err , "error parsing step manifest: %s" , step .Resource .Name )
1214
1199
}
1215
1200
1216
- // Attempt to create the ClusterRoleBinding.
1217
- _ , err = o .opClient .KubernetesInterface ().RbacV1 ().ClusterRoleBindings ().Create (& rb )
1218
- if k8serrors .IsAlreadyExists (err ) {
1219
- // if we're updating, point owner to the newest csv
1220
- rb .Labels [ownerutil .OwnerKey ] = step .Resolving
1221
- _ , err = o .opClient .UpdateClusterRoleBinding (& rb )
1222
- if err != nil {
1223
- return errorwrap .Wrapf (err , "error updating clusterrolebinding %s" , rb .GetName ())
1224
- }
1225
-
1226
- // If it already existed, mark the step as Present.
1227
- plan .Status .Plan [i ].Status = v1alpha1 .StepStatusPresent
1228
- } else if err != nil {
1229
- return errorwrap .Wrapf (err , "error creating clusterrolebinding %s" , rb .GetName ())
1230
- } else {
1231
- // If no error occurred, mark the step as Created.
1232
- plan .Status .Plan [i ].Status = v1alpha1 .StepStatusCreated
1201
+ status , err := ensurer .EnsureClusterRoleBinding (& rb , step )
1202
+ if err != nil {
1203
+ return err
1233
1204
}
1234
1205
1206
+ plan .Status .Plan [i ].Status = status
1207
+
1235
1208
case roleKind :
1236
1209
// Marshal the manifest into a Role instance.
1237
1210
var r rbacv1.Role
@@ -1248,24 +1221,13 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1248
1221
r .SetOwnerReferences (updated )
1249
1222
r .SetNamespace (namespace )
1250
1223
1251
- // Attempt to create the Role.
1252
- _ , err = o .opClient .KubernetesInterface ().RbacV1 ().Roles (plan .Namespace ).Create (& r )
1253
- if k8serrors .IsAlreadyExists (err ) {
1254
- // If it already existed, mark the step as Present.
1255
- r .SetNamespace (plan .Namespace )
1256
- _ , err = o .opClient .UpdateRole (& r )
1257
- if err != nil {
1258
- return errorwrap .Wrapf (err , "error updating role %s" , r .GetName ())
1259
- }
1260
-
1261
- plan .Status .Plan [i ].Status = v1alpha1 .StepStatusPresent
1262
- } else if err != nil {
1263
- return errorwrap .Wrapf (err , "error creating role %s" , r .GetName ())
1264
- } else {
1265
- // If no error occurred, mark the step as Created.
1266
- plan .Status .Plan [i ].Status = v1alpha1 .StepStatusCreated
1224
+ status , err := ensurer .EnsureRole (plan .Namespace , & r )
1225
+ if err != nil {
1226
+ return err
1267
1227
}
1268
1228
1229
+ plan .Status .Plan [i ].Status = status
1230
+
1269
1231
case roleBindingKind :
1270
1232
// Marshal the manifest into a RoleBinding instance.
1271
1233
var rb rbacv1.RoleBinding
@@ -1282,24 +1244,13 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1282
1244
rb .SetOwnerReferences (updated )
1283
1245
rb .SetNamespace (namespace )
1284
1246
1285
- // Attempt to create the RoleBinding.
1286
- _ , err = o .opClient .KubernetesInterface ().RbacV1 ().RoleBindings (plan .Namespace ).Create (& rb )
1287
- if k8serrors .IsAlreadyExists (err ) {
1288
- rb .SetNamespace (plan .Namespace )
1289
- _ , err = o .opClient .UpdateRoleBinding (& rb )
1290
- if err != nil {
1291
- return errorwrap .Wrapf (err , "error updating rolebinding %s" , rb .GetName ())
1292
- }
1293
-
1294
- // If it already existed, mark the step as Present.
1295
- plan .Status .Plan [i ].Status = v1alpha1 .StepStatusPresent
1296
- } else if err != nil {
1297
- return errorwrap .Wrapf (err , "error creating rolebinding %s" , rb .GetName ())
1298
- } else {
1299
- // If no error occurred, mark the step as Created.
1300
- plan .Status .Plan [i ].Status = v1alpha1 .StepStatusCreated
1247
+ status , err := ensurer .EnsureRoleBinding (plan .Namespace , & rb )
1248
+ if err != nil {
1249
+ return err
1301
1250
}
1302
1251
1252
+ plan .Status .Plan [i ].Status = status
1253
+
1303
1254
case serviceAccountKind :
1304
1255
// Marshal the manifest into a ServiceAccount instance.
1305
1256
var sa corev1.ServiceAccount
@@ -1316,25 +1267,13 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1316
1267
sa .SetOwnerReferences (updated )
1317
1268
sa .SetNamespace (namespace )
1318
1269
1319
- // Attempt to create the ServiceAccount.
1320
- _ , err = o .opClient .KubernetesInterface ().CoreV1 ().ServiceAccounts (plan .Namespace ).Create (& sa )
1321
- if k8serrors .IsAlreadyExists (err ) {
1322
- // If it already exists we need to patch the existing SA with the new OwnerReferences
1323
- sa .SetNamespace (plan .Namespace )
1324
- _ , err = o .opClient .UpdateServiceAccount (& sa )
1325
- if err != nil {
1326
- return errorwrap .Wrapf (err , "error updating service account: %s" , sa .GetName ())
1327
- }
1328
-
1329
- // Mark as present
1330
- plan .Status .Plan [i ].Status = v1alpha1 .StepStatusPresent
1331
- } else if err != nil {
1332
- return errorwrap .Wrapf (err , "error creating service account: %s" , sa .GetName ())
1333
- } else {
1334
- // If no error occurred, mark the step as Created.
1335
- plan .Status .Plan [i ].Status = v1alpha1 .StepStatusCreated
1270
+ status , err := ensurer .EnsureServiceAccount (namespace , & sa )
1271
+ if err != nil {
1272
+ return err
1336
1273
}
1337
1274
1275
+ plan .Status .Plan [i ].Status = status
1276
+
1338
1277
case serviceKind :
1339
1278
// Marshal the manifest into a Service instance
1340
1279
var s corev1.Service
@@ -1351,25 +1290,13 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1351
1290
s .SetOwnerReferences (updated )
1352
1291
s .SetNamespace (namespace )
1353
1292
1354
- // Attempt to create the Service
1355
- _ , err = o .opClient .KubernetesInterface ().CoreV1 ().Services (plan .Namespace ).Create (& s )
1356
- if k8serrors .IsAlreadyExists (err ) {
1357
- // If it already exists we need to patch the existing SA with the new OwnerReferences
1358
- s .SetNamespace (plan .Namespace )
1359
- _ , err = o .opClient .UpdateService (& s )
1360
- if err != nil {
1361
- return errorwrap .Wrapf (err , "error updating service: %s" , s .GetName ())
1362
- }
1363
-
1364
- // Mark as present
1365
- plan .Status .Plan [i ].Status = v1alpha1 .StepStatusPresent
1366
- } else if err != nil {
1367
- return errorwrap .Wrapf (err , "error creating service: %s" , s .GetName ())
1368
- } else {
1369
- // If no error occurred, mark the step as Created
1370
- plan .Status .Plan [i ].Status = v1alpha1 .StepStatusCreated
1293
+ status , err := ensurer .EnsureService (namespace , & s )
1294
+ if err != nil {
1295
+ return err
1371
1296
}
1372
1297
1298
+ plan .Status .Plan [i ].Status = status
1299
+
1373
1300
default :
1374
1301
return v1alpha1 .ErrInvalidInstallPlan
1375
1302
}
0 commit comments