diff --git a/internal/controller/apicerts/certs_manager_test.go b/internal/controller/apicerts/certs_manager_test.go index f36268e54..f7e99bdd5 100644 --- a/internal/controller/apicerts/certs_manager_test.go +++ b/internal/controller/apicerts/certs_manager_test.go @@ -103,7 +103,7 @@ func TestManagerControllerOptions(t *testing.T) { when("starting up", func() { it("asks for an initial event because the Secret may not exist yet and it needs to run anyway", func() { - r.Equal(controllerlib.Key{ + r.Equal(&controllerlib.Key{ Namespace: installedInNamespace, Name: certsSecretResourceName, }, observableWithInitialEventOption.GetInitialEventKey()) diff --git a/internal/controller/kubecertagent/creater.go b/internal/controller/kubecertagent/creater.go index 8354d6fd4..229848ec7 100644 --- a/internal/controller/kubecertagent/creater.go +++ b/internal/controller/kubecertagent/creater.go @@ -44,6 +44,7 @@ func NewCreaterController( kubeSystemPodInformer corev1informers.PodInformer, agentPodInformer corev1informers.PodInformer, withInformer pinnipedcontroller.WithInformerOptionFunc, + withInitialEvent pinnipedcontroller.WithInitialEventOptionFunc, ) controllerlib.Controller { return controllerlib.New( controllerlib.Config{ @@ -69,6 +70,10 @@ func NewCreaterController( pinnipedcontroller.SimpleFilter(isAgentPod), controllerlib.InformerOption{}, ), + // Be sure to run once even to make sure the CIC is updated if there are no controller manager + // pods. We should be able to pass an empty key since we don't use the key in the sync (we sync + // the world). + withInitialEvent(controllerlib.Key{}), ) } diff --git a/internal/controller/kubecertagent/creater_test.go b/internal/controller/kubecertagent/creater_test.go index 430ac83a5..2953b1f4c 100644 --- a/internal/controller/kubecertagent/creater_test.go +++ b/internal/controller/kubecertagent/creater_test.go @@ -48,11 +48,35 @@ func TestCreaterControllerFilter(t *testing.T) { kubeSystemPodInformer, agentPodInformer, observableWithInformerOption.WithInformer, + controllerlib.WithInitialEvent, ) }, ) } +func TestCreaterControllerInitialEvent(t *testing.T) { + kubeSystemInformerClient := kubernetesfake.NewSimpleClientset() + kubeSystemInformers := kubeinformers.NewSharedInformerFactory(kubeSystemInformerClient, 0) + + agentInformerClient := kubernetesfake.NewSimpleClientset() + agentInformers := kubeinformers.NewSharedInformerFactory(agentInformerClient, 0) + + observableWithInitialEventOption := testutil.NewObservableWithInitialEventOption() + + _ = NewCreaterController( + nil, // agentPodConfig, shouldn't matter + nil, // credentialIssuerConfigLocationConfig, shouldn't matter + nil, // clock, shound't matter + nil, // k8sClient, shouldn't matter + nil, // pinnipedAPIClient, shouldn't matter + kubeSystemInformers.Core().V1().Pods(), + agentInformers.Core().V1().Pods(), + controllerlib.WithInformer, + observableWithInitialEventOption.WithInitialEvent, + ) + require.Equal(t, &controllerlib.Key{}, observableWithInitialEventOption.GetInitialEventKey()) +} + func TestCreaterControllerSync(t *testing.T) { spec.Run(t, "CreaterControllerSync", func(t *testing.T, when spec.G, it spec.S) { const kubeSystemNamespace = "kube-system" @@ -98,6 +122,7 @@ func TestCreaterControllerSync(t *testing.T) { kubeSystemInformers.Core().V1().Pods(), agentInformers.Core().V1().Pods(), controllerlib.WithInformer, + controllerlib.WithInitialEvent, ) // Set this at the last second to support calling subject.Name(). diff --git a/internal/controllermanager/prepare_controllers.go b/internal/controllermanager/prepare_controllers.go index 41f22ce70..88296f3d0 100644 --- a/internal/controllermanager/prepare_controllers.go +++ b/internal/controllermanager/prepare_controllers.go @@ -180,6 +180,7 @@ func PrepareControllers(c *Config) (func(ctx context.Context), error) { informers.kubeSystemNamespaceK8s.Core().V1().Pods(), informers.installationNamespaceK8s.Core().V1().Pods(), controllerlib.WithInformer, + controllerlib.WithInitialEvent, ), singletonWorker, ). diff --git a/internal/testutil/observable_with_initial_event_option.go b/internal/testutil/observable_with_initial_event_option.go index 8cfb1e4d0..091390c39 100644 --- a/internal/testutil/observable_with_initial_event_option.go +++ b/internal/testutil/observable_with_initial_event_option.go @@ -6,7 +6,7 @@ package testutil import "go.pinniped.dev/internal/controllerlib" type ObservableWithInitialEventOption struct { - key controllerlib.Key + key *controllerlib.Key } func NewObservableWithInitialEventOption() *ObservableWithInitialEventOption { @@ -14,10 +14,11 @@ func NewObservableWithInitialEventOption() *ObservableWithInitialEventOption { } func (i *ObservableWithInitialEventOption) WithInitialEvent(key controllerlib.Key) controllerlib.Option { - i.key = key + i.key = new(controllerlib.Key) + *i.key = key return controllerlib.WithInitialEvent(key) } -func (i *ObservableWithInitialEventOption) GetInitialEventKey() controllerlib.Key { +func (i *ObservableWithInitialEventOption) GetInitialEventKey() *controllerlib.Key { return i.key }