Repository: knative/pkg
Pull request #2469 (2022-03-18 18:10:23)

bump k8s deps to v0.23.5
Latest patch came out this week.

knative-prow-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/knative/pkg/pull/2469#" title="Author self-approved">dprotaso</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=knative%2Fpkg).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/knative/pkg/blob/main/OWNERS)~~ [dprotaso]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
knative-prow-robot: @dprotaso: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-knative-pkg-unit-tests | e187f70873557e7754fdd2967624a60b7d8344e5 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_pkg/2469/pull-knative-pkg-unit-tests/1504882932416778240) | true | `/test pull-knative-pkg-unit-tests`

[Full PR test history](https://gubernator.knative.dev/pr/knative_pkg/2469). [Your PR dashboard](https://gubernator.knative.dev/pr/dprotaso).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
knative-prow-robot: @dprotaso: The following tests **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-knative-pkg-unit-tests | e187f70873557e7754fdd2967624a60b7d8344e5 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_pkg/2469/pull-knative-pkg-unit-tests/1504882932416778240) | true | `/test pull-knative-pkg-unit-tests`
pull-knative-pkg-build-tests | e187f70873557e7754fdd2967624a60b7d8344e5 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_pkg/2469/pull-knative-pkg-build-tests/1504882932379029504) | true | `/test pull-knative-pkg-build-tests`

[Full PR test history](https://gubernator.knative.dev/pr/knative_pkg/2469). [Your PR dashboard](https://gubernator.knative.dev/pr/dprotaso).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
codecov[bot]: # [Codecov](https://codecov.io/gh/knative/pkg/pull/2469?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative) Report
> Merging [#2469](https://codecov.io/gh/knative/pkg/pull/2469?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative) (67750b2) into [main](https://codecov.io/gh/knative/pkg/commit/7f16595277b23aaa88a30b4f174782e0ea9206d9?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative) (7f16595) will **decrease** coverage by `0.02%`.
> The diff coverage is `n/a`.

```diff
@@            Coverage Diff             @@
##             main    #2469      +/-   ##
==========================================
- Coverage   63.56%   63.53%   -0.03%     
==========================================
  Files         228      228              
  Lines       10007    10007              
==========================================
- Hits         6361     6358       -3     
- Misses       3343     3345       +2     
- Partials      303      304       +1     
```


| [Impacted Files](https://codecov.io/gh/knative/pkg/pull/2469?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative) | Coverage Δ | |
|---|---|---|
| [test/gcs/mock/mock.go](https://codecov.io/gh/knative/pkg/pull/2469/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative#diff-dGVzdC9nY3MvbW9jay9tb2NrLmdv) | `90.32% <0.00%> (-1.08%)` | :arrow_down: |
| [controller/controller.go](https://codecov.io/gh/knative/pkg/pull/2469/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative#diff-Y29udHJvbGxlci9jb250cm9sbGVyLmdv) | `88.01% <0.00%> (-0.38%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/knative/pkg/pull/2469?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/knative/pkg/pull/2469?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative). Last update [7f16595...67750b2](https://codecov.io/gh/knative/pkg/pull/2469?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative).


Patch:
diff --git a/.codecov.yaml b/.codecov.yaml
index da447d16a..1c1f0db20 100644
--- a/.codecov.yaml
+++ b/.codecov.yaml
@@ -18,6 +18,10 @@ comment:
   behavior: default
 ignore:
   - "**/zz_generated*.go" # Ignore generated files.
+  - "codegen/**/*" #TODO: fix coverage
+  - "injection/**/*" #TODO: fix coverage
+  - "test/**/*"
+  - "tracing/**/*" #TODO: fix coverage
   - "client"
   - "hack"
   - "reconciler/testing"
diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES
index 3cd3cd791..60484d324 100644
--- a/OWNERS_ALIASES
+++ b/OWNERS_ALIASES
@@ -63,6 +63,7 @@ aliases:
   - lberk
   - lionelvillard
   - matzew
+  - odacremolbap
   - pierDipi
   - vaikas
   knative-admin:
diff --git a/code-of-conduct.md b/code-of-conduct.md
index 5f04b3187..355a52f82 100644
--- a/code-of-conduct.md
+++ b/code-of-conduct.md
@@ -1,75 +1,3 @@
-# Contributor Covenant Code of Conduct
+## Knative Community Code of Conduct
 
-## Our Pledge
-
-In the interest of fostering an open and welcoming environment, we as
-contributors and maintainers pledge to making participation in our project and
-our community a harassment-free experience for everyone, regardless of age, body
-size, disability, ethnicity, gender identity and expression, level of
-experience, education, socio-economic status, nationality, personal appearance,
-race, religion, or sexual identity and orientation.
-
-## Our Standards
-
-Examples of behavior that contributes to creating a positive environment
-include:
-
-- Using welcoming and inclusive language
-- Being respectful of differing viewpoints and experiences
-- Gracefully accepting constructive criticism
-- Focusing on what is best for the community
-- Showing empathy towards other community members
-
-Examples of unacceptable behavior by participants include:
-
-- The use of sexualized language or imagery and unwelcome sexual attention or
-  advances
-- Trolling, insulting/derogatory comments, and personal or political attacks
-- Public or private harassment
-- Publishing others' private information, such as a physical or electronic
-  address, without explicit permission
-- Other conduct which could reasonably be considered inappropriate in a
-  professional setting
-
-## Our Responsibilities
-
-Project maintainers are responsible for clarifying the standards of acceptable
-behavior and are expected to take appropriate and fair corrective action in
-response to any instances of unacceptable behavior.
-
-Project maintainers have the right and responsibility to remove, edit, or reject
-comments, commits, code, wiki edits, issues, and other contributions that are
-not aligned to this Code of Conduct, or to ban temporarily or permanently any
-contributor for other behaviors that they deem inappropriate, threatening,
-offensive, or harmful.
-
-## Scope
-
-This Code of Conduct applies both within project spaces and in public spaces
-when an individual is representing the project or its community. Examples of
-representing a project or community include using an official project e-mail
-address, posting via an official social media account, or acting as an appointed
-representative at an online or offline event. Representation of a project may be
-further defined and clarified by project maintainers.
-
-## Enforcement
-
-Instances of abusive, harassing, or otherwise unacceptable behavior may be
-reported by contacting the project team at
-knative-code-of-conduct@googlegroups.com. All complaints will be reviewed and
-investigated and will result in a response that is deemed necessary and
-appropriate to the circumstances. The project team is obligated to maintain
-confidentiality with regard to the reporter of an incident. Further details of
-specific enforcement policies may be posted separately.
-
-Project maintainers who do not follow or enforce the Code of Conduct in good
-faith may face temporary or permanent repercussions as determined by other
-members of the project's leadership.
-
-## Attribution
-
-This Code of Conduct is adapted from the [Contributor Covenant][homepage],
-version 1.4, available at
-https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
-
-[homepage]: https://www.contributor-covenant.org
+The [Knative Community Code of Conduct](https://github.com/knative/community/blob/main/CODE-OF-CONDUCT.md) is defined in the [Knative community repository](https://github.com/knative/community).
diff --git a/controller/controller.go b/controller/controller.go
index b6c8662d2..9fdb0a9d5 100644
--- a/controller/controller.go
+++ b/controller/controller.go
@@ -468,6 +468,13 @@ func (c *Impl) RunContext(ctx context.Context, threadiness int) error {
 		if err != nil {
 			return err
 		}
+		if ib, ok := le.(kle.ElectorWithInitialBuckets); ok {
+			for _, b := range ib.InitialBuckets() {
+				// No need to provide an enq function since the controller
+				// is not processing items
+				la.Promote(b, nil)
+			}
+		}
 		sg.Add(1)
 		go func() {
 			defer sg.Done()
diff --git a/go.mod b/go.mod
index 7ed80bef2..8432447af 100644
--- a/go.mod
+++ b/go.mod
@@ -41,13 +41,13 @@ require (
 	google.golang.org/grpc v1.42.0
 	google.golang.org/protobuf v1.27.1
 	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
-	k8s.io/api v0.23.4
+	k8s.io/api v0.23.5
 	k8s.io/apiextensions-apiserver v0.23.4
-	k8s.io/apimachinery v0.23.4
-	k8s.io/client-go v0.23.4
-	k8s.io/code-generator v0.23.4
+	k8s.io/apimachinery v0.23.5
+	k8s.io/client-go v0.23.5
+	k8s.io/code-generator v0.23.5
 	k8s.io/gengo v0.0.0-20220307231824-4627b89bbf1b
-	k8s.io/klog/v2 v2.40.2-0.20220227211518-7ea6d6adb645
+	k8s.io/klog/v2 v2.60.1-0.20220317184644-43cc75f9ae89
 	knative.dev/hack v0.0.0-20220224013837-e1785985d364
 	sigs.k8s.io/yaml v1.3.0
 )
diff --git a/go.sum b/go.sum
index 53ea8c319..dae1043a5 100644
--- a/go.sum
+++ b/go.sum
@@ -1161,17 +1161,21 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
 honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
 honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-k8s.io/api v0.23.4 h1:85gnfXQOWbJa1SiWGpE9EEtHs0UVvDyIsSMpEtl2D4E=
 k8s.io/api v0.23.4/go.mod h1:i77F4JfyNNrhOjZF7OwwNJS5Y1S9dpwvb9iYRYRczfI=
+k8s.io/api v0.23.5 h1:zno3LUiMubxD/V1Zw3ijyKO3wxrhbUF1Ck+VjBvfaoA=
+k8s.io/api v0.23.5/go.mod h1:Na4XuKng8PXJ2JsploYYrivXrINeTaycCGcYgF91Xm8=
 k8s.io/apiextensions-apiserver v0.23.4 h1:AFDUEu/yEf0YnuZhqhIFhPLPhhcQQVuR1u3WCh0rveU=
 k8s.io/apiextensions-apiserver v0.23.4/go.mod h1:TWYAKymJx7nLMxWCgWm2RYGXHrGlVZnxIlGnvtfYu+g=
-k8s.io/apimachinery v0.23.4 h1:fhnuMd/xUL3Cjfl64j5ULKZ1/J9n8NuQEgNL+WXWfdM=
 k8s.io/apimachinery v0.23.4/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM=
+k8s.io/apimachinery v0.23.5 h1:Va7dwhp8wgkUPWsEXk6XglXWU4IKYLKNlv8VkX7SDM0=
+k8s.io/apimachinery v0.23.5/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM=
 k8s.io/apiserver v0.23.4/go.mod h1:A6l/ZcNtxGfPSqbFDoxxOjEjSKBaQmE+UTveOmMkpNc=
-k8s.io/client-go v0.23.4 h1:YVWvPeerA2gpUudLelvsolzH7c2sFoXXR5wM/sWqNFU=
 k8s.io/client-go v0.23.4/go.mod h1:PKnIL4pqLuvYUK1WU7RLTMYKPiIh7MYShLshtRY9cj0=
-k8s.io/code-generator v0.23.4 h1:MmDMH74oo8YD4r+KdUzd/VVmXUeXf5u0owLI9wZWP5Y=
+k8s.io/client-go v0.23.5 h1:zUXHmEuqx0RY4+CsnkOn5l0GU+skkRXKGJrhmE2SLd8=
+k8s.io/client-go v0.23.5/go.mod h1:flkeinTO1CirYgzMPRWxUCnV0G4Fbu2vLhYCObnt/r4=
 k8s.io/code-generator v0.23.4/go.mod h1:S0Q1JVA+kSzTI1oUvbKAxZY/DYbA/ZUb4Uknog12ETk=
+k8s.io/code-generator v0.23.5 h1:xn3a6J5pUL49AoH6SPrOFtnB5cvdMl76f/bEY176R3c=
+k8s.io/code-generator v0.23.5/go.mod h1:S0Q1JVA+kSzTI1oUvbKAxZY/DYbA/ZUb4Uknog12ETk=
 k8s.io/component-base v0.23.4/go.mod h1:8o3Gg8i2vnUXGPOwciiYlkSaZT+p+7gA9Scoz8y4W4E=
 k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
 k8s.io/gengo v0.0.0-20220307231824-4627b89bbf1b h1:vEhKDJESYfeRiaBNmRvO+/12RAo1cFeu6vGm1fBFY34=
@@ -1179,8 +1183,8 @@ k8s.io/gengo v0.0.0-20220307231824-4627b89bbf1b/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAE
 k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
 k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
 k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
-k8s.io/klog/v2 v2.40.2-0.20220227211518-7ea6d6adb645 h1:9ralYm+Xufh/NgewZj+kGEkERlOA9bfSbpvxt9bLrUg=
-k8s.io/klog/v2 v2.40.2-0.20220227211518-7ea6d6adb645/go.mod h1:N3kgBtsFxMb4nQ0eBDgbHEt/dtxBuTkSFQ+7K5OUoz4=
+k8s.io/klog/v2 v2.60.1-0.20220317184644-43cc75f9ae89 h1:bUNlsw5yb353zbKMj8srOr6V2Ajhz1VkTKonP1L8r2o=
+k8s.io/klog/v2 v2.60.1-0.20220317184644-43cc75f9ae89/go.mod h1:N3kgBtsFxMb4nQ0eBDgbHEt/dtxBuTkSFQ+7K5OUoz4=
 k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 h1:E3J9oCLlaobFUqsjG9DfKbP2BmgwBL2p7pn0A3dG9W4=
 k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk=
 k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
diff --git a/leaderelection/context.go b/leaderelection/context.go
index 4e4c46a47..9e4a91822 100644
--- a/leaderelection/context.go
+++ b/leaderelection/context.go
@@ -80,6 +80,12 @@ type Elector interface {
 	Run(context.Context)
 }
 
+// ElectorWithInitialBuckets is an optional interface for electors to
+// supply an initial set of buckets
+type ElectorWithInitialBuckets interface {
+	InitialBuckets() []reconciler.Bucket
+}
+
 // BuildElector builds a leaderelection.LeaderElector for the named LeaderAware
 // reconciler using a builder added to the context via WithStandardLeaderElectorBuilder.
 func BuildElector(ctx context.Context, la reconciler.LeaderAware, queueName string, enq func(reconciler.Bucket, types.NamespacedName)) (Elector, error) {
@@ -255,11 +261,22 @@ type unopposedElector struct {
 	enq func(reconciler.Bucket, types.NamespacedName)
 }
 
+var (
+	_ Elector                   = (*unopposedElector)(nil)
+	_ ElectorWithInitialBuckets = (*unopposedElector)(nil)
+)
+
 // Run implements Elector
 func (ue *unopposedElector) Run(ctx context.Context) {
 	ue.la.Promote(ue.bkt, ue.enq)
 }
 
+func (ue *unopposedElector) InitialBuckets() []reconciler.Bucket {
+	return []reconciler.Bucket{
+		reconciler.UniversalBucket(),
+	}
+}
+
 type runAll struct {
 	les []Elector
 }
diff --git a/vendor/k8s.io/api/policy/v1beta1/generated.proto b/vendor/k8s.io/api/policy/v1beta1/generated.proto
index 133ba0493..8a2824b51 100644
--- a/vendor/k8s.io/api/policy/v1beta1/generated.proto
+++ b/vendor/k8s.io/api/policy/v1beta1/generated.proto
@@ -144,7 +144,6 @@ message PodDisruptionBudgetSpec {
   // A null selector selects no pods.
   // An empty selector ({}) also selects no pods, which differs from standard behavior of selecting all pods.
   // In policy/v1, an empty selector will select all pods in the namespace.
-  // +patchStrategy=replace
   // +optional
   optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 2;
 
diff --git a/vendor/k8s.io/api/policy/v1beta1/types.go b/vendor/k8s.io/api/policy/v1beta1/types.go
index 553cb316d..486f93461 100644
--- a/vendor/k8s.io/api/policy/v1beta1/types.go
+++ b/vendor/k8s.io/api/policy/v1beta1/types.go
@@ -36,9 +36,8 @@ type PodDisruptionBudgetSpec struct {
 	// A null selector selects no pods.
 	// An empty selector ({}) also selects no pods, which differs from standard behavior of selecting all pods.
 	// In policy/v1, an empty selector will select all pods in the namespace.
-	// +patchStrategy=replace
 	// +optional
-	Selector *metav1.LabelSelector `json:"selector,omitempty" patchStrategy:"replace" protobuf:"bytes,2,opt,name=selector"`
+	Selector *metav1.LabelSelector `json:"selector,omitempty" protobuf:"bytes,2,opt,name=selector"`
 
 	// An eviction is allowed if at most "maxUnavailable" pods selected by
 	// "selector" are unavailable after the eviction, i.e. even in absence of
diff --git a/vendor/k8s.io/klog/v2/contextual.go b/vendor/k8s.io/klog/v2/contextual.go
new file mode 100644
index 000000000..33743ffb8
--- /dev/null
+++ b/vendor/k8s.io/klog/v2/contextual.go
@@ -0,0 +1,252 @@
+/*
+Copyright 2021 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package klog
+
+import (
+	"context"
+
+	"github.com/go-logr/logr"
+)
+
+// This file provides the implementation of
+// https://github.com/kubernetes/enhancements/tree/master/keps/sig-instrumentation/1602-structured-logging
+//
+// SetLogger and ClearLogger were originally added to klog.go and got moved
+// here. Contextual logging adds a way to retrieve a Logger for direct logging
+// without the logging calls in klog.go.
+//
+// The global variables are expected to be modified only during sequential
+// parts of a program (init, serial tests) and therefore are not protected by
+// mutex locking.
+
+var (
+	// contextualLoggingEnabled controls whether contextual logging is
+	// active. Disabling it may have some small performance benefit.
+	contextualLoggingEnabled = true
+
+	// globalLogger is the global Logger chosen by users of klog, nil if
+	// none is available.
+	globalLogger *Logger
+
+	// globalLoggerOptions contains the options that were supplied for
+	// globalLogger.
+	globalLoggerOptions loggerOptions
+
+	// klogLogger is used as fallback for logging through the normal klog code
+	// when no Logger is set.
+	klogLogger logr.Logger = logr.New(&klogger{})
+)
+
+// SetLogger sets a Logger implementation that will be used as backing
+// implementation of the traditional klog log calls. klog will do its own
+// verbosity checks before calling logger.V().Info. logger.Error is always
+// called, regardless of the klog verbosity settings.
+//
+// If set, all log lines will be suppressed from the regular output, and
+// redirected to the logr implementation.
+// Use as:
+//   ...
+//   klog.SetLogger(zapr.NewLogger(zapLog))
+//
+// To remove a backing logr implemention, use ClearLogger. Setting an
+// empty logger with SetLogger(logr.Logger{}) does not work.
+//
+// Modifying the logger is not thread-safe and should be done while no other
+// goroutines invoke log calls, usually during program initialization.
+func SetLogger(logger logr.Logger) {
+	SetLoggerWithOptions(logger)
+}
+
+// SetLoggerWithOptions is a more flexible version of SetLogger. Without
+// additional options, it behaves exactly like SetLogger. By passing
+// ContextualLogger(true) as option, it can be used to set a logger that then
+// will also get called directly by applications which retrieve it via
+// FromContext, Background, or TODO.
+//
+// Supporting direct calls is recommended because it avoids the overhead of
+// routing log entries through klogr into klog and then into the actual Logger
+// backend.
+//
+// Experimental
+//
+// Notice: This function is EXPERIMENTAL and may be changed or removed in a
+// later release.
+func SetLoggerWithOptions(logger logr.Logger, opts ...LoggerOption) {
+	globalLogger = &logger
+	globalLoggerOptions = loggerOptions{}
+	for _, opt := range opts {
+		opt(&globalLoggerOptions)
+	}
+}
+
+// ContextualLogger determines whether the logger passed to
+// SetLoggerWithOptions may also get called directly. Such a logger cannot rely
+// on verbosity checking in klog.
+//
+// Experimental
+//
+// Notice: This function is EXPERIMENTAL and may be changed or removed in a
+// later release.
+func ContextualLogger(enabled bool) LoggerOption {
+	return func(o *loggerOptions) {
+		o.contextualLogger = enabled
+	}
+}
+
+// FlushLogger provides a callback for flushing data buffered by the logger.
+//
+// Experimental
+//
+// Notice: This function is EXPERIMENTAL and may be changed or removed in a
+// later release.
+func FlushLogger(flush func()) LoggerOption {
+	return func(o *loggerOptions) {
+		o.flush = flush
+	}
+}
+
+// LoggerOption implements the functional parameter paradigm for
+// SetLoggerWithOptions.
+//
+// Experimental
+//
+// Notice: This type is EXPERIMENTAL and may be changed or removed in a
+// later release.
+type LoggerOption func(o *loggerOptions)
+
+type loggerOptions struct {
+	contextualLogger bool
+	flush            func()
+}
+
+// ClearLogger removes a backing Logger implementation if one was set earlier
+// with SetLogger.
+//
+// Modifying the logger is not thread-safe and should be done while no other
+// goroutines invoke log calls, usually during program initialization.
+func ClearLogger() {
+	globalLogger = nil
+	globalLoggerOptions = loggerOptions{}
+}
+
+// EnableContextualLogging controls whether contextual logging is enabled.
+// By default it is enabled. When disabled, FromContext avoids looking up
+// the logger in the context and always returns the global logger.
+// LoggerWithValues, LoggerWithName, and NewContext become no-ops
+// and return their input logger respectively context. This may be useful
+// to avoid the additional overhead for contextual logging.
+//
+// This must be called during initialization before goroutines are started.
+//
+// Experimental
+//
+// Notice: This function is EXPERIMENTAL and may be changed or removed in a
+// later release.
+func EnableContextualLogging(enabled bool) {
+	contextualLoggingEnabled = enabled
+}
+
+// FromContext retrieves a logger set by the caller or, if not set,
+// falls back to the program's global logger (a Logger instance or klog
+// itself).
+//
+// Experimental
+//
+// Notice: This function is EXPERIMENTAL and may be changed or removed in a
+// later release.
+func FromContext(ctx context.Context) Logger {
+	if contextualLoggingEnabled {
+		if logger, err := logr.FromContext(ctx); err == nil {
+			return logger
+		}
+	}
+
+	return Background()
+}
+
+// TODO can be used as a last resort by code that has no means of
+// receiving a logger from its caller. FromContext or an explicit logger
+// parameter should be used instead.
+//
+// Experimental
+//
+// Notice: This function is EXPERIMENTAL and may be changed or removed in a
+// later release.
+func TODO() Logger {
+	return Background()
+}
+
+// Background retrieves the fallback logger. It should not be called before
+// that logger was initialized by the program and not by code that should
+// better receive a logger via its parameters. TODO can be used as a temporary
+// solution for such code.
+//
+// Experimental
+//
+// Notice: This function is EXPERIMENTAL and may be changed or removed in a
+// later release.
+func Background() Logger {
+	if globalLoggerOptions.contextualLogger {
+		// Is non-nil because globalLoggerOptions.contextualLogger is
+		// only true if a logger was set.
+		return *globalLogger
+	}
+
+	return klogLogger
+}
+
+// LoggerWithValues returns logger.WithValues(...kv) when
+// contextual logging is enabled, otherwise the logger.
+//
+// Experimental
+//
+// Notice: This function is EXPERIMENTAL and may be changed or removed in a
+// later release.
+func LoggerWithValues(logger Logger, kv ...interface{}) Logger {
+	if contextualLoggingEnabled {
+		return logger.WithValues(kv...)
+	}
+	return logger
+}
+
+// LoggerWithName returns logger.WithName(name) when contextual logging is
+// enabled, otherwise the logger.
+//
+// Experimental
+//
+// Notice: This function is EXPERIMENTAL and may be changed or removed in a
+// later release.
+func LoggerWithName(logger Logger, name string) Logger {
+	if contextualLoggingEnabled {
+		return logger.WithName(name)
+	}
+	return logger
+}
+
+// NewContext returns logr.NewContext(ctx, logger) when
+// contextual logging is enabled, otherwise ctx.
+//
+// Experimental
+//
+// Notice: This function is EXPERIMENTAL and may be changed or removed in a
+// later release.
+func NewContext(ctx context.Context, logger Logger) context.Context {
+	if contextualLoggingEnabled {
+		return logr.NewContext(ctx, logger)
+	}
+	return ctx
+}
diff --git a/vendor/k8s.io/klog/v2/exit.go b/vendor/k8s.io/klog/v2/exit.go
new file mode 100644
index 000000000..320a14772
--- /dev/null
+++ b/vendor/k8s.io/klog/v2/exit.go
@@ -0,0 +1,69 @@
+// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/
+//
+// Copyright 2013 Google Inc. All Rights Reserved.
+// Copyright 2022 The Kubernetes Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package klog
+
+import (
+	"fmt"
+	"os"
+	"time"
+)
+
+var (
+
+	// ExitFlushTimeout is the timeout that klog has traditionally used during
+	// calls like Fatal or Exit when flushing log data right before exiting.
+	// Applications that replace those calls and do not have some specific
+	// requirements like "exit immediately" can use this value as parameter
+	// for FlushAndExit.
+	//
+	// Can be set for testing purpose or to change the application's
+	// default.
+	ExitFlushTimeout = 10 * time.Second
+
+	// OsExit is the function called by FlushAndExit to terminate the program.
+	//
+	// Can be set for testing purpose or to change the application's
+	// default behavior. Note that the function should not simply return
+	// because callers of functions like Fatal will not expect that.
+	OsExit = os.Exit
+)
+
+// FlushAndExit flushes log data for a certain amount of time and then calls
+// os.Exit. Combined with some logging call it provides a replacement for
+// traditional calls like Fatal or Exit.
+func FlushAndExit(flushTimeout time.Duration, exitCode int) {
+	timeoutFlush(flushTimeout)
+	OsExit(exitCode)
+}
+
+// timeoutFlush calls Flush and returns when it completes or after timeout
+// elapses, whichever happens first.  This is needed because the hooks invoked
+// by Flush may deadlock when klog.Fatal is called from a hook that holds
+// a lock. Flushing also might take too long.
+func timeoutFlush(timeout time.Duration) {
+	done := make(chan bool, 1)
+	go func() {
+		Flush() // calls logging.lockAndFlushAll()
+		done <- true
+	}()
+	select {
+	case <-done:
+	case <-time.After(timeout):
+		fmt.Fprintln(os.Stderr, "klog: Flush took longer than", timeout)
+	}
+}
diff --git a/vendor/k8s.io/klog/v2/imports.go b/vendor/k8s.io/klog/v2/imports.go
new file mode 100644
index 000000000..43cd08190
--- /dev/null
+++ b/vendor/k8s.io/klog/v2/imports.go
@@ -0,0 +1,58 @@
+/*
+Copyright 2021 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package klog
+
+import (
+	"github.com/go-logr/logr"
+)
+
+// The reason for providing these aliases is to allow code to work with logr
+// without directly importing it.
+
+// Logger in this package is exactly the same as logr.Logger.
+//
+// Experimental
+//
+// Notice: This type is EXPERIMENTAL and may be changed or removed in a
+// later release.
+type Logger = logr.Logger
+
+// LogSink in this package is exactly the same as logr.LogSink.
+//
+// Experimental
+//
+// Notice: This type is EXPERIMENTAL and may be changed or removed in a
+// later release.
+type LogSink = logr.LogSink
+
+// Runtimeinfo in this package is exactly the same as logr.RuntimeInfo.
+//
+// Experimental
+//
+// Notice: This type is EXPERIMENTAL and may be changed or removed in a
+// later release.
+type RuntimeInfo = logr.RuntimeInfo
+
+var (
+	// New is an alias for logr.New.
+	//
+	// Experimental
+	//
+	// Notice: This variable is EXPERIMENTAL and may be changed or removed in a
+	// later release.
+	New = logr.New
+)
diff --git a/vendor/k8s.io/klog/v2/k8s_references.go b/vendor/k8s.io/klog/v2/k8s_references.go
new file mode 100644
index 000000000..db58f8baa
--- /dev/null
+++ b/vendor/k8s.io/klog/v2/k8s_references.go
@@ -0,0 +1,94 @@
+/*
+Copyright 2021 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package klog
+
+import (
+	"fmt"
+	"reflect"
+
+	"github.com/go-logr/logr"
+)
+
+// ObjectRef references a kubernetes object
+type ObjectRef struct {
+	Name      string `json:"name"`
+	Namespace string `json:"namespace,omitempty"`
+}
+
+func (ref ObjectRef) String() string {
+	if ref.Namespace != "" {
+		return fmt.Sprintf("%s/%s", ref.Namespace, ref.Name)
+	}
+	return ref.Name
+}
+
+// MarshalLog ensures that loggers with support for structured output will log
+// as a struct by removing the String method via a custom type.
+func (ref ObjectRef) MarshalLog() interface{} {
+	type or ObjectRef
+	return or(ref)
+}
+
+var _ logr.Marshaler = ObjectRef{}
+
+// KMetadata is a subset of the kubernetes k8s.io/apimachinery/pkg/apis/meta/v1.Object interface
+// this interface may expand in the future, but will always be a subset of the
+// kubernetes k8s.io/apimachinery/pkg/apis/meta/v1.Object interface
+type KMetadata interface {
+	GetName() string
+	GetNamespace() string
+}
+
+// KObj returns ObjectRef from ObjectMeta
+func KObj(obj KMetadata) ObjectRef {
+	if obj == nil {
+		return ObjectRef{}
+	}
+	if val := reflect.ValueOf(obj); val.Kind() == reflect.Ptr && val.IsNil() {
+		return ObjectRef{}
+	}
+
+	return ObjectRef{
+		Name:      obj.GetName(),
+		Namespace: obj.GetNamespace(),
+	}
+}
+
+// KRef returns ObjectRef from name and namespace
+func KRef(namespace, name string) ObjectRef {
+	return ObjectRef{
+		Name:      name,
+		Namespace: namespace,
+	}
+}
+
+// KObjs returns slice of ObjectRef from an slice of ObjectMeta
+func KObjs(arg interface{}) []ObjectRef {
+	s := reflect.ValueOf(arg)
+	if s.Kind() != reflect.Slice {
+		return nil
+	}
+	objectRefs := make([]ObjectRef, 0, s.Len())
+	for i := 0; i < s.Len(); i++ {
+		if v, ok := s.Index(i).Interface().(KMetadata); ok {
+			objectRefs = append(objectRefs, KObj(v))
+		} else {
+			return nil
+		}
+	}
+	return objectRefs
+}
diff --git a/vendor/k8s.io/klog/v2/klog.go b/vendor/k8s.io/klog/v2/klog.go
index 0b235f42f..bb6f64be4 100644
--- a/vendor/k8s.io/klog/v2/klog.go
+++ b/vendor/k8s.io/klog/v2/klog.go
@@ -81,7 +81,6 @@ import (
 	"math"
 	"os"
 	"path/filepath"
-	"reflect"
 	"runtime"
 	"strconv"
 	"strings"
@@ -396,7 +395,7 @@ func init() {
 	logging.addDirHeader = false
 	logging.skipLogHeaders = false
 	logging.oneOutput = false
-	logging.flushD = newFlushDaemon(flushInterval, logging.lockAndFlushAll, nil)
+	logging.flushD = newFlushDaemon(logging.lockAndFlushAll, nil)
 }
 
 // InitFlags is for explicitly initializing the flags.
@@ -450,6 +449,9 @@ type loggingT struct {
 	file [severity.NumSeverity]flushSyncWriter
 	// flushD holds a flushDaemon that frequently flushes log file buffers.
 	flushD *flushDaemon
+	// flushInterval is the interval for periodic flushing. If zero,
+	// the global default will be used.
+	flushInterval time.Duration
 	// pcs is used in V to avoid an allocation when computing the caller's PC.
 	pcs [1]uintptr
 	// vmap is a cache of the V Level for each V() call site, identified by PC.
@@ -487,9 +489,6 @@ type loggingT struct {
 	// If true, add the file directory to the header
 	addDirHeader bool
 
-	// If set, all output will be redirected unconditionally to the provided logr.Logger
-	logr *logr.Logger
-
 	// If true, messages will not be propagated to lower severity log levels
 	oneOutput bool
 
@@ -689,7 +688,7 @@ func (l *loggingT) printS(err error, s severity.Severity, depth int, msg string,
 		serialize.KVListFormat(&b.Buffer, "err", err)
 	}
 	serialize.KVListFormat(&b.Buffer, keysAndValues...)
-	l.printDepth(s, logging.logr, nil, depth+1, &b.Buffer)
+	l.printDepth(s, globalLogger, nil, depth+1, &b.Buffer)
 	// Make the buffer available for reuse.
 	l.bufferCache.PutBuffer(b)
 }
@@ -711,34 +710,6 @@ func (rb *redirectBuffer) Write(bytes []byte) (n int, err error) {
 	return rb.w.Write(bytes)
 }
 
-// SetLogger will set the backing logr implementation for klog.
-// If set, all log lines will be suppressed from the regular Output, and
-// redirected to the logr implementation.
-// Use as:
-//   ...
-//   klog.SetLogger(zapr.NewLogger(zapLog))
-//
-// To remove a backing logr implemention, use ClearLogger. Setting an
-// empty logger with SetLogger(logr.Logger{}) does not work.
-//
-// Modifying the logger is not thread-safe and should be done while no other
-// goroutines invoke log calls, usually during program initialization.
-func SetLogger(logr logr.Logger) {
-	logging.logr = &logr
-}
-
-// ClearLogger removes a backing logr implementation if one was set earlier
-// with SetLogger.
-//
-// Modifying the logger is not thread-safe and should be done while no other
-// goroutines invoke log calls, usually during program initialization.
-func ClearLogger() {
-	logging.mu.Lock()
-	defer logging.mu.Unlock()
-
-	logging.logr = nil
-}
-
 // SetOutput sets the output destination for all severities
 func SetOutput(w io.Writer) {
 	logging.mu.Lock()
@@ -794,7 +765,7 @@ func (l *loggingT) output(s severity.Severity, log *logr.Logger, buf *buffer.Buf
 		// TODO: set 'severity' and caller information as structured log info
 		// keysAndValues := []interface{}{"severity", severityName[s], "file", file, "line", line}
 		if s == severity.ErrorLog {
-			logging.logr.WithCallDepth(depth+3).Error(nil, string(data))
+			globalLogger.WithCallDepth(depth+3).Error(nil, string(data))
 		} else {
 			log.WithCallDepth(depth + 3).Info(string(data))
 		}
@@ -847,8 +818,8 @@ func (l *loggingT) output(s severity.Severity, log *logr.Logger, buf *buffer.Buf
 		if atomic.LoadUint32(&fatalNoStacks) > 0 {
 			l.mu.Unlock()
 			isLocked = false
-			timeoutFlush(10 * time.Second)
-			os.Exit(1)
+			timeoutFlush(ExitFlushTimeout)
+			OsExit(1)
 		}
 		// Dump all goroutine stacks before exiting.
 		trace := stacks(true)
@@ -865,8 +836,8 @@ func (l *loggingT) output(s severity.Severity, log *logr.Logger, buf *buffer.Buf
 		}
 		l.mu.Unlock()
 		isLocked = false
-		timeoutFlush(10 * time.Second)
-		os.Exit(255) // C++ uses -1, which is silly because it's anded(&) with 255 anyway.
+		timeoutFlush(ExitFlushTimeout)
+		OsExit(255) // C++ uses -1, which is silly because it's anded with 255 anyway.
 	}
 	l.bufferCache.PutBuffer(buf)
 
@@ -876,23 +847,6 @@ func (l *loggingT) output(s severity.Severity, log *logr.Logger, buf *buffer.Buf
 	}
 }
 
-// timeoutFlush calls Flush and returns when it completes or after timeout
-// elapses, whichever happens first.  This is needed because the hooks invoked
-// by Flush may deadlock when klog.Fatal is called from a hook that holds
-// a lock.
-func timeoutFlush(timeout time.Duration) {
-	done := make(chan bool, 1)
-	go func() {
-		Flush() // calls logging.lockAndFlushAll()
-		done <- true
-	}()
-	select {
-	case <-done:
-	case <-time.After(timeout):
-		fmt.Fprintln(os.Stderr, "klog: Flush took longer than", timeout)
-	}
-}
-
 // stacks is a wrapper for runtime.Stack that attempts to recover the data for all goroutines.
 func stacks(all bool) []byte {
 	// We don't know how big the traces are, so grow a few times if they don't fit. Start large, though.
@@ -929,7 +883,7 @@ func (l *loggingT) exit(err error) {
 		return
 	}
 	l.flushAll()
-	os.Exit(2)
+	OsExit(2)
 }
 
 // syncBuffer joins a bufio.Writer to its underlying file, providing access to the
@@ -1025,7 +979,11 @@ const bufferSize = 256 * 1024
 // createFiles creates all the log files for severity from sev down to infoLog.
 // l.mu is held.
 func (l *loggingT) createFiles(sev severity.Severity) error {
-	l.flushD.run()
+	interval := l.flushInterval
+	if interval == 0 {
+		interval = flushInterval
+	}
+	l.flushD.run(interval)
 	now := time.Now()
 	// Files are created in decreasing severity order, so as soon as we find one
 	// has already been created, we can stop.
@@ -1049,7 +1007,6 @@ const flushInterval = 5 * time.Second
 type flushDaemon struct {
 	mu       sync.Mutex
 	clock    clock.WithTicker
-	interval time.Duration
 	flush    func()
 	stopC    chan struct{}
 	stopDone chan struct{}
@@ -1057,20 +1014,19 @@ type flushDaemon struct {
 
 // newFlushDaemon returns a new flushDaemon. If the passed clock is nil, a
 // clock.RealClock is used.
-func newFlushDaemon(interval time.Duration, flush func(), tickClock clock.WithTicker) *flushDaemon {
+func newFlushDaemon(flush func(), tickClock clock.WithTicker) *flushDaemon {
 	if tickClock == nil {
 		tickClock = clock.RealClock{}
 	}
 	return &flushDaemon{
-		interval: interval,
-		flush:    flush,
-		clock:    tickClock,
+		flush: flush,
+		clock: tickClock,
 	}
 }
 
 // run starts a goroutine that periodically calls the daemons flush function.
 // Calling run on an already running daemon will have no effect.
-func (f *flushDaemon) run() {
+func (f *flushDaemon) run(interval time.Duration) {
 	f.mu.Lock()
 	defer f.mu.Unlock()
 
@@ -1081,7 +1037,7 @@ func (f *flushDaemon) run() {
 	f.stopC = make(chan struct{}, 1)
 	f.stopDone = make(chan struct{}, 1)
 
-	ticker := f.clock.NewTicker(f.interval)
+	ticker := f.clock.NewTicker(interval)
 	go func() {
 		defer ticker.Stop()
 		defer func() { f.stopDone <- struct{}{} }()
@@ -1128,6 +1084,13 @@ func StopFlushDaemon() {
 	logging.flushD.stop()
 }
 
+// StartFlushDaemon ensures that the flush daemon runs with the given delay
+// between flush calls. If it is already running, it gets restarted.
+func StartFlushDaemon(interval time.Duration) {
+	StopFlushDaemon()
+	logging.flushD.run(interval)
+}
+
 // lockAndFlushAll is like flushAll but locks l.mu first.
 func (l *loggingT) lockAndFlushAll() {
 	l.mu.Lock()
@@ -1146,6 +1109,9 @@ func (l *loggingT) flushAll() {
 			file.Sync()  // ignore error
 		}
 	}
+	if globalLoggerOptions.flush != nil {
+		globalLoggerOptions.flush()
+	}
 }
 
 // CopyStandardLogTo arranges for messages written to the Go "log" package's
@@ -1192,7 +1158,7 @@ func (lb logBridge) Write(b []byte) (n int, err error) {
 	}
 	// printWithFileLine with alsoToStderr=true, so standard log messages
 	// always appear on standard error.
-	logging.printWithFileLine(severity.Severity(lb), logging.logr, logging.filter, file, line, true, text)
+	logging.printWithFileLine(severity.Severity(lb), globalLogger, logging.filter, file, line, true, text)
 	return len(b), nil
 }
 
@@ -1230,10 +1196,10 @@ type Verbose struct {
 }
 
 func newVerbose(level Level, b bool) Verbose {
-	if logging.logr == nil {
+	if globalLogger == nil {
 		return Verbose{b, nil}
 	}
-	v := logging.logr.V(int(level))
+	v := globalLogger.V(int(level))
 	return Verbose{b, &v}
 }
 
@@ -1352,7 +1318,7 @@ func (v Verbose) InfoS(msg string, keysAndValues ...interface{}) {
 // InfoSDepth acts as InfoS but uses depth to determine which call frame to log.
 // InfoSDepth(0, "msg") is the same as InfoS("msg").
 func InfoSDepth(depth int, msg string, keysAndValues ...interface{}) {
-	logging.infoS(logging.logr, logging.filter, depth, msg, keysAndValues...)
+	logging.infoS(globalLogger, logging.filter, depth, msg, keysAndValues...)
 }
 
 // InfoSDepth is equivalent to the global InfoSDepth function, guarded by the value of v.
@@ -1381,37 +1347,37 @@ func (v Verbose) ErrorS(err error, msg string, keysAndValues ...interface{}) {
 // Info logs to the INFO log.
 // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
 func Info(args ...interface{}) {
-	logging.print(severity.InfoLog, logging.logr, logging.filter, args...)
+	logging.print(severity.InfoLog, globalLogger, logging.filter, args...)
 }
 
 // InfoDepth acts as Info but uses depth to determine which call frame to log.
 // InfoDepth(0, "msg") is the same as Info("msg").
 func InfoDepth(depth int, args ...interface{}) {
-	logging.printDepth(severity.InfoLog, logging.logr, logging.filter, depth, args...)
+	logging.printDepth(severity.InfoLog, globalLogger, logging.filter, depth, args...)
 }
 
 // Infoln logs to the INFO log.
 // Arguments are handled in the manner of fmt.Println; a newline is always appended.
 func Infoln(args ...interface{}) {
-	logging.println(severity.InfoLog, logging.logr, logging.filter, args...)
+	logging.println(severity.InfoLog, globalLogger, logging.filter, args...)
 }
 
 // InfolnDepth acts as Infoln but uses depth to determine which call frame to log.
 // InfolnDepth(0, "msg") is the same as Infoln("msg").
 func InfolnDepth(depth int, args ...interface{}) {
-	logging.printlnDepth(severity.InfoLog, logging.logr, logging.filter, depth, args...)
+	logging.printlnDepth(severity.InfoLog, globalLogger, logging.filter, depth, args...)
 }
 
 // Infof logs to the INFO log.
 // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
 func Infof(format string, args ...interface{}) {
-	logging.printf(severity.InfoLog, logging.logr, logging.filter, format, args...)
+	logging.printf(severity.InfoLog, globalLogger, logging.filter, format, args...)
 }
 
 // InfofDepth acts as Infof but uses depth to determine which call frame to log.
 // InfofDepth(0, "msg", args...) is the same as Infof("msg", args...).
 func InfofDepth(depth int, format string, args ...interface{}) {
-	logging.printfDepth(severity.InfoLog, logging.logr, logging.filter, depth, format, args...)
+	logging.printfDepth(severity.InfoLog, globalLogger, logging.filter, depth, format, args...)
 }
 
 // InfoS structured logs to the INFO log.
@@ -1423,79 +1389,79 @@ func InfofDepth(depth int, format string, args ...interface{}) {
 // output:
 // >> I1025 00:15:15.525108       1 controller_utils.go:116] "Pod status updated" pod="kubedns" status="ready"
 func InfoS(msg string, keysAndValues ...interface{}) {
-	logging.infoS(logging.logr, logging.filter, 0, msg, keysAndValues...)
+	logging.infoS(globalLogger, logging.filter, 0, msg, keysAndValues...)
 }
 
 // Warning logs to the WARNING and INFO logs.
 // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
 func Warning(args ...interface{}) {
-	logging.print(severity.WarningLog, logging.logr, logging.filter, args...)
+	logging.print(severity.WarningLog, globalLogger, logging.filter, args...)
 }
 
 // WarningDepth acts as Warning but uses depth to determine which call frame to log.
 // WarningDepth(0, "msg") is the same as Warning("msg").
 func WarningDepth(depth int, args ...interface{}) {
-	logging.printDepth(severity.WarningLog, logging.logr, logging.filter, depth, args...)
+	logging.printDepth(severity.WarningLog, globalLogger, logging.filter, depth, args...)
 }
 
 // Warningln logs to the WARNING and INFO logs.
 // Arguments are handled in the manner of fmt.Println; a newline is always appended.
 func Warningln(args ...interface{}) {
-	logging.println(severity.WarningLog, logging.logr, logging.filter, args...)
+	logging.println(severity.WarningLog, globalLogger, logging.filter, args...)
 }
 
 // WarninglnDepth acts as Warningln but uses depth to determine which call frame to log.
 // WarninglnDepth(0, "msg") is the same as Warningln("msg").
 func WarninglnDepth(depth int, args ...interface{}) {
-	logging.printlnDepth(severity.WarningLog, logging.logr, logging.filter, depth, args...)
+	logging.printlnDepth(severity.WarningLog, globalLogger, logging.filter, depth, args...)
 }
 
 // Warningf logs to the WARNING and INFO logs.
 // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
 func Warningf(format string, args ...interface{}) {
-	logging.printf(severity.WarningLog, logging.logr, logging.filter, format, args...)
+	logging.printf(severity.WarningLog, globalLogger, logging.filter, format, args...)
 }
 
 // WarningfDepth acts as Warningf but uses depth to determine which call frame to log.
 // WarningfDepth(0, "msg", args...) is the same as Warningf("msg", args...).
 func WarningfDepth(depth int, format string, args ...interface{}) {
-	logging.printfDepth(severity.WarningLog, logging.logr, logging.filter, depth, format, args...)
+	logging.printfDepth(severity.WarningLog, globalLogger, logging.filter, depth, format, args...)
 }
 
 // Error logs to the ERROR, WARNING, and INFO logs.
 // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
 func Error(args ...interface{}) {
-	logging.print(severity.ErrorLog, logging.logr, logging.filter, args...)
+	logging.print(severity.ErrorLog, globalLogger, logging.filter, args...)
 }
 
 // ErrorDepth acts as Error but uses depth to determine which call frame to log.
 // ErrorDepth(0, "msg") is the same as Error("msg").
 func ErrorDepth(depth int, args ...interface{}) {
-	logging.printDepth(severity.ErrorLog, logging.logr, logging.filter, depth, args...)
+	logging.printDepth(severity.ErrorLog, globalLogger, logging.filter, depth, args...)
 }
 
 // Errorln logs to the ERROR, WARNING, and INFO logs.
 // Arguments are handled in the manner of fmt.Println; a newline is always appended.
 func Errorln(args ...interface{}) {
-	logging.println(severity.ErrorLog, logging.logr, logging.filter, args...)
+	logging.println(severity.ErrorLog, globalLogger, logging.filter, args...)
 }
 
 // ErrorlnDepth acts as Errorln but uses depth to determine which call frame to log.
 // ErrorlnDepth(0, "msg") is the same as Errorln("msg").
 func ErrorlnDepth(depth int, args ...interface{}) {
-	logging.printlnDepth(severity.ErrorLog, logging.logr, logging.filter, depth, args...)
+	logging.printlnDepth(severity.ErrorLog, globalLogger, logging.filter, depth, args...)
 }
 
 // Errorf logs to the ERROR, WARNING, and INFO logs.
 // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
 func Errorf(format string, args ...interface{}) {
-	logging.printf(severity.ErrorLog, logging.logr, logging.filter, format, args...)
+	logging.printf(severity.ErrorLog, globalLogger, logging.filter, format, args...)
 }
 
 // ErrorfDepth acts as Errorf but uses depth to determine which call frame to log.
 // ErrorfDepth(0, "msg", args...) is the same as Errorf("msg", args...).
 func ErrorfDepth(depth int, format string, args ...interface{}) {
-	logging.printfDepth(severity.ErrorLog, logging.logr, logging.filter, depth, format, args...)
+	logging.printfDepth(severity.ErrorLog, globalLogger, logging.filter, depth, format, args...)
 }
 
 // ErrorS structured logs to the ERROR, WARNING, and INFO logs.
@@ -1508,97 +1474,97 @@ func ErrorfDepth(depth int, format string, args ...interface{}) {
 // output:
 // >> E1025 00:15:15.525108       1 controller_utils.go:114] "Failed to update pod status" err="timeout"
 func ErrorS(err error, msg string, keysAndValues ...interface{}) {
-	logging.errorS(err, logging.logr, logging.filter, 0, msg, keysAndValues...)
+	logging.errorS(err, globalLogger, logging.filter, 0, msg, keysAndValues...)
 }
 
 // ErrorSDepth acts as ErrorS but uses depth to determine which call frame to log.
 // ErrorSDepth(0, "msg") is the same as ErrorS("msg").
 func ErrorSDepth(depth int, err error, msg string, keysAndValues ...interface{}) {
-	logging.errorS(err, logging.logr, logging.filter, depth, msg, keysAndValues...)
+	logging.errorS(err, globalLogger, logging.filter, depth, msg, keysAndValues...)
 }
 
 // Fatal logs to the FATAL, ERROR, WARNING, and INFO logs,
-// including a stack trace of all running goroutines, then calls os.Exit(255).
+// including a stack trace of all running goroutines, then calls OsExit(255).
 // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
 func Fatal(args ...interface{}) {
-	logging.print(severity.FatalLog, logging.logr, logging.filter, args...)
+	logging.print(severity.FatalLog, globalLogger, logging.filter, args...)
 }
 
 // FatalDepth acts as Fatal but uses depth to determine which call frame to log.
 // FatalDepth(0, "msg") is the same as Fatal("msg").
 func FatalDepth(depth int, args ...interface{}) {
-	logging.printDepth(severity.FatalLog, logging.logr, logging.filter, depth, args...)
+	logging.printDepth(severity.FatalLog, globalLogger, logging.filter, depth, args...)
 }
 
 // Fatalln logs to the FATAL, ERROR, WARNING, and INFO logs,
-// including a stack trace of all running goroutines, then calls os.Exit(255).
+// including a stack trace of all running goroutines, then calls OsExit(255).
 // Arguments are handled in the manner of fmt.Println; a newline is always appended.
 func Fatalln(args ...interface{}) {
-	logging.println(severity.FatalLog, logging.logr, logging.filter, args...)
+	logging.println(severity.FatalLog, globalLogger, logging.filter, args...)
 }
 
 // FatallnDepth acts as Fatalln but uses depth to determine which call frame to log.
 // FatallnDepth(0, "msg") is the same as Fatalln("msg").
 func FatallnDepth(depth int, args ...interface{}) {
-	logging.printlnDepth(severity.FatalLog, logging.logr, logging.filter, depth, args...)
+	logging.printlnDepth(severity.FatalLog, globalLogger, logging.filter, depth, args...)
 }
 
 // Fatalf logs to the FATAL, ERROR, WARNING, and INFO logs,
-// including a stack trace of all running goroutines, then calls os.Exit(255).
+// including a stack trace of all running goroutines, then calls OsExit(255).
 // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
 func Fatalf(format string, args ...interface{}) {
-	logging.printf(severity.FatalLog, logging.logr, logging.filter, format, args...)
+	logging.printf(severity.FatalLog, globalLogger, logging.filter, format, args...)
 }
 
 // FatalfDepth acts as Fatalf but uses depth to determine which call frame to log.
 // FatalfDepth(0, "msg", args...) is the same as Fatalf("msg", args...).
 func FatalfDepth(depth int, format string, args ...interface{}) {
-	logging.printfDepth(severity.FatalLog, logging.logr, logging.filter, depth, format, args...)
+	logging.printfDepth(severity.FatalLog, globalLogger, logging.filter, depth, format, args...)
 }
 
 // fatalNoStacks is non-zero if we are to exit without dumping goroutine stacks.
 // It allows Exit and relatives to use the Fatal logs.
 var fatalNoStacks uint32
 
-// Exit logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1).
+// Exit logs to the FATAL, ERROR, WARNING, and INFO logs, then calls OsExit(1).
 // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
 func Exit(args ...interface{}) {
 	atomic.StoreUint32(&fatalNoStacks, 1)
-	logging.print(severity.FatalLog, logging.logr, logging.filter, args...)
+	logging.print(severity.FatalLog, globalLogger, logging.filter, args...)
 }
 
 // ExitDepth acts as Exit but uses depth to determine which call frame to log.
 // ExitDepth(0, "msg") is the same as Exit("msg").
 func ExitDepth(depth int, args ...interface{}) {
 	atomic.StoreUint32(&fatalNoStacks, 1)
-	logging.printDepth(severity.FatalLog, logging.logr, logging.filter, depth, args...)
+	logging.printDepth(severity.FatalLog, globalLogger, logging.filter, depth, args...)
 }
 
-// Exitln logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1).
+// Exitln logs to the FATAL, ERROR, WARNING, and INFO logs, then calls OsExit(1).
 func Exitln(args ...interface{}) {
 	atomic.StoreUint32(&fatalNoStacks, 1)
-	logging.println(severity.FatalLog, logging.logr, logging.filter, args...)
+	logging.println(severity.FatalLog, globalLogger, logging.filter, args...)
 }
 
 // ExitlnDepth acts as Exitln but uses depth to determine which call frame to log.
 // ExitlnDepth(0, "msg") is the same as Exitln("msg").
 func ExitlnDepth(depth int, args ...interface{}) {
 	atomic.StoreUint32(&fatalNoStacks, 1)
-	logging.printlnDepth(severity.FatalLog, logging.logr, logging.filter, depth, args...)
+	logging.printlnDepth(severity.FatalLog, globalLogger, logging.filter, depth, args...)
 }
 
-// Exitf logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1).
+// Exitf logs to the FATAL, ERROR, WARNING, and INFO logs, then calls OsExit(1).
 // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
 func Exitf(format string, args ...interface{}) {
 	atomic.StoreUint32(&fatalNoStacks, 1)
-	logging.printf(severity.FatalLog, logging.logr, logging.filter, format, args...)
+	logging.printf(severity.FatalLog, globalLogger, logging.filter, format, args...)
 }
 
 // ExitfDepth acts as Exitf but uses depth to determine which call frame to log.
 // ExitfDepth(0, "msg", args...) is the same as Exitf("msg", args...).
 func ExitfDepth(depth int, format string, args ...interface{}) {
 	atomic.StoreUint32(&fatalNoStacks, 1)
-	logging.printfDepth(severity.FatalLog, logging.logr, logging.filter, depth, format, args...)
+	logging.printfDepth(severity.FatalLog, globalLogger, logging.filter, depth, format, args...)
 }
 
 // LogFilter is a collection of functions that can filter all logging calls,
@@ -1616,73 +1582,3 @@ type LogFilter interface {
 func SetLogFilter(filter LogFilter) {
 	logging.filter = filter
 }
-
-// ObjectRef references a kubernetes object
-type ObjectRef struct {
-	Name      string `json:"name"`
-	Namespace string `json:"namespace,omitempty"`
-}
-
-func (ref ObjectRef) String() string {
-	if ref.Namespace != "" {
-		return fmt.Sprintf("%s/%s", ref.Namespace, ref.Name)
-	}
-	return ref.Name
-}
-
-// MarshalLog ensures that loggers with support for structured output will log
-// as a struct by removing the String method via a custom type.
-func (ref ObjectRef) MarshalLog() interface{} {
-	type or ObjectRef
-	return or(ref)
-}
-
-var _ logr.Marshaler = ObjectRef{}
-
-// KMetadata is a subset of the kubernetes k8s.io/apimachinery/pkg/apis/meta/v1.Object interface
-// this interface may expand in the future, but will always be a subset of the
-// kubernetes k8s.io/apimachinery/pkg/apis/meta/v1.Object interface
-type KMetadata interface {
-	GetName() string
-	GetNamespace() string
-}
-
-// KObj returns ObjectRef from ObjectMeta
-func KObj(obj KMetadata) ObjectRef {
-	if obj == nil {
-		return ObjectRef{}
-	}
-	if val := reflect.ValueOf(obj); val.Kind() == reflect.Ptr && val.IsNil() {
-		return ObjectRef{}
-	}
-
-	return ObjectRef{
-		Name:      obj.GetName(),
-		Namespace: obj.GetNamespace(),
-	}
-}
-
-// KRef returns ObjectRef from name and namespace
-func KRef(namespace, name string) ObjectRef {
-	return ObjectRef{
-		Name:      name,
-		Namespace: namespace,
-	}
-}
-
-// KObjs returns slice of ObjectRef from an slice of ObjectMeta
-func KObjs(arg interface{}) []ObjectRef {
-	s := reflect.ValueOf(arg)
-	if s.Kind() != reflect.Slice {
-		return nil
-	}
-	objectRefs := make([]ObjectRef, 0, s.Len())
-	for i := 0; i < s.Len(); i++ {
-		if v, ok := s.Index(i).Interface().(KMetadata); ok {
-			objectRefs = append(objectRefs, KObj(v))
-		} else {
-			return nil
-		}
-	}
-	return objectRefs
-}
diff --git a/vendor/k8s.io/klog/v2/klogr.go b/vendor/k8s.io/klog/v2/klogr.go
new file mode 100644
index 000000000..cdb3834fa
--- /dev/null
+++ b/vendor/k8s.io/klog/v2/klogr.go
@@ -0,0 +1,92 @@
+/*
+Copyright 2021 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package klog
+
+import (
+	"github.com/go-logr/logr"
+
+	"k8s.io/klog/v2/internal/serialize"
+)
+
+// NewKlogr returns a logger that is functionally identical to
+// klogr.NewWithOptions(klogr.FormatKlog), i.e. it passes through to klog. The
+// difference is that it uses a simpler implementation.
+//
+// Experimental
+//
+// Notice: This function is EXPERIMENTAL and may be changed or removed in a
+// later release.
+func NewKlogr() Logger {
+	return New(&klogger{})
+}
+
+// klogger is a subset of klogr/klogr.go. It had to be copied to break an
+// import cycle (klogr wants to use klog, and klog wants to use klogr).
+type klogger struct {
+	level     int
+	callDepth int
+	prefix    string
+	values    []interface{}
+}
+
+func (l *klogger) Init(info logr.RuntimeInfo) {
+	l.callDepth += info.CallDepth
+}
+
+func (l klogger) Info(level int, msg string, kvList ...interface{}) {
+	trimmed := serialize.TrimDuplicates(l.values, kvList)
+	if l.prefix != "" {
+		msg = l.prefix + ": " + msg
+	}
+	V(Level(level)).InfoSDepth(l.callDepth+1, msg, append(trimmed[0], trimmed[1]...)...)
+}
+
+func (l klogger) Enabled(level int) bool {
+	return V(Level(level)).Enabled()
+}
+
+func (l klogger) Error(err error, msg string, kvList ...interface{}) {
+	trimmed := serialize.TrimDuplicates(l.values, kvList)
+	if l.prefix != "" {
+		msg = l.prefix + ": " + msg
+	}
+	ErrorSDepth(l.callDepth+1, err, msg, append(trimmed[0], trimmed[1]...)...)
+}
+
+// WithName returns a new logr.Logger with the specified name appended.  klogr
+// uses '/' characters to separate name elements.  Callers should not pass '/'
+// in the provided name string, but this library does not actually enforce that.
+func (l klogger) WithName(name string) logr.LogSink {
+	if len(l.prefix) > 0 {
+		l.prefix = l.prefix + "/"
+	}
+	l.prefix += name
+	return &l
+}
+
+func (l klogger) WithValues(kvList ...interface{}) logr.LogSink {
+	l.values = serialize.WithValues(l.values, kvList)
+	return &l
+}
+
+func (l klogger) WithCallDepth(depth int) logr.LogSink {
+	l.callDepth += depth
+	return &l
+}
+
+var _ logr.LogSink = &klogger{}
+var _ logr.CallDepthLogSink = &klogger{}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 697dd45de..0dd1ccdb9 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -611,7 +611,7 @@ gopkg.in/yaml.v2
 # gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
 ## explicit
 gopkg.in/yaml.v3
-# k8s.io/api v0.23.4
+# k8s.io/api v0.23.5
 ## explicit; go 1.16
 k8s.io/api/admission/v1
 k8s.io/api/admissionregistration/v1
@@ -678,7 +678,7 @@ k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensio
 k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/internalinterfaces
 k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1
 k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1
-# k8s.io/apimachinery v0.23.4
+# k8s.io/apimachinery v0.23.5
 ## explicit; go 1.16
 k8s.io/apimachinery/pkg/api/apitesting
 k8s.io/apimachinery/pkg/api/apitesting/fuzzer
@@ -731,7 +731,7 @@ k8s.io/apimachinery/pkg/version
 k8s.io/apimachinery/pkg/watch
 k8s.io/apimachinery/third_party/forked/golang/json
 k8s.io/apimachinery/third_party/forked/golang/reflect
-# k8s.io/client-go v0.23.4
+# k8s.io/client-go v0.23.5
 ## explicit; go 1.16
 k8s.io/client-go/applyconfigurations/admissionregistration/v1
 k8s.io/client-go/applyconfigurations/admissionregistration/v1beta1
@@ -1007,7 +1007,7 @@ k8s.io/client-go/util/homedir
 k8s.io/client-go/util/keyutil
 k8s.io/client-go/util/retry
 k8s.io/client-go/util/workqueue
-# k8s.io/code-generator v0.23.4
+# k8s.io/code-generator v0.23.5
 ## explicit; go 1.16
 k8s.io/code-generator
 k8s.io/code-generator/cmd/client-gen
@@ -1054,7 +1054,7 @@ k8s.io/gengo/generator
 k8s.io/gengo/namer
 k8s.io/gengo/parser
 k8s.io/gengo/types
-# k8s.io/klog/v2 v2.40.2-0.20220227211518-7ea6d6adb645
+# k8s.io/klog/v2 v2.60.1-0.20220317184644-43cc75f9ae89
 ## explicit; go 1.13
 k8s.io/klog/v2
 k8s.io/klog/v2/internal/buffer


Test patch:
diff --git a/controller/controller_test.go b/controller/controller_test.go
index 6ce2e3dd0..e75be6469 100644
--- a/controller/controller_test.go
+++ b/controller/controller_test.go
@@ -920,11 +920,17 @@ func TestStartAndShutdown(t *testing.T) {
 type countingLeaderAwareReconciler struct {
 	reconciler.LeaderAwareFuncs
 
-	count atomic.Int32
+	reconcileCount atomic.Int32
+	promotionCount atomic.Int32
 }
 
 var _ reconciler.LeaderAware = (*countingLeaderAwareReconciler)(nil)
 
+func (cr *countingLeaderAwareReconciler) Promote(b reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error {
+	cr.promotionCount.Inc()
+	return cr.LeaderAwareFuncs.Promote(b, enq)
+}
+
 func (cr *countingLeaderAwareReconciler) Reconcile(ctx context.Context, key string) error {
 	namespace, name, err := cache.SplitMetaNamespaceKey(key)
 	if err != nil {
@@ -935,7 +941,7 @@ func (cr *countingLeaderAwareReconciler) Reconcile(ctx context.Context, key stri
 		Namespace: namespace,
 		Name:      name,
 	}) {
-		cr.count.Inc()
+		cr.reconcileCount.Inc()
 	}
 	return nil
 }
@@ -983,9 +989,22 @@ func TestStartAndShutdownWithLeaderAwareNoElection(t *testing.T) {
 		// We expect the work to complete.
 	}
 
-	if got, want := r.count.Load(), int32(0); got != want {
+	if got, want := r.reconcileCount.Load(), int32(0); got != want {
 		t.Errorf("reconcile count = %v, wanted %v", got, want)
 	}
+
+	// Since the elector can't easily be mocked we assume:
+	// 1. We are using the unopposed elector
+	// 2. It has a single initial bucket (the Universe)
+	//
+	// Thus we expect two promotions to occur
+	// 1. It provides the initial set of buckets and these are promoted
+	//    before reconciliation and leader election go routines start
+	// 2. When leader election starts the unopposed elector promotes
+	//    that same bucket again
+	if got, want := r.promotionCount.Load(), int32(2); got != want {
+		t.Errorf("promotion count = %v, wanted %v", got, want)
+	}
 }
 
 func TestStartAndShutdownWithLeaderAwareWithLostElection(t *testing.T) {
@@ -1055,7 +1074,7 @@ func TestStartAndShutdownWithLeaderAwareWithLostElection(t *testing.T) {
 		// We expect the work to complete.
 	}
 
-	if got, want := r.count.Load(), int32(0); got != want {
+	if got, want := r.reconcileCount.Load(), int32(0); got != want {
 		t.Errorf("reconcile count = %v, wanted %v", got, want)
 	}
 }
diff --git a/leaderelection/context_test.go b/leaderelection/context_test.go
index b54e8ffee..ab8878158 100644
--- a/leaderelection/context_test.go
+++ b/leaderelection/context_test.go
@@ -382,3 +382,10 @@ func TestStandardBucketName(t *testing.T) {
 		})
 	}
 }
+
+func TestUnopposedElectorInitialBucket(t *testing.T) {
+	u := &unopposedElector{}
+	if u.InitialBuckets()[0] != reconciler.UniversalBucket() {
+		t.Errorf("expected the unopposedElector to return the universal bucket")
+	}
+}