Skip to content

Commit 9db1069

Browse files
joelanfordclaude
andcommitted
⚠ Single-tenant simplification: remove deprecated features and simplify operator model
Implement the single-tenant simplification design to re-affirm OLM v1's cluster-admin-only operational model. Changes across work items: - 01-cluster-admin: Grant operator-controller cluster-admin ClusterRole (remove custom RBAC rules) - 02-deprecate-service-account: Mark spec.serviceAccount as deprecated and optional; remove from docs/examples/tooling - 03-remove-preflight-permissions: Remove PreflightPermissions feature gate and RBAC pre-authorization code - 04-remove-synthetic-permissions: Remove SyntheticPermissions feature gate and synthetic user/group authentication - 05-remove-single-own-namespace: Remove SingleOwnNamespaceInstallSupport feature gate, watchNamespace config, and own-namespace test fixtures - 07-simplify-contentmanager: Remove per-extension REST config and use shared manager client for content management - 09-documentation: Resolve merge conflicts, add cleanup tracking Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
5 parents 6078a1e + a413f64 + f0ea057 + bb55e34 + 127614b commit 9db1069

File tree

133 files changed

+727
-50185
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

133 files changed

+727
-50185
lines changed

api/v1/clusterextension_types.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,14 @@ type ClusterExtensionSpec struct {
6666
// +required
6767
Namespace string `json:"namespace"`
6868

69-
// serviceAccount specifies a ServiceAccount used to perform all interactions with the cluster
70-
// that are required to manage the extension.
71-
// The ServiceAccount must be configured with the necessary permissions to perform these interactions.
72-
// The ServiceAccount must exist in the namespace referenced in the spec.
73-
// The serviceAccount field is required.
69+
// serviceAccount was previously used to specify a ServiceAccount for managing the extension.
70+
// This field is now deprecated and ignored. operator-controller uses its own ServiceAccount
71+
// for all Kubernetes API interactions.
7472
//
75-
// +required
76-
ServiceAccount ServiceAccountReference `json:"serviceAccount"`
73+
// Deprecated: This field is ignored. It will be removed in a future API version.
74+
//
75+
// +optional
76+
ServiceAccount ServiceAccountReference `json:"serviceAccount,omitzero"`
7777

7878
// source is required and selects the installation source of content for this ClusterExtension.
7979
// Set the sourceType field to perform the selection.
@@ -376,7 +376,10 @@ type CatalogFilter struct {
376376
UpgradeConstraintPolicy UpgradeConstraintPolicy `json:"upgradeConstraintPolicy,omitempty"`
377377
}
378378

379-
// ServiceAccountReference identifies the serviceAccount used fo install a ClusterExtension.
379+
// ServiceAccountReference identifies the serviceAccount used to install a ClusterExtension.
380+
//
381+
// Deprecated: This type is deprecated and will be removed in a future API version.
382+
// operator-controller now uses its own ServiceAccount for all operations.
380383
type ServiceAccountReference struct {
381384
// name is a required, immutable reference to the name of the ServiceAccount used for installation
382385
// and management of the content for the package specified in the packageName field.
@@ -549,6 +552,10 @@ type ClusterExtensionInstallStatus struct {
549552
// +kubebuilder:printcolumn:name=Age,type=date,JSONPath=`.metadata.creationTimestamp`
550553

551554
// ClusterExtension is the Schema for the clusterextensions API
555+
//
556+
// WARNING: This is a cluster-admin-only API. Creating a ClusterExtension instructs
557+
// operator-controller to install arbitrary workloads and RBAC, which is equivalent to
558+
// cluster-admin privileges. Only cluster administrators should have write access to this resource.
552559
type ClusterExtension struct {
553560
metav1.TypeMeta `json:",inline"`
554561

api/v1/validation_test.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@ func TestValidate(t *testing.T) {
2323
}
2424
defaultExtensionSpec := func(s *ClusterExtensionSpec) *ClusterExtensionSpec {
2525
s.Namespace = "ns"
26-
s.ServiceAccount = ServiceAccountReference{
27-
Name: "sa",
28-
}
2926
s.Source = SourceConfig{
3027
SourceType: SourceTypeCatalog,
3128
Catalog: &CatalogFilter{

applyconfigurations/api/v1/clusterextensionspec.go

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

applyconfigurations/api/v1/serviceaccountreference.go

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/operator-controller/main.go

Lines changed: 16 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ import (
5959
ocv1 "github.com/operator-framework/operator-controller/api/v1"
6060
"github.com/operator-framework/operator-controller/internal/operator-controller/action"
6161
"github.com/operator-framework/operator-controller/internal/operator-controller/applier"
62-
"github.com/operator-framework/operator-controller/internal/operator-controller/authentication"
6362
"github.com/operator-framework/operator-controller/internal/operator-controller/catalogmetadata/cache"
6463
catalogclient "github.com/operator-framework/operator-controller/internal/operator-controller/catalogmetadata/client"
6564
"github.com/operator-framework/operator-controller/internal/operator-controller/contentmanager"
@@ -474,11 +473,10 @@ func run() error {
474473

475474
certProvider := getCertificateProvider()
476475
regv1ManifestProvider := &applier.RegistryV1ManifestProvider{
477-
BundleRenderer: registryv1.Renderer,
478-
CertificateProvider: certProvider,
479-
IsWebhookSupportEnabled: certProvider != nil,
480-
IsSingleOwnNamespaceEnabled: features.OperatorControllerFeatureGate.Enabled(features.SingleOwnNamespaceInstallSupport),
481-
IsDeploymentConfigEnabled: features.OperatorControllerFeatureGate.Enabled(features.DeploymentConfig),
476+
BundleRenderer: registryv1.Renderer,
477+
CertificateProvider: certProvider,
478+
IsWebhookSupportEnabled: certProvider != nil,
479+
IsDeploymentConfigEnabled: features.OperatorControllerFeatureGate.Enabled(features.DeploymentConfig),
482480
}
483481
var cerCfg reconcilerConfigurator
484482
if features.OperatorControllerFeatureGate.Enabled(features.BoxcutterRuntime) {
@@ -622,9 +620,6 @@ func (c *boxcutterReconcilerConfigurator) Configure(ceReconciler *controllers.Cl
622620
}
623621
ceReconciler.ReconcileSteps = []controllers.ReconcileStepFunc{
624622
controllers.HandleFinalizers(c.finalizers),
625-
controllers.ValidateClusterExtension(
626-
controllers.ServiceAccountValidator(coreClient),
627-
),
628623
controllers.MigrateStorage(storageMigrator),
629624
controllers.RetrieveRevisionStates(revisionStatesGetter),
630625
controllers.ResolveBundle(c.resolver, c.mgr.GetClient()),
@@ -654,29 +649,19 @@ func (c *boxcutterReconcilerConfigurator) Configure(ceReconciler *controllers.Cl
654649
return fmt.Errorf("unable to add tracking cache to manager: %v", err)
655650
}
656651

657-
cerCoreClient, err := corev1client.NewForConfig(c.mgr.GetConfig())
658-
if err != nil {
659-
return fmt.Errorf("unable to create client for ClusterExtensionRevision controller: %w", err)
660-
}
661-
cerTokenGetter := authentication.NewTokenGetter(cerCoreClient, authentication.WithExpirationDuration(1*time.Hour))
662-
663-
revisionEngineFactory, err := controllers.NewDefaultRevisionEngineFactory(
652+
revisionEngine := controllers.NewRevisionEngine(
664653
c.mgr.GetScheme(),
665654
trackingCache,
666655
discoveryClient,
667656
c.mgr.GetRESTMapper(),
668657
fieldOwnerPrefix,
669-
c.mgr.GetConfig(),
670-
cerTokenGetter,
658+
c.mgr.GetClient(),
671659
)
672-
if err != nil {
673-
return fmt.Errorf("unable to create revision engine factory: %w", err)
674-
}
675660

676661
if err = (&controllers.ClusterExtensionRevisionReconciler{
677-
Client: c.mgr.GetClient(),
678-
RevisionEngineFactory: revisionEngineFactory,
679-
TrackingCache: trackingCache,
662+
Client: c.mgr.GetClient(),
663+
RevisionEngine: revisionEngine,
664+
TrackingCache: trackingCache,
680665
}).SetupWithManager(c.mgr); err != nil {
681666
return fmt.Errorf("unable to setup ClusterExtensionRevision controller: %w", err)
682667
}
@@ -688,19 +673,13 @@ func (c *helmReconcilerConfigurator) Configure(ceReconciler *controllers.Cluster
688673
if err != nil {
689674
return fmt.Errorf("unable to create core client: %w", err)
690675
}
691-
tokenGetter := authentication.NewTokenGetter(coreClient, authentication.WithExpirationDuration(1*time.Hour))
692-
clientRestConfigMapper := action.ServiceAccountRestConfigMapper(tokenGetter)
693-
if features.OperatorControllerFeatureGate.Enabled(features.SyntheticPermissions) {
694-
clientRestConfigMapper = action.SyntheticUserRestConfigMapper(clientRestConfigMapper)
695-
}
696676

697677
cfgGetter, err := helmclient.NewActionConfigGetter(c.mgr.GetConfig(), c.mgr.GetRESTMapper(),
698678
helmclient.StorageDriverMapper(action.ChunkedStorageDriverMapper(coreClient, c.mgr.GetAPIReader(), cfg.systemNamespace)),
699679
helmclient.ClientNamespaceMapper(func(obj client.Object) (string, error) {
700680
ext := obj.(*ocv1.ClusterExtension)
701681
return ext.Spec.Namespace, nil
702682
}),
703-
helmclient.ClientRestConfigMapper(clientRestConfigMapper),
704683
)
705684
if err != nil {
706685
return fmt.Errorf("unable to create helm action config getter: %w", err)
@@ -713,11 +692,14 @@ func (c *helmReconcilerConfigurator) Configure(ceReconciler *controllers.Cluster
713692
return fmt.Errorf("unable to create helm action client getter: %w", err)
714693
}
715694

716-
cm := contentmanager.NewManager(clientRestConfigMapper, c.mgr.GetConfig(), c.mgr.GetRESTMapper())
695+
cm, err := contentmanager.NewManager(c.mgr.GetConfig(), c.mgr.GetRESTMapper())
696+
if err != nil {
697+
setupLog.Error(err, "unable to create content manager")
698+
return err
699+
}
717700
err = c.finalizers.Register(controllers.ClusterExtensionCleanupContentManagerCacheFinalizer, finalizers.FinalizerFunc(func(ctx context.Context, obj client.Object) (crfinalizer.Result, error) {
718-
ext := obj.(*ocv1.ClusterExtension)
719-
err := cm.Delete(ext)
720-
return crfinalizer.Result{}, err
701+
cm.Delete(ctx, obj.GetName())
702+
return crfinalizer.Result{}, nil
721703
}))
722704
if err != nil {
723705
setupLog.Error(err, "unable to register content manager cleanup finalizer")
@@ -737,9 +719,6 @@ func (c *helmReconcilerConfigurator) Configure(ceReconciler *controllers.Cluster
737719
revisionStatesGetter := &controllers.HelmRevisionStatesGetter{ActionClientGetter: acg}
738720
ceReconciler.ReconcileSteps = []controllers.ReconcileStepFunc{
739721
controllers.HandleFinalizers(c.finalizers),
740-
controllers.ValidateClusterExtension(
741-
controllers.ServiceAccountValidator(coreClient),
742-
),
743722
controllers.RetrieveRevisionStates(revisionStatesGetter),
744723
controllers.ResolveBundle(c.resolver, c.mgr.GetClient()),
745724
controllers.UnpackBundle(c.imagePuller, c.imageCache),

0 commit comments

Comments
 (0)