Skip to content

Commit 806c298

Browse files
committed
m
1 parent 5511f94 commit 806c298

3 files changed

Lines changed: 90 additions & 82 deletions

File tree

controllers/funcs.go

Lines changed: 78 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,17 @@ import (
2222
"errors"
2323
"fmt"
2424
"strings"
25-
"time"
2625

2726
topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1"
2827
corev1 "k8s.io/api/core/v1"
2928
rbacv1 "k8s.io/api/rbac/v1"
30-
k8s_errors "k8s.io/apimachinery/pkg/api/errors"
3129
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3230
ctrl "sigs.k8s.io/controller-runtime"
33-
"sigs.k8s.io/controller-runtime/pkg/client"
31+
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
3432

3533
"github.com/openstack-k8s-operators/lib-common/modules/common/condition"
3634
"github.com/openstack-k8s-operators/lib-common/modules/common/helper"
3735
common_rbac "github.com/openstack-k8s-operators/lib-common/modules/common/rbac"
38-
common_role "github.com/openstack-k8s-operators/lib-common/modules/common/role"
39-
common_rolebinding "github.com/openstack-k8s-operators/lib-common/modules/common/rolebinding"
4036
"github.com/openstack-k8s-operators/lib-common/modules/common/secret"
4137
)
4238

@@ -207,34 +203,34 @@ func ensureConsoleNamespace(
207203
ns := &corev1.Namespace{
208204
ObjectMeta: metav1.ObjectMeta{
209205
Name: consolesNamespace,
210-
Labels: map[string]string{
211-
"app": "ironic",
212-
},
213206
},
214207
}
215208

216-
err := h.GetClient().Get(ctx, client.ObjectKey{Name: consolesNamespace}, ns)
217-
if err != nil {
218-
if k8s_errors.IsNotFound(err) {
219-
// Namespace doesn't exist, create it
220-
err = h.GetClient().Create(ctx, ns)
221-
if err != nil {
222-
return fmt.Errorf("failed to create console namespace %s: %w", consolesNamespace, err)
223-
}
224-
h.GetLogger().Info(fmt.Sprintf("Created console namespace: %s", consolesNamespace))
225-
return nil
209+
op, err := controllerutil.CreateOrPatch(ctx, h.GetClient(), ns, func() error {
210+
// Set labels
211+
if ns.Labels == nil {
212+
ns.Labels = make(map[string]string)
226213
}
227-
return fmt.Errorf("failed to get console namespace %s: %w", consolesNamespace, err)
214+
ns.Labels["app"] = "ironic"
215+
return nil
216+
})
217+
218+
if err != nil {
219+
return fmt.Errorf("failed to reconcile console namespace %s: %w", consolesNamespace, err)
220+
}
221+
222+
if op != controllerutil.OperationResultNone {
223+
h.GetLogger().Info(fmt.Sprintf("Namespace %s %s", consolesNamespace, op))
228224
}
229225

230-
// Namespace already exists
231226
return nil
232227
}
233228

234229
// reconcileGraphicalConsoleRbac creates a Role and RoleBinding in the console namespace
235230
// that grants the ServiceAccount from the service namespace permissions to create console pods.
236231
// This enables cross-namespace RBAC where the ironic ServiceAccount in the 'openstack' namespace
237232
// can create pods and secrets in the 'openstack-ironic-consoles' namespace.
233+
// Note: These resources cannot have owner references since cross-namespace ownership is not allowed.
238234
func reconcileGraphicalConsoleRbac(
239235
ctx context.Context,
240236
h *helper.Helper,
@@ -244,81 +240,91 @@ func reconcileGraphicalConsoleRbac(
244240
rules []rbacv1.PolicyRule,
245241
) (ctrl.Result, error) {
246242
serviceNamespace := instance.RbacNamespace()
247-
248-
// Create Role in the console namespace
249243
roleName := serviceAccountName + "-console-role"
250-
role := common_role.NewRole(
251-
&rbacv1.Role{
252-
ObjectMeta: metav1.ObjectMeta{
253-
Name: roleName,
254-
Namespace: consoleNamespace,
255-
},
256-
Rules: rules,
244+
roleBindingName := serviceAccountName + "-console-rolebinding"
245+
246+
labels := map[string]string{
247+
"app": "ironic",
248+
"ironic.openstack.org/service": serviceAccountName,
249+
}
250+
251+
// Create or update Role in the console namespace without owner references
252+
role := &rbacv1.Role{
253+
ObjectMeta: metav1.ObjectMeta{
254+
Name: roleName,
255+
Namespace: consoleNamespace,
257256
},
258-
time.Duration(10),
259-
)
260-
roleResult, err := role.CreateOrPatch(ctx, h)
257+
}
258+
259+
op, err := controllerutil.CreateOrPatch(ctx, h.GetClient(), role, func() error {
260+
// Set labels
261+
role.Labels = labels
262+
// Set rules
263+
role.Rules = rules
264+
return nil
265+
})
266+
261267
if err != nil {
262268
instance.RbacConditionsSet(condition.FalseCondition(
263269
condition.RoleReadyCondition,
264270
condition.ErrorReason,
265271
condition.SeverityWarning,
266272
condition.RoleReadyErrorMessage,
267273
err.Error()))
268-
return roleResult, err
269-
} else if (roleResult != ctrl.Result{}) {
270-
instance.RbacConditionsSet(condition.FalseCondition(
271-
condition.RoleReadyCondition,
272-
condition.RequestedReason,
273-
condition.SeverityInfo,
274-
condition.RoleCreatingMessage))
275-
return roleResult, nil
274+
return ctrl.Result{}, err
276275
}
276+
277+
if op != controllerutil.OperationResultNone {
278+
h.GetLogger().Info(fmt.Sprintf("Role %s %s in namespace %s", roleName, op, consoleNamespace))
279+
}
280+
277281
instance.RbacConditionsSet(condition.TrueCondition(
278282
condition.RoleReadyCondition,
279283
condition.RoleReadyMessage))
280284

281-
// Create RoleBinding in the console namespace that references the ServiceAccount
282-
// from the service namespace
283-
roleBindingName := serviceAccountName + "-console-rolebinding"
284-
rolebinding := common_rolebinding.NewRoleBinding(
285-
&rbacv1.RoleBinding{
286-
ObjectMeta: metav1.ObjectMeta{
287-
Name: roleBindingName,
288-
Namespace: consoleNamespace,
289-
},
290-
RoleRef: rbacv1.RoleRef{
291-
APIGroup: "rbac.authorization.k8s.io",
292-
Kind: "Role",
293-
Name: roleName,
294-
},
295-
Subjects: []rbacv1.Subject{
296-
{
297-
Kind: "ServiceAccount",
298-
Name: serviceAccountName,
299-
Namespace: serviceNamespace, // Cross-namespace reference
300-
},
301-
},
285+
// Create or update RoleBinding in the console namespace that references the ServiceAccount
286+
// from the service namespace (cross-namespace reference)
287+
roleBinding := &rbacv1.RoleBinding{
288+
ObjectMeta: metav1.ObjectMeta{
289+
Name: roleBindingName,
290+
Namespace: consoleNamespace,
302291
},
303-
time.Duration(10),
304-
)
305-
roleBindingResult, err := rolebinding.CreateOrPatch(ctx, h)
292+
}
293+
294+
op, err = controllerutil.CreateOrPatch(ctx, h.GetClient(), roleBinding, func() error {
295+
// Set labels
296+
roleBinding.Labels = labels
297+
// Set RoleRef (immutable, but safe to set on create)
298+
roleBinding.RoleRef = rbacv1.RoleRef{
299+
APIGroup: "rbac.authorization.k8s.io",
300+
Kind: "Role",
301+
Name: roleName,
302+
}
303+
// Set Subjects
304+
roleBinding.Subjects = []rbacv1.Subject{
305+
{
306+
Kind: "ServiceAccount",
307+
Name: serviceAccountName,
308+
Namespace: serviceNamespace,
309+
},
310+
}
311+
return nil
312+
})
313+
306314
if err != nil {
307315
instance.RbacConditionsSet(condition.FalseCondition(
308316
condition.RoleBindingReadyCondition,
309317
condition.ErrorReason,
310318
condition.SeverityWarning,
311319
condition.RoleBindingReadyErrorMessage,
312320
err.Error()))
313-
return roleBindingResult, err
314-
} else if (roleBindingResult != ctrl.Result{}) {
315-
instance.RbacConditionsSet(condition.FalseCondition(
316-
condition.RoleBindingReadyCondition,
317-
condition.RequestedReason,
318-
condition.SeverityInfo,
319-
condition.RoleBindingCreatingMessage))
320-
return roleBindingResult, nil
321+
return ctrl.Result{}, err
322+
}
323+
324+
if op != controllerutil.OperationResultNone {
325+
h.GetLogger().Info(fmt.Sprintf("RoleBinding %s %s in namespace %s", roleBindingName, op, consoleNamespace))
321326
}
327+
322328
instance.RbacConditionsSet(condition.TrueCondition(
323329
condition.RoleBindingReadyCondition,
324330
condition.RoleBindingReadyMessage))

controllers/ironic_controller.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,6 @@ func (r *IronicReconciler) reconcileNormal(ctx context.Context, instance *ironic
305305
return rbacResult, nil
306306
}
307307

308-
309-
310308
// ConfigMap
311309
configMapVars := make(map[string]env.Setter)
312310

controllers/ironicconductor_controller.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -464,13 +464,6 @@ func (r *IronicConductorReconciler) reconcileServices(
464464
}
465465
}
466466
if instance.Spec.GraphicalConsoles == "Enabled" {
467-
//
468-
// Create the console namespace for graphical console pods
469-
//
470-
err = ensureConsoleNamespace(ctx, helper, instance.Namespace)
471-
if err != nil {
472-
return ctrl.Result{}, err
473-
}
474467

475468
//
476469
// Create the conductor pod route to enable traffic to the
@@ -550,6 +543,17 @@ func (r *IronicConductorReconciler) reconcileNormal(ctx context.Context, instanc
550543

551544
// Roles and binding for existing service account for graphical consoles
552545
if instance.Spec.GraphicalConsoles == "Enabled" {
546+
// TODO: (stevebaker) Uncomment this when the role.yaml
547+
// rule which allows namespace operations is applied.
548+
// Until then, proceed as if the namespace has been created.
549+
// //
550+
// // Create the console namespace for graphical console pods
551+
// //
552+
// err := ensureConsoleNamespace(ctx, helper, instance.Namespace)
553+
// if err != nil {
554+
// return ctrl.Result{}, err
555+
// }
556+
553557
consoleNamespace := getConsoleNamespaceName(instance.Namespace)
554558
serviceAccountName := instance.RbacResourceName()
555559
gcRbacResult, err := reconcileGraphicalConsoleRbac(
@@ -993,9 +997,9 @@ func (r *IronicConductorReconciler) generateServiceConfigMaps(
993997
templateParameters["LogPath"] = ironicconductor.LogPath
994998
graphicalConsolesEnabled := instance.Spec.GraphicalConsoles == "Enabled"
995999
templateParameters["GraphicalConsolesEnabled"] = graphicalConsolesEnabled
1000+
templateParameters["ConsoleNamespace"] = getConsoleNamespaceName(instance.Namespace)
9961001
if graphicalConsolesEnabled {
9971002
templateParameters["ConsoleImage"] = instance.Spec.ConsoleImage
998-
templateParameters["ConsoleNamespace"] = getConsoleNamespaceName(instance.Namespace)
9991003
}
10001004

10011005
databaseAccount := db.GetAccount()

0 commit comments

Comments
 (0)