diff --git a/pkg/cmds/webhook.go b/pkg/cmds/webhook.go index 06c09b94..768fc471 100644 --- a/pkg/cmds/webhook.go +++ b/pkg/cmds/webhook.go @@ -25,11 +25,15 @@ import ( "github.com/spf13/cobra" flag "github.com/spf13/pflag" + reg "k8s.io/api/admissionregistration/v1" v1 "k8s.io/api/admissionregistration/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/wait" clientscheme "k8s.io/client-go/kubernetes/scheme" _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/klog/v2" "k8s.io/klog/v2/klogr" + kutil "kmodules.xyz/client-go" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/healthz" @@ -40,6 +44,11 @@ import ( var setupLog = ctrl.Log.WithName("setup") +const ( + releaseRevisionLabelKey = "release-revision" + releaseRevisionEnvKey = "RELEASE_REVISION" +) + func NewCmdWebhook(ctx context.Context) *cobra.Command { certDir := "/var/serving-cert" var webhookName string @@ -104,6 +113,12 @@ func NewCmdWebhook(ctx context.Context) *cobra.Command { if err := mgr.Add(manager.RunnableFunc(func(ctx context.Context) error { if mgr.GetCache().WaitForCacheSync(context.TODO()) { + kbclient := mgr.GetClient() + klog.Infoln("waiting for webhook configuration to be ready") + err := WaitUntilWebhookConfigurationApplied(ctx, webhookName, kbclient) + if err != nil { + setupLog.Error(err, "unable to wait until webhook configuration is applied") + } if err := updateMutatingWebhookCABundle(mgr, webhookName, certDir); err != nil { setupLog.Error(err, "unable to update caBundle for MutatingWebhookConfiguration") os.Exit(1) @@ -138,7 +153,6 @@ func updateMutatingWebhookCABundle(mgr ctrl.Manager, name, certDir string) error if err != nil { return err } - caBundle, err := os.ReadFile(filepath.Join(certDir, "ca.crt")) if err != nil { return err @@ -167,3 +181,36 @@ func updateValidatingWebhookCABundle(mgr ctrl.Manager, name, certDir string) err } return mgr.GetClient().Update(context.TODO(), webhook, &client.UpdateOptions{}) } + +func WaitUntilWebhookConfigurationApplied(ctx context.Context, webhookName string, c client.Client) error { + releaseRevision := os.Getenv(releaseRevisionEnvKey) + + return wait.PollUntilContextTimeout(ctx, kutil.RetryInterval, kutil.ReadinessTimeout, true, func(ctx context.Context) (bool, error) { + var mwc reg.MutatingWebhookConfiguration + err := c.Get(ctx, types.NamespacedName{ + Name: webhookName, + }, &mwc) + if err != nil { + return false, nil + } + var vwc reg.ValidatingWebhookConfiguration + err = c.Get(ctx, types.NamespacedName{ + Name: webhookName, + }, &vwc) + if err != nil { + return false, nil + } + mwcReleaseRevision, mwcExists := mwc.ObjectMeta.Labels[releaseRevisionLabelKey] + vwcReleaseRevision, vwcExists := vwc.ObjectMeta.Labels[releaseRevisionLabelKey] + + if !mwcExists || !vwcExists { + return false, nil + } + + if mwcReleaseRevision != releaseRevision || vwcReleaseRevision != releaseRevision { + return false, nil + } + + return true, nil + }) +}