Skip to content
This repository has been archived by the owner on Apr 22, 2024. It is now read-only.

Commit

Permalink
move controller initialization to PreRun
Browse files Browse the repository at this point in the history
Signed-off-by: huabing zhao <[email protected]>
  • Loading branch information
zhaohuabing committed Feb 27, 2024
1 parent 7befec3 commit 082c3cb
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 31 deletions.
60 changes: 32 additions & 28 deletions internal/k8s/secret_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ type SecretController struct {
config *configv1.Config
secrets map[string][]*oidcv1.OIDCConfig
restConf *rest.Config
manager manager.Manager
k8sClient client.Client
namespace string
}
Expand All @@ -63,10 +64,16 @@ func NewSecretController(cfg *configv1.Config) *SecretController {
}
}

// Name implements run.PreRunner
func (s *SecretController) Name() string { return "Secret controller" }

// PreRun saves the original configuration in PreRun phase because the
// configuration is loaded from the file in the Config Validate phase.
func (s *SecretController) PreRun() error {
var needWatchSecrets = false
var (
needWatchSecrets = false
err error
)

// Check if there are any k8s secrets to watch
for _, c := range s.config.Chains {
Expand Down Expand Up @@ -118,57 +125,54 @@ func (s *SecretController) PreRun() error {
}
}

// Load the k8s configuration from in-cluster environment
if s.restConf == nil {
conf, err := config.GetConfig()
s.restConf, err = config.GetConfig()
if err != nil {
return fmt.Errorf("%w: %w", ErrLoadingConfig, err)
}
s.restConf = conf
}

return nil
}
// The controller manager is encapsulated in the secret controller because we
// only need it to watch secrets and update the configuration.
//TODO: Add manager options, like metrics, healthz, leader election, etc.
s.manager, err = ctrl.NewManager(s.restConf, manager.Options{})
s.k8sClient = s.manager.GetClient()
if err != nil {
return fmt.Errorf("error creating controller manager: %w", err)
}

func secretNamespacedName(secretRef *oidcv1.OIDCConfig_SecretReference, currentNamespace string) types.NamespacedName {
return types.NamespacedName{
Namespace: currentNamespace,
Name: secretRef.GetName(),
if err = ctrl.NewControllerManagedBy(s.manager).
For(&corev1.Secret{}).
Complete(s); err != nil {
return fmt.Errorf("error creating secret controller:%w", err)
}
}

// Name implements run.PreRunner
func (s *SecretController) Name() string { return "Secret controller" }
return nil
}

// ServeContext starts the controller manager and watches secrets for updates.
// The controller manager is encapsulated in the secret controller because we
// only need it to watch secrets and update the configuration.
func (s *SecretController) ServeContext(ctx context.Context) error {
// If there are no secrets to watch, we can skip starting the controller manager
if len(s.secrets) == 0 {
<-ctx.Done()
return nil
}

//TODO: Add manager options, like metrics, healthz, leader election, etc.
mgr, err := ctrl.NewManager(s.restConf, manager.Options{})
s.k8sClient = mgr.GetClient()
if err != nil {
return fmt.Errorf("error creating controller manager: %w", err)
}

if err = ctrl.NewControllerManagedBy(mgr).
For(&corev1.Secret{}).
Complete(s); err != nil {
return fmt.Errorf("error creating secret controller:%w", err)
}

if err = mgr.Start(ctx); err != nil {
if err := s.manager.Start(ctx); err != nil {
return fmt.Errorf("error starting controller manager:%w", err)
}

return nil
}

func secretNamespacedName(secretRef *oidcv1.OIDCConfig_SecretReference, currentNamespace string) types.NamespacedName {
return types.NamespacedName{
Namespace: currentNamespace,
Name: secretRef.GetName(),
}
}

func (s *SecretController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
changedSecret := req.NamespacedName.String()

Expand Down
6 changes: 4 additions & 2 deletions internal/k8s/secret_controller_lifecycle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,13 @@ func TestController(t *testing.T) {
require.NoError(t, err)
}()

t.Run("controller ", func(t *testing.T) {
t.Run("controller is setup at preRun", func(t *testing.T) {
require.Eventually(t, func() bool {
return controller.k8sClient != nil
}, defaultWait, defaultTick, "Controller manager is not ready")
}, defaultWait, defaultTick, "Controller manager is not setup")
})

t.Run("controller is ready", func(t *testing.T) {
require.Eventually(t, func() bool {
err := controller.k8sClient.Create(context.Background(), &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Expand Down
3 changes: 2 additions & 1 deletion internal/k8s/secret_controller_reconcile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,15 @@ func TestOIDCProcessWithKubernetesSecret(t *testing.T) {
secrets := secretsForTest()
kubeClient := fake.NewClientBuilder().WithLists(secrets).Build()
controller := NewSecretController(originalConf)
controller.k8sClient = kubeClient
controller.namespace = "default"

// pre-run the controller
err := controller.PreRun()
if tt.err != "" {
require.EqualError(t, err, tt.err)
}
// replace the k8s client with the fake client for testing
controller.k8sClient = kubeClient

// reconcile the secrets
for _, secret := range secrets.Items {
Expand Down

0 comments on commit 082c3cb

Please sign in to comment.