Repository: kyverno/kyverno
Pull request #1692 (2021-03-10 04:30:35)

Add certificate renewer in webhook registration controller
## Related issue

<!--
Please link the GitHub issue this pull request resolves in the format of `#1234`. If you discussed this change
with a maintainer, please mention her/him using the `@` syntax (e.g. `@JimBugwadia`).

If this change neither resolves an existing issue nor has sign-off from one of the maintainers, there is a
chance substantial changes will be requested or that the changes will be rejected.

You can discuss changes with maintainers in the [Kyverno Slack Channel](https://kubernetes.slack.com/).
-->

## What type of PR is this
/kind bug
/kind feature

This PR:
- fixes https://github.com/kyverno/kyverno/issues/1434
- fixes https://github.com/kyverno/kyverno/issues/1177
- fixes https://github.com/kyverno/kyverno/issues/1261
- eliminates throttling requests when registering webhook configurations, https://github.com/kyverno/kyverno/issues/1576#issuecomment-796360633.

In this PR, Kyverno is able to read CA cert from existing secret during start. With this, it is possible to scale up to multiple replicas. It also adds a certificate renewer to automatically renew Kyverno managed certificates. When the cert is renewed, Kyverno forces a rolling update to re-register webhook configurations and to re-create the webhook server.

To optimize webhook registration, webhook monitor, and cert renewal process, I will migrate webhook controller to use `controller-runtime` framework, with leader election enabled, and send it in a separate PR.

<!--

> Uncomment only one ` /kind <>` line, hit enter to put that in a new line, and remove leading whitespaces from that line:
>
> /kind api-change
> /kind bug
> /kind cleanup
> /kind design
> /kind documentation
> /kind failing-test
> /kind feature
-->


<!--
Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request.
-->

## Checklist

<!--
Put an `x` in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of
them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code.
-->

- [x] I have read the [contributing guidelines](https://github.com/kyverno/kyverno/blob/main/CONTRIBUTING.md).
- [] I have added tests that prove my fix is effective or that my feature works.
- [] I have added or changed [the documentation](https://github.com/kyverno/website).
  - If not, I have raised an issue in [kyverno/website](https://github.com/kyverno/website) to track the doc update: https://github.com/kyverno/website/issues/109.
  <!-- Uncomment to link to the issue -->
  <!-- https://github.com/kyverno/website/issues/1 -->

## Further comments

<!--
If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution
you did and what alternatives you considered, etc...
-->



Patch:
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 874b6e55e..6ee986481 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -41,6 +41,9 @@ them, don't hesitate to ask. We're here to help! This is simply a reminder of wh
 - [] I have read the [contributing guidelines](https://github.com/kyverno/kyverno/blob/main/CONTRIBUTING.md).
 - [] I have added tests that prove my fix is effective or that my feature works.
 - [] I have added or changed [the documentation](https://github.com/kyverno/website).
+  - If not, I have raised an issue in [kyverno/website](https://github.com/kyverno/website) to track the doc update:
+  <!-- Uncomment to link to the issue -->
+  <!-- https://github.com/kyverno/website/issues/1 -->
 
 ## Further comments
 
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index 196eb0e7a..66448fba3 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -43,6 +43,10 @@ jobs:
       - name: golangci-lint
         uses: reviewdog/action-golangci-lint@v1
 
+      - name: Checking unused pkgs using go mod tidy
+        run: |
+          make unused-package-check
+
   build-init-kyverno:
     runs-on: ubuntu-latest
     needs: pre-checks
diff --git a/.github/workflows/go.sum b/.github/workflows/go.sum
deleted file mode 100644
index e85a2f8b2..000000000
--- a/.github/workflows/go.sum
+++ /dev/null
@@ -1,40 +0,0 @@
-name: gosum
-
-on:
-  pull_request:
-    branches:
-      - 'master'
-    paths:
-      - '.github/workflows/gosum.yml'
-      - 'go.mod'
-      - 'go.sum'
-
-jobs:
-  fix:
-    runs-on: ubuntu-latest
-    steps:
-      -
-        name: Checkout
-        uses: actions/checkout@v2
-      -
-        name: Set up Go
-        uses: actions/setup-go@v2
-        with:
-          go-version: 1.14
-      -
-        name: Tidy
-        run: |
-          rm -f go.sum
-          go mod tidy
-      -
-        name: Create Pull Request
-        uses: peter-evans/create-pull-request@v2
-        with:
-          token: ${{ secrets.GITHUB_TOKEN }}
-          commit-message: "fix: go mod tidy"
-          title: "fix: go mod tidy"
-          body: |
-            Current `go.mod` and `go.sum` don't match the source code.
-          branch: go-mod-tidy
-          branch-suffix: timestamp
-          labels: automerge
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 32b2fc200..eb8e60856 100644
--- a/Makefile
+++ b/Makefile
@@ -20,6 +20,16 @@ LD_FLAGS="-s -w -X $(PACKAGE)/pkg/version.BuildVersion=$(GIT_VERSION) -X $(PACKA
 # KYVERNO
 ##################################
 
+.PHONY: unused-package-check
+unused-package-check:
+	@echo "------------------"
+	@echo "--> Check unused packages for the all kyverno components"
+	@echo "------------------"
+	@tidy=$$(go mod tidy); \
+	if [ -n "$${tidy}" ]; then \
+		echo "go mod tidy checking failed!"; echo "$${tidy}"; echo; \
+	fi
+
 KYVERNO_PATH:= cmd/kyverno
 build: kyverno
 PWD := $(CURDIR)
@@ -43,8 +53,8 @@ docker-build-initContainer-amd64:
 	@docker build -f $(PWD)/$(INITC_PATH)/Dockerfile -t $(REPO)/$(INITC_IMAGE):$(IMAGE_TAG) . --build-arg LD_FLAGS=$(LD_FLAGS) --build-arg TARGETPLATFORM="linux/amd64"
 
 docker-push-initContainer:
-	@docker buildx build --file $(PWD)/$(INITC_PATH)/Dockerfile --progress plane --push --platform linux/arm64,linux/amd64 --tag $(REPO)/$(INITC_IMAGE):$(IMAGE_TAG) .
-	@docker buildx build --file $(PWD)/$(INITC_PATH)/Dockerfile --progress plane --push --platform linux/arm64,linux/amd64 --tag $(REPO)/$(INITC_IMAGE):latest .
+	@docker buildx build --file $(PWD)/$(INITC_PATH)/Dockerfile --progress plane --push --platform linux/arm64,linux/amd64 --tag $(REPO)/$(INITC_IMAGE):$(IMAGE_TAG) . --build-arg LD_FLAGS=$(LD_FLAGS)
+	@docker buildx build --file $(PWD)/$(INITC_PATH)/Dockerfile --progress plane --push --platform linux/arm64,linux/amd64 --tag $(REPO)/$(INITC_IMAGE):latest . --build-arg LD_FLAGS=$(LD_FLAGS)
 
 ##################################
 # KYVERNO CONTAINER
@@ -74,8 +84,8 @@ docker-build-kyverno-amd64:
 	@docker build -f $(PWD)/$(KYVERNO_PATH)/Dockerfile -t $(REPO)/$(KYVERNO_IMAGE):$(IMAGE_TAG) . --build-arg LD_FLAGS=$(LD_FLAGS) --build-arg TARGETPLATFORM="linux/amd64"
 
 docker-push-kyverno:
-	@docker buildx build --file $(PWD)/$(KYVERNO_PATH)/Dockerfile --progress plane --push --platform linux/arm64,linux/amd64 --tag $(REPO)/$(KYVERNO_IMAGE):$(IMAGE_TAG) .
-	@docker buildx build --file $(PWD)/$(KYVERNO_PATH)/Dockerfile --progress plane --push --platform linux/arm64,linux/amd64 --tag $(REPO)/$(KYVERNO_IMAGE):latest .
+	@docker buildx build --file $(PWD)/$(KYVERNO_PATH)/Dockerfile --progress plane --push --platform linux/arm64,linux/amd64 --tag $(REPO)/$(KYVERNO_IMAGE):$(IMAGE_TAG) . --build-arg LD_FLAGS=$(LD_FLAGS)
+	@docker buildx build --file $(PWD)/$(KYVERNO_PATH)/Dockerfile --progress plane --push --platform linux/arm64,linux/amd64 --tag $(REPO)/$(KYVERNO_IMAGE):latest . --build-arg LD_FLAGS=$(LD_FLAGS)
 
 ##################################
 
@@ -105,9 +115,9 @@ docker-build-cli-amd64:
 	@docker build -f $(PWD)/$(CLI_PATH)/Dockerfile -t $(REPO)/$(KYVERNO_CLI_IMAGE):$(IMAGE_TAG) . --build-arg LD_FLAGS=$(LD_FLAGS) --build-arg TARGETPLATFORM="linux/amd64"
 
 docker-push-cli:
-	@docker buildx build --file $(PWD)/$(CLI_PATH)/Dockerfile --progress plane --push --platform linux/arm64,linux/amd64 --tag $(REPO)/$(KYVERNO_CLI_IMAGE):$(IMAGE_TAG) .
-	@docker buildx build --file $(PWD)/$(CLI_PATH)/Dockerfile --progress plane --push --platform linux/arm64,linux/amd64 --tag $(REPO)/$(KYVERNO_CLI_IMAGE):latest .
-
+	@docker buildx build --file $(PWD)/$(CLI_PATH)/Dockerfile --progress plane --push --platform linux/arm64,linux/amd64 --tag $(REPO)/$(KYVERNO_CLI_IMAGE):$(IMAGE_TAG) . --build-arg LD_FLAGS=$(LD_FLAGS)
+	@docker buildx build --file $(PWD)/$(CLI_PATH)/Dockerfile --progress plane --push --platform linux/arm64,linux/amd64 --tag $(REPO)/$(KYVERNO_CLI_IMAGE):latest . --build-arg LD_FLAGS=$(LD_FLAGS)
+ 
 ##################################
 docker-publish-all: docker-publish-initContainer docker-publish-kyverno docker-publish-cli
 
diff --git a/README.md b/README.md
index f397d846c..68ef46b5d 100644
--- a/README.md
+++ b/README.md
@@ -30,4 +30,13 @@ Checkout out the Kyverno <a href="https://kyverno.io/community">Community</a> pa
 - For feature requests and bugs, file an [issue](https://github.com/kyverno/kyverno/issues).
 - For discussions or questions, join the **#kyverno** channel on the [Kubernetes Slack](https://kubernetes.slack.com/) or the [mailing list](https://groups.google.com/g/kyverno).
 
+## Spread The Love
+
+We built Kyverno to make it easy to secure and manage Kubernetes configurations. If you like the project, [let us know](https://github.com/kyverno/kyverno/stargazers)!
+
+[![Stargazers over time](https://starchart.cc/kyverno/kyverno.svg)](https://starchart.cc/kyverno/kyverno)
+
+
+
+
 
diff --git a/cmd/cli/kubectl-kyverno/Dockerfile b/cmd/cli/kubectl-kyverno/Dockerfile
index 001153de5..24a9df1c0 100644
--- a/cmd/cli/kubectl-kyverno/Dockerfile
+++ b/cmd/cli/kubectl-kyverno/Dockerfile
@@ -18,8 +18,6 @@ RUN go env
 
 RUN CGO_ENABLED=0 go build -o /output/kyverno -ldflags="${LD_FLAGS}" -v ./cmd/cli/kubectl-kyverno/
 
-RUN useradd -u 10001 kyverno
-
 # Packaging stage
 FROM scratch
 
@@ -28,6 +26,6 @@ LABEL maintainer="Kyverno"
 COPY --from=builder /output/kyverno /
 COPY --from=builder /etc/passwd /etc/passwd
 
-USER kyverno
+USER 10001
 
 ENTRYPOINT ["./kyverno"]
\ No newline at end of file
diff --git a/cmd/initContainer/Dockerfile b/cmd/initContainer/Dockerfile
index 8dde90a73..0adaf8a99 100644
--- a/cmd/initContainer/Dockerfile
+++ b/cmd/initContainer/Dockerfile
@@ -18,8 +18,6 @@ RUN go env
 
 RUN CGO_ENABLED=0 go build -o /output/kyvernopre -ldflags="${LD_FLAGS}" -v ./cmd/initContainer/
 
-RUN useradd -u 10001 kyverno
-
 # Packaging stage
 FROM scratch
 
@@ -28,6 +26,6 @@ LABEL maintainer="Kyverno"
 COPY --from=builder /output/kyvernopre /
 COPY --from=builder /etc/passwd /etc/passwd
 
-USER kyverno
+USER 10001
 
 ENTRYPOINT ["./kyvernopre"]
diff --git a/cmd/initContainer/main.go b/cmd/initContainer/main.go
index 7e09ecff8..4f0dc8986 100644
--- a/cmd/initContainer/main.go
+++ b/cmd/initContainer/main.go
@@ -10,7 +10,6 @@ import (
 	"sync"
 	"time"
 
-	"github.com/kyverno/kyverno/pkg/config"
 	client "github.com/kyverno/kyverno/pkg/dclient"
 	"github.com/kyverno/kyverno/pkg/signal"
 	"github.com/kyverno/kyverno/pkg/utils"
@@ -28,8 +27,6 @@ var (
 )
 
 const (
-	mutatingWebhookConfigKind      string = "MutatingWebhookConfiguration"
-	validatingWebhookConfigKind    string = "ValidatingWebhookConfiguration"
 	policyReportKind               string = "PolicyReport"
 	clusterPolicyReportKind        string = "ClusterPolicyReport"
 	reportChangeRequestKind        string = "ReportChangeRequest"
@@ -72,16 +69,6 @@ func main() {
 	}
 
 	requests := []request{
-		{validatingWebhookConfigKind, config.ValidatingWebhookConfigurationName},
-		{validatingWebhookConfigKind, config.ValidatingWebhookConfigurationDebugName},
-		{mutatingWebhookConfigKind, config.MutatingWebhookConfigurationName},
-		{mutatingWebhookConfigKind, config.MutatingWebhookConfigurationDebugName},
-
-		{validatingWebhookConfigKind, config.PolicyValidatingWebhookConfigurationName},
-		{validatingWebhookConfigKind, config.PolicyValidatingWebhookConfigurationDebugName},
-		{mutatingWebhookConfigKind, config.PolicyMutatingWebhookConfigurationName},
-		{mutatingWebhookConfigKind, config.PolicyMutatingWebhookConfigurationDebugName},
-
 		{policyReportKind, ""},
 		{clusterPolicyReportKind, ""},
 
@@ -120,8 +107,6 @@ func main() {
 
 func executeRequest(client *client.Client, req request) error {
 	switch req.kind {
-	case mutatingWebhookConfigKind, validatingWebhookConfigKind:
-		return removeWebhookIfExists(client, req.kind, req.name)
 	case policyReportKind:
 		return removePolicyReport(client, req.kind)
 	case clusterPolicyReportKind:
@@ -236,29 +221,6 @@ func merge(done <-chan struct{}, stopCh <-chan struct{}, processes ...<-chan err
 	return out
 }
 
-func removeWebhookIfExists(client *client.Client, kind string, name string) error {
-	logger := log.Log.WithName("removeExistingWebhook").WithValues("kind", kind, "name", name)
-	var err error
-	// Get resource
-	_, err = client.GetResource("", kind, "", name)
-	if errors.IsNotFound(err) {
-		logger.V(4).Info("resource not found")
-		return nil
-	}
-	if err != nil {
-		logger.Error(err, "failed to get resource")
-		return err
-	}
-	// Delete resource
-	err = client.DeleteResource("", kind, "", name, false)
-	if err != nil {
-		logger.Error(err, "failed to delete resource")
-		return err
-	}
-	logger.Info("removed the resource")
-	return nil
-}
-
 func removeClusterPolicyReport(client *client.Client, kind string) error {
 	logger := log.Log.WithName("removeClusterPolicyReport")
 
diff --git a/cmd/kyverno/Dockerfile b/cmd/kyverno/Dockerfile
index e4f4f4bfc..8e999e883 100644
--- a/cmd/kyverno/Dockerfile
+++ b/cmd/kyverno/Dockerfile
@@ -18,8 +18,6 @@ RUN go env
 
 RUN CGO_ENABLED=0 go build -o /output/kyverno -ldflags="${LD_FLAGS}" -v ./cmd/kyverno/
 
-RUN useradd -u 10001 kyverno
-
 # Packaging stage
 FROM scratch
 
@@ -28,6 +26,6 @@ LABEL maintainer="Kyverno"
 COPY --from=builder /output/kyverno /
 COPY --from=builder /etc/passwd /etc/passwd
 
-USER kyverno
+USER 10001
 
 ENTRYPOINT ["./kyverno"]
diff --git a/cmd/kyverno/localDockerfile b/cmd/kyverno/localDockerfile
index 42309392d..e58ab3904 100644
--- a/cmd/kyverno/localDockerfile
+++ b/cmd/kyverno/localDockerfile
@@ -1,3 +1,7 @@
 FROM scratch
+
 ADD kyverno /kyverno
+
+USER 10001
+
 ENTRYPOINT ["/kyverno"]
\ No newline at end of file
diff --git a/cmd/kyverno/main.go b/cmd/kyverno/main.go
index 61e8548ac..01ab10270 100755
--- a/cmd/kyverno/main.go
+++ b/cmd/kyverno/main.go
@@ -24,6 +24,7 @@ import (
 	"github.com/kyverno/kyverno/pkg/policystatus"
 	"github.com/kyverno/kyverno/pkg/resourcecache"
 	"github.com/kyverno/kyverno/pkg/signal"
+	ktls "github.com/kyverno/kyverno/pkg/tls"
 	"github.com/kyverno/kyverno/pkg/utils"
 	"github.com/kyverno/kyverno/pkg/version"
 	"github.com/kyverno/kyverno/pkg/webhookconfig"
@@ -144,7 +145,7 @@ func main() {
 		log.Log)
 
 	// Resource Mutating Webhook Watcher
-	webhookMonitor := webhookconfig.NewMonitor(log.Log.WithName("WebhookMonitor"))
+	webhookMonitor := webhookconfig.NewMonitor(rCache, log.Log.WithName("WebhookMonitor"))
 
 	// KYVERNO CRD INFORMER
 	// watches CRD resources:
@@ -283,8 +284,9 @@ func main() {
 		client,
 	)
 
+	certRenewer := ktls.NewCertRenewer(client, clientConfig, ktls.CertRenewalInterval, ktls.CertValidityDuration, log.Log.WithName("CertRenewer"))
 	// Configure certificates
-	tlsPair, err := client.InitTLSPemPair(clientConfig, serverIP)
+	tlsPair, err := certRenewer.InitTLSPemPair(serverIP)
 	if err != nil {
 		setupLog.Error(err, "Failed to initialize TLS key/certificate pair")
 		os.Exit(1)
@@ -329,6 +331,7 @@ func main() {
 		pCacheController.Cache,
 		webhookCfg,
 		webhookMonitor,
+		certRenewer,
 		statusSync.Listener,
 		configData,
 		reportReqGen,
diff --git a/definitions/install.yaml b/definitions/install.yaml
index ca3b27db4..c1dc3bdc0 100644
--- a/definitions/install.yaml
+++ b/definitions/install.yaml
@@ -2480,7 +2480,6 @@ spec:
           privileged: false
           readOnlyRootFilesystem: true
           runAsNonRoot: true
-          runAsUser: 1000
       initContainers:
       - image: ghcr.io/kyverno/kyvernopre:v1.3.4
         imagePullPolicy: IfNotPresent
@@ -2493,7 +2492,6 @@ spec:
           privileged: false
           readOnlyRootFilesystem: true
           runAsNonRoot: true
-          runAsUser: 1000
       securityContext:
         runAsNonRoot: true
       serviceAccountName: kyverno-service-account
diff --git a/definitions/manifest/deployment.yaml b/definitions/manifest/deployment.yaml
index 31d7a7725..f6d6568ac 100755
--- a/definitions/manifest/deployment.yaml
+++ b/definitions/manifest/deployment.yaml
@@ -24,7 +24,6 @@ spec:
           image: ghcr.io/kyverno/kyvernopre:latest
           imagePullPolicy: IfNotPresent
           securityContext:
-            runAsUser: 1000
             runAsNonRoot: true
             privileged: false
             allowPrivilegeEscalation: false
@@ -57,7 +56,6 @@ spec:
             - name: KYVERNO_SVC
               value: kyverno-svc
           securityContext:
-            runAsUser: 1000
             runAsNonRoot: true
             privileged: false
             allowPrivilegeEscalation: false
diff --git a/go.mod b/go.mod
index 52c74dd91..a2b2bed18 100644
--- a/go.mod
+++ b/go.mod
@@ -7,19 +7,15 @@ require (
 	github.com/cornelk/hashmap v1.0.1
 	github.com/evanphx/json-patch/v5 v5.2.0
 	github.com/fatih/color v1.9.0
-	github.com/fsnotify/fsnotify v1.4.9 // indirect
 	github.com/gardener/controller-manager-library v0.2.0
 	github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32
 	github.com/go-git/go-billy/v5 v5.0.0
 	github.com/go-git/go-git/v5 v5.2.0
 	github.com/go-logr/logr v0.3.0
-	github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
 	github.com/googleapis/gnostic v0.5.4
-	github.com/hashicorp/golang-lru v0.5.4 // indirect
 	github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af
 	github.com/julienschmidt/httprouter v1.3.0
 	github.com/kataras/tablewriter v0.0.0-20180708051242-e063d29b7c23
-	github.com/kr/pretty v0.2.0 // indirect
 	github.com/lensesio/tableprinter v0.0.0-20201125135848-89e81fc956e7
 	github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a
 	github.com/mattn/go-isatty v0.0.12 // indirect
@@ -32,8 +28,6 @@ require (
 	github.com/sirupsen/logrus v1.6.0 // indirect
 	github.com/spf13/cobra v1.1.1
 	github.com/stretchr/testify v1.6.1
-	golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect
-	golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
 	gopkg.in/yaml.v2 v2.3.0
 	gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
 	gotest.tools v2.2.0+incompatible
diff --git a/go.sum b/go.sum
index adde073da..6fc77d16f 100644
--- a/go.sum
+++ b/go.sum
@@ -70,17 +70,17 @@ github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUW
 github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
 github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
 github.com/ahmetb/gen-crd-api-reference-docs v0.1.5/go.mod h1:P/XzJ+c2+khJKNKABcm2biRwk2QAuwbLf8DlXuaL7WM=
+github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
 github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
 github.com/alecthomas/participle v0.2.1/go.mod h1:SW6HZGeZgSIpcUWX3fXpfZhuaWHnmoD5KCVaqSaNTkk=
-github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
-github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
 github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
 github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
+github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
 github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
 github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ=
 github.com/appscode/jsonpatch v0.0.0-20190108182946-7c0e3b262f30/go.mod h1:4AJxUpXUhv4N+ziTvIcWWXgeorXpxPZOfk9HdEVr96M=
@@ -89,9 +89,9 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5
 github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
 github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg=
 github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
 github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
-github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
 github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
 github.com/aws/aws-sdk-go v1.20.21/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
 github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
@@ -103,7 +103,6 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
 github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
 github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
 github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
-github.com/blang/semver v3.5.0+incompatible h1:CGxCgetQ64DKk7rdZ++Vfnb1+ogGNnB17OJKJXD2Cfs=
 github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
 github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
 github.com/bombsimon/wsl v1.2.5/go.mod h1:43lEF/i0kpXbLCeDXL9LMT8c92HyBywXb0AsgMHYngM=
@@ -111,7 +110,6 @@ github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEe
 github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
 github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/cheggaaa/pb v1.0.28/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
@@ -120,7 +118,6 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
 github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
 github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
 github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
-github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
 github.com/coredns/coredns v1.4.0/go.mod h1:zASH/MVDgR6XZTbxvOnsZfffS+31vg6Ackf/wo1+AM0=
@@ -184,7 +181,6 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
 github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 github.com/evanphx/json-patch v4.0.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
-github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
 github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses=
 github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
@@ -194,6 +190,7 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
 github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
 github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
 github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
+github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
 github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
 github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
@@ -208,6 +205,7 @@ github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2H
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew=
 github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
+github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
 github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
 github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
 github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
@@ -216,12 +214,9 @@ github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6
 github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
 github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
 github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
-github.com/go-git/go-billy v1.0.0 h1:bXR6Zu3opPSg0R4dDxqaLglY4rxw7ja7wS16qSpOKL4=
-github.com/go-git/go-billy v4.2.0+incompatible h1:Z6QtVXd5tjxUtcODLugkJg4WaZnGg13CD8qB9pr+7q0=
 github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM=
 github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
-github.com/go-git/go-git v1.0.0 h1:YcN9iDGDoXuIw0vHls6rINwV416HYa0EB2X+RBsyYp4=
-github.com/go-git/go-git v4.7.0+incompatible h1:+W9rgGY4DOKKdX2x6HxSR7HNeTxqiKrOvKnuittYVdA=
+github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbKy9zOy4aAKrJ5pibIRpVO2BXnK1Tlcg+caKI7Ox5M=
 github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
 github.com/go-git/go-git/v5 v5.2.0 h1:YPBLG/3UK1we1ohRkncLjaXWLW+HKp5QNM/jTli2JgI=
 github.com/go-git/go-git/v5 v5.2.0/go.mod h1:kh02eMX+wdqqxgNMEyq8YgwlIOsDOa9homkUq1PoTMs=
@@ -234,14 +229,10 @@ github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp
 github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM=
 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
-github.com/go-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg=
 github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
-github.com/go-logr/logr v0.2.0 h1:QvGt2nLcHH0WK9orKa+ppBPAxREcH364nPUedEpK0TY=
 github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
 github.com/go-logr/logr v0.3.0 h1:q4c+kbcR0d5rSurhBR8dIgieOaYpXtsdTYfx22Cu6rs=
 github.com/go-logr/logr v0.3.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
-github.com/go-logr/zapr v0.1.0 h1:h+WVe9j6HAA01niTJPA/kKH0i7e0rLZBCwauQFcRE54=
-github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk=
 github.com/go-logr/zapr v0.2.0/go.mod h1:qhKdvif7YF5GI9NWEpyxTSSBdGmzkNguibrdCNVPunU=
 github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
 github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
@@ -250,11 +241,9 @@ github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70t
 github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
 github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
 github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk=
-github.com/go-openapi/analysis v0.19.5 h1:8b2ZgKfKIUTVQpTb77MoRDIMEIwvDVw40o3aOXdfYzI=
 github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU=
 github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
 github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
-github.com/go-openapi/errors v0.19.2 h1:a2kIyV3w+OS3S97zxUndRVD46+FhGOUBDFY7nmu4CsY=
 github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
 github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
 github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
@@ -272,11 +261,9 @@ github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf
 github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
 github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
 github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs=
-github.com/go-openapi/loads v0.19.4 h1:5I4CCSqoWzT+82bBkNIvmLc0UOsoKKQ4Fz+3VxOB7SY=
 github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk=
 github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA=
 github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64=
-github.com/go-openapi/runtime v0.19.4 h1:csnOgcgAiuGoM/Po7PEpKDoNulCcF3FGbSnbHfxgjMI=
 github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4=
 github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
 github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
@@ -289,7 +276,6 @@ github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pL
 github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
 github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY=
 github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=
-github.com/go-openapi/strfmt v0.19.5 h1:0utjKrw+BAh8s57XE9Xz8DUBsVvPmRUB6styvl9wWIM=
 github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk=
 github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
 github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
@@ -299,11 +285,8 @@ github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tF
 github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
 github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
 github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
-github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
-github.com/go-openapi/validate v0.19.8 h1:YFzsdWIDfVuLvIOF+ZmKjVg1MbPJ1QgY9PihMwei1ys=
 github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
 github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
-github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
 github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4=
@@ -331,7 +314,6 @@ github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
 github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -346,7 +328,6 @@ github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+
 github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
 github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
 github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
@@ -382,14 +363,12 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
 github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
 github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
-github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
 github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -402,17 +381,13 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf
 github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
 github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
 github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
-github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
 github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
-github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk=
-github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU=
-github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I=
 github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
 github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
 github.com/googleapis/gnostic v0.5.4 h1:ynbQIWjLw7iv6HAFdixb30U7Uvcmx+f4KlLJpmhkTK0=
@@ -471,7 +446,6 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
 github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
 github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
-github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
 github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
 github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
@@ -483,14 +457,11 @@ github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoI
 github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M=
 github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
 github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
-github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4=
 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
-github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ=
-github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 github.com/imdario/mergo v0.3.10 h1:6q5mVkdH/vYmqngx7kZQTjJ5HRsx+ImorDIEQ+beJgc=
 github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
@@ -509,8 +480,6 @@ github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBv
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
-github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
 github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
@@ -542,13 +511,12 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJ
 github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
 github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
 github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
-github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/kurin/blazer v0.5.4-0.20190613185654-cf2f27cc0be3/go.mod h1:4FCXMUWo9DllR2Do4TtBd377ezyAJ51vB5uTBjt0pGU=
 github.com/lensesio/tableprinter v0.0.0-20201125135848-89e81fc956e7 h1:k/1ku0yehLCPqERCHkIHMDqDg1R02AcCScRuHbamU3s=
@@ -591,7 +559,6 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp
 github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
 github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
 github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
-github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
 github.com/miekg/dns v1.1.8/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
@@ -621,7 +588,6 @@ github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUb
 github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
 github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
 github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
 github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
 github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -655,6 +621,7 @@ github.com/nats-io/stan.go v0.4.5/go.mod h1:Ji7mK6gRZJSH1nc3ZJH6vi7zn/QnZhpR9Arm
 github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
 github.com/ncw/directio v1.0.5 h1:JSUBhdjEvVaJvOoyPAbcW0fnd0tvRXD76wEfZ1KcQz4=
 github.com/ncw/directio v1.0.5/go.mod h1:rX/pKEYkOXBGOggmcyJeJGloCkleSvphPx2eV3t6ROk=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
 github.com/nsqio/go-nsq v1.0.7/go.mod h1:XP5zaUs3pqf+Q71EqUJs3HYfBIqfK6G83WQMdNN+Ito=
 github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
@@ -666,7 +633,6 @@ github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
 github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
 github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4=
@@ -676,7 +642,6 @@ github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuB
 github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
-github.com/onsi/gomega v1.8.1 h1:C5Dqfs/LeauYDX0jJXIe2SWmwCbGzx9yF8C8xy3Lh34=
 github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
 github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
 github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs=
@@ -685,12 +650,10 @@ github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6 h1:lNCW6THr
 github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CFcDWnWD9XkenwhI=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
 github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
-github.com/patrickmn/go-cache v1.0.0 h1:3gD5McaYs9CxjyK5AXGcq8gdeCARtd/9gJDUvVeaZ0Y=
 github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
 github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
 github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu//Vk=
 github.com/pborman/getopt v0.0.0-20180729010549-6fdd0a2c7117/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
-github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
 github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
@@ -716,13 +679,11 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:
 github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
 github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
 github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
 github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
-github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw=
 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
@@ -762,7 +723,6 @@ github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxr
 github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
-github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
 github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
@@ -777,12 +737,10 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k
 github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE=
 github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
-github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
 github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
 github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
-github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
 github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
 github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4=
 github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
@@ -805,9 +763,7 @@ github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRci
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.2.3-0.20181224173747-660f15d67dbb/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
 github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@@ -848,11 +804,9 @@ github.com/yujunz/go-getter v1.5.1-lite.0.20201201013212-6d9c071adddf/go.mod h1:
 go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
-go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
 go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
 go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
 go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
-go.mongodb.org/mongo-driver v1.1.2 h1:jxcFYjlkl8xaERsgLo+RNquI0epW6zuy/ZRQs6jnrFA=
 go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
@@ -862,18 +816,15 @@ go.starlark.net v0.0.0-20190528202925-30ae18b8564f/go.mod h1:c1/X6cHgvdXj6pUlmWK
 go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
 go.uber.org/atomic v0.0.0-20181018215023-8dc6146f7569/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
-go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
 go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
 go.uber.org/multierr v0.0.0-20180122172545-ddea229ff1df/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
-go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
 go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
 go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
 go.uber.org/zap v0.0.0-20180814183419-67bc79d13d15/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
-go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
 go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -896,10 +847,7 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20191117063200-497ca9f6d64f/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo=
-golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE=
 golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@@ -970,8 +918,6 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
 golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
-golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -1021,14 +967,12 @@ golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
 golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1038,7 +982,6 @@ golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201112073958-5cba982894dd h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY=
 golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1047,16 +990,13 @@ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fq
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
-golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
-golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
 golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s=
 golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1115,11 +1055,9 @@ golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapK
 golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU=
 gomodules.xyz/jsonpatch/v2 v2.1.0/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU=
 google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
 google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
@@ -1137,8 +1075,8 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
 google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
-google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
 google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
 google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@@ -1171,8 +1109,6 @@ google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ij
 google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
 google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg=
 google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
 google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
 google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
@@ -1187,18 +1123,16 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
 google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
 google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
 google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
-gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
 gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
-gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
@@ -1232,9 +1166,7 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
 gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v3 v3.0.0-20190905181640-827449938966/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71 h1:Xe2gvTZUJpsvOWUnvmL/tmhVBZUmHSvLbMjRj6NUUKo=
 gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
 gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
@@ -1249,17 +1181,11 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
 k8s.io/api v0.0.0-20190918155943-95b840bb6a1f/go.mod h1:uWuOHnjmNrtQomJrvEBg0c0HRNyQ+8KTEERVsK0PW48=
 k8s.io/api v0.16.4/go.mod h1:AtzMnsR45tccQss5q8RnF+W8L81DH6XwXwo/joEx9u0=
 k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI=
-k8s.io/api v0.17.2/go.mod h1:BS9fjjLc4CMuqfSO8vgbHPKMt5+SF0ET6u/RVDihTo4=
-k8s.io/api v0.18.12 h1:97X6znOXMVgCKivTAgpBXGBGlCe3gbM++yFdldgBCaE=
-k8s.io/api v0.18.12/go.mod h1:3sS78jmUoGHwERyMbEhxP6owcQ77UxGo+Yy+dKNWrh0=
 k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo=
 k8s.io/api v0.20.2 h1:y/HR22XDZY3pniu9hIFDLpUCPq2w5eQ6aV/VFQ7uJMw=
 k8s.io/api v0.20.2/go.mod h1:d7n6Ehyzx+S+cE3VhTGfVNNqtGc/oL9DCdYYahlurV8=
 k8s.io/apiextensions-apiserver v0.0.0-20190918161926-8f644eb6e783/go.mod h1:xvae1SZB3E17UpV59AWc271W/Ph25N+bjPyR63X6tPY=
 k8s.io/apiextensions-apiserver v0.16.4/go.mod h1:HYQwjujEkXmQNhap2C9YDdIVOSskGZ3et0Mvjcyjbto=
-k8s.io/apiextensions-apiserver v0.17.2/go.mod h1:4KdMpjkEjjDI2pPfBA15OscyNldHWdBCfsWMDWAmSTs=
-k8s.io/apiextensions-apiserver v0.18.12 h1:b0jTgW/qwqZBMIJTMxkLvvAtNRDZboG5yZiIbOFgQv8=
-k8s.io/apiextensions-apiserver v0.18.12/go.mod h1:nihADkPed1L37Vxpz2/BrtxO9mCtINH23aNtUe/CRLo=
 k8s.io/apiextensions-apiserver v0.20.1/go.mod h1:ntnrZV+6a3dB504qwC5PN/Yg9PBiDNt1EVqbW2kORVk=
 k8s.io/apiextensions-apiserver v0.20.2 h1:rfrMWQ87lhd8EzQWRnbQ4gXrniL/yTRBgYH1x1+BLlo=
 k8s.io/apiextensions-apiserver v0.20.2/go.mod h1:F6TXp389Xntt+LUq3vw6HFOLttPa0V8821ogLGwb6Zs=
@@ -1267,33 +1193,22 @@ k8s.io/apimachinery v0.0.0-20190612125636-6a5db36e93ad/go.mod h1:I4A+glKBHiTgiEj
 k8s.io/apimachinery v0.0.0-20190913080033-27d36303b655/go.mod h1:nL6pwRT8NgfF8TT68DBI8uEePRt89cSvoXUVqbkWHq4=
 k8s.io/apimachinery v0.16.4/go.mod h1:llRdnznGEAqC3DcNm6yEj472xaFVfLM7hnYofMb12tQ=
 k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
-k8s.io/apimachinery v0.17.2/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
-k8s.io/apimachinery v0.18.12 h1:bLFXU4IxOu06F6Z6PV7eqtapXFb1G2q0ni0XBNFtJH8=
-k8s.io/apimachinery v0.18.12/go.mod h1:PF5taHbXgTEJLU+xMypMmYTXTWPJ5LaW8bfsisxnEXk=
 k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
 k8s.io/apimachinery v0.20.2 h1:hFx6Sbt1oG0n6DZ+g4bFt5f6BoMkOjKWsQFu077M3Vg=
 k8s.io/apimachinery v0.20.2/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
 k8s.io/apiserver v0.0.0-20190918160949-bfa5e2e684ad/go.mod h1:XPCXEwhjaFN29a8NldXA901ElnKeKLrLtREO9ZhFyhg=
 k8s.io/apiserver v0.16.4/go.mod h1:kbLJOak655g6W7C+muqu1F76u9wnEycfKMqbVaXIdAc=
-k8s.io/apiserver v0.17.2/go.mod h1:lBmw/TtQdtxvrTk0e2cgtOxHizXI+d0mmGQURIHQZlo=
-k8s.io/apiserver v0.18.12/go.mod h1:uFOeW4LlxS6KDgLWy3n3gh0DhC6m41QIFgL33ouk+4w=
 k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU=
 k8s.io/apiserver v0.20.2/go.mod h1:2nKd93WyMhZx4Hp3RfgH2K5PhwyTrprrkWYnI7id7jA=
-k8s.io/cli-runtime v0.18.12 h1:gVWbvntlEttCIvy1jc5UUr2cG/4TmmCM1MY/PGeENBo=
-k8s.io/cli-runtime v0.18.12/go.mod h1:wTj8W8za8NDWe505mrlckiZ5H2cZA0YEuv0E7WC+Srs=
 k8s.io/cli-runtime v0.20.2 h1:W0/FHdbApnl9oB7xdG643c/Zaf7TZT+43I+zKxwqvhU=
 k8s.io/cli-runtime v0.20.2/go.mod h1:FjH6uIZZZP3XmwrXWeeYCbgxcrD6YXxoAykBaWH0VdM=
 k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90/go.mod h1:J69/JveO6XESwVgG53q3Uz5OSfgsv4uxpScmmyYOOlk=
 k8s.io/client-go v0.16.4/go.mod h1:ZgxhFDxSnoKY0J0U2/Y1C8obKDdlhGPZwA7oHH863Ok=
 k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k=
-k8s.io/client-go v0.17.2/go.mod h1:QAzRgsa0C2xl4/eVpeVAZMvikCn8Nm81yqVx3Kk9XYI=
-k8s.io/client-go v0.18.12 h1:MDGRE2tGidz29g45dI4kfelJo+aRmDqWx0Way8mD88A=
-k8s.io/client-go v0.18.12/go.mod h1:0aC8XkA09dX/goYqHQJ/kVv0zL1t+weOZt3pmz9LpxA=
 k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y=
 k8s.io/client-go v0.20.2 h1:uuf+iIAbfnCSw8IGAv/Rg0giM+2bOzHLOsbbrwrdhNQ=
 k8s.io/client-go v0.20.2/go.mod h1:kH5brqWqp7HDxUFKoEgiI4v8G1xzbe9giaCenUWJzgE=
 k8s.io/code-generator v0.0.0-20200306081859-6a048a382944/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc=
-k8s.io/component-base v0.0.0-20190612130303-4062e14deebe h1:GHRdxwv4/80MA+Yy/YVyfc9n6VyOhEGzyM09mEXsIAU=
 k8s.io/component-base v0.0.0-20190612130303-4062e14deebe/go.mod h1:MmIDXnint3qMN0cqXHKrSiJ2XQKo3J1BPIz7in7NvO0=
 k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
 k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
@@ -1313,18 +1228,12 @@ k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH
 k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
 k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
 k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
-k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6 h1:Oh3Mzx5pJ+yIumsAD0MOECPVeXsVot0UkiaCGVyfGQY=
-k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
 k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd h1:sOHNzJIkytDF6qadMNKhhDRpc6ODik8lVC6nOur7B2c=
 k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
 k8s.io/metrics v0.16.4/go.mod h1:dckkfqvaASo+NrzEmp8ST8yCc9hGt7lx9ABAILyDHx8=
 k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0=
 k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
-k8s.io/utils v0.0.0-20191114184206-e782cd3c129f h1:GiPwtSzdP43eI1hpPCbROQCCIgCuiMMNF8YUVLF3vJo=
 k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
-k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89 h1:d4vVOjXm687F1iLSP2q3lyPPuyvTUt3aVoBpi2DqRsU=
-k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
-k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw=
 k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 k8s.io/utils v0.0.0-20210111153108-fddb29f9d009 h1:0T5IaWHO3sJTEmCP6mUlBvMukxPKUQWqiI/YuiBNMiQ=
 k8s.io/utils v0.0.0-20210111153108-fddb29f9d009/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
@@ -1334,11 +1243,7 @@ mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZI
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
 rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
 rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
-sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7 h1:uuHDyjllyzRyCIvvn0OBjiRB0SgBZGqHNYAmjR7fO50=
-sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0=
 sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
-sigs.k8s.io/controller-runtime v0.5.0 h1:CbqIy5fbUX+4E9bpnBFd204YAzRYlM9SWW77BbrcDQo=
-sigs.k8s.io/controller-runtime v0.5.0/go.mod h1:REiJzC7Y00U+2YkMbT8wxgrsX5USpXKGhb2sCtAXiT8=
 sigs.k8s.io/controller-runtime v0.8.1 h1:O0K2CJ2JavK8/Tf4LfcpAwRxOFBhv8DjyrbmE6Qw59s=
 sigs.k8s.io/controller-runtime v0.8.1/go.mod h1:U/l+DUopBc1ecfRZ5aviA9JDmGFQKvLf5YkZNx2e0sU=
 sigs.k8s.io/controller-tools v0.2.4/go.mod h1:m/ztfQNocGYBgTTCmFdnK94uVvgxeZeE3LtJvd/jIzA=
@@ -1350,12 +1255,9 @@ sigs.k8s.io/kustomize/kyaml v0.10.3 h1:ARSJUMN/c3k31DYxRfZ+vp/UepUQjg9zCwny7Oj90
 sigs.k8s.io/kustomize/kyaml v0.10.3/go.mod h1:RA+iCHA2wPCOfv6uG6TfXXWhYsHpgErq/AljxWKuxtg=
 sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
 sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA=
-sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18=
 sigs.k8s.io/structured-merge-diff v1.0.1 h1:LOs1LZWMsz1xs77Phr/pkB4LFaavH7IVq/3+WTN9XTA=
 sigs.k8s.io/structured-merge-diff v1.0.1/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA=
 sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
-sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E=
-sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
 sigs.k8s.io/structured-merge-diff/v4 v4.0.2 h1:YHQV7Dajm86OuqnIR6zAelnDWBRjo+YhYV9PmGrh1s8=
 sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
 sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
diff --git a/pkg/dclient/certificates.go b/pkg/dclient/certificates.go
deleted file mode 100644
index 784fa5c94..000000000
--- a/pkg/dclient/certificates.go
+++ /dev/null
@@ -1,243 +0,0 @@
-package client
-
-import (
-	"encoding/base64"
-	"fmt"
-	"net/url"
-
-	"github.com/kyverno/kyverno/pkg/config"
-	tls "github.com/kyverno/kyverno/pkg/tls"
-	v1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
-	"k8s.io/client-go/rest"
-)
-
-// InitTLSPemPair Loads or creates PEM private key and TLS certificate for webhook server.
-// Created pair is stored in cluster's secret.
-// Returns struct with key/certificate pair.
-func (c *Client) InitTLSPemPair(configuration *rest.Config, serverIP string) (*tls.PemPair, error) {
-	logger := c.log
-	certProps, err := c.GetTLSCertProps(configuration)
-	if err != nil {
-		return nil, err
-	}
-
-	logger.Info("Building key/certificate pair for TLS")
-	tlsPair, err := c.buildTLSPemPair(certProps, serverIP)
-	if err != nil {
-		return nil, err
-	}
-	if err = c.WriteTLSPairToSecret(certProps, tlsPair); err != nil {
-		return nil, fmt.Errorf("Unable to save TLS pair to the cluster: %v", err)
-	}
-
-	return tlsPair, nil
-}
-
-// buildTLSPemPair Issues TLS certificate for webhook server using self-signed CA cert
-// Returns signed and approved TLS certificate in PEM format
-func (c *Client) buildTLSPemPair(props tls.CertificateProps, serverIP string) (*tls.PemPair, error) {
-	caCert, caPEM, err := tls.GenerateCACert()
-	if err != nil {
-		return nil, err
-	}
-
-	if err := c.WriteCACertToSecret(caPEM, props); err != nil {
-		return nil, fmt.Errorf("failed to write CA cert to secret: %v", err)
-	}
-
-	return tls.GenerateCertPem(caCert, props, serverIP)
-}
-
-//ReadRootCASecret returns the RootCA from the pre-defined secret
-func (c *Client) ReadRootCASecret() (result []byte) {
-	logger := c.log.WithName("ReadRootCASecret")
-	certProps, err := c.GetTLSCertProps(c.clientConfig)
-	if err != nil {
-		logger.Error(err, "failed to get TLS Cert Properties")
-		return result
-	}
-	sname := generateRootCASecretName(certProps)
-	stlsca, err := c.GetResource("", Secrets, certProps.Namespace, sname)
-	if err != nil {
-		return result
-	}
-	tlsca, err := convertToSecret(stlsca)
-	if err != nil {
-		logger.Error(err, "failed to convert secret", "name", sname, "namespace", certProps.Namespace)
-		return result
-	}
-
-	result = tlsca.Data[rootCAKey]
-	if len(result) == 0 {
-		logger.Info("root CA certificate not found in secret", "name", tlsca.Name, "namespace", certProps.Namespace)
-		return result
-	}
-	logger.V(4).Info("using CA bundle defined in secret to validate the webhook's server certificate", "name", tlsca.Name, "namespace", certProps.Namespace)
-	return result
-}
-
-const selfSignedAnnotation string = "self-signed-cert"
-const rootCAKey string = "rootCA.crt"
-
-// ReadTLSPair Reads the pair of TLS certificate and key from the specified secret.
-func (c *Client) ReadTLSPair(props tls.CertificateProps) *tls.PemPair {
-	logger := c.log.WithName("ReadTLSPair")
-	sname := generateTLSPairSecretName(props)
-	unstrSecret, err := c.GetResource("", Secrets, props.Namespace, sname)
-	if err != nil {
-		logger.Error(err, "Failed to get secret", "name", sname, "namespace", props.Namespace)
-		return nil
-	}
-
-	// If secret contains annotation 'self-signed-cert', then it's created using helper scripts to setup self-signed certificates.
-	// As the root CA used to sign the certificate is required for webhook cnofiguration, check if the corresponding secret is created
-	annotations := unstrSecret.GetAnnotations()
-	if _, ok := annotations[selfSignedAnnotation]; ok {
-		sname := generateRootCASecretName(props)
-		_, err := c.GetResource("", Secrets, props.Namespace, sname)
-		if err != nil {
-			logger.Error(err, "Root CA secret is required while using self-signed certificates TLS pair, defaulting to generating new TLS pair", "name", sname, "namespace", props.Namespace)
-			return nil
-		}
-	}
-	secret, err := convertToSecret(unstrSecret)
-	if err != nil {
-		return nil
-	}
-	pemPair := tls.PemPair{
-		Certificate: secret.Data[v1.TLSCertKey],
-		PrivateKey:  secret.Data[v1.TLSPrivateKeyKey],
-	}
-	if len(pemPair.Certificate) == 0 {
-		logger.Info("TLS Certificate not found in secret", "name", sname, "namespace", props.Namespace)
-		return nil
-	}
-	if len(pemPair.PrivateKey) == 0 {
-		logger.Info("TLS PrivateKey not found in secret", "name", sname, "namespace", props.Namespace)
-		return nil
-	}
-	return &pemPair
-}
-
-// WriteCACertToSecret stores the CA cert in secret
-func (c *Client) WriteCACertToSecret(caPEM *tls.PemPair, props tls.CertificateProps) error {
-	logger := c.log.WithName("CAcert")
-	name := generateRootCASecretName(props)
-
-	secretUnstr, err := c.GetResource("", Secrets, props.Namespace, name)
-	if err != nil {
-		secret := &v1.Secret{
-			TypeMeta: metav1.TypeMeta{
-				Kind:       "Secret",
-				APIVersion: "v1",
-			},
-			ObjectMeta: metav1.ObjectMeta{
-				Name:      name,
-				Namespace: props.Namespace,
-				Annotations: map[string]string{
-					selfSignedAnnotation: "true",
-				},
-			},
-			Data: map[string][]byte{
-				rootCAKey: caPEM.Certificate,
-			},
-			Type: v1.SecretTypeOpaque,
-		}
-
-		_, err := c.CreateResource("", Secrets, props.Namespace, secret, false)
-		if err == nil {
-			logger.Info("secret created", "name", name, "namespace", props.Namespace)
-		}
-		return err
-	}
-
-	if _, ok := secretUnstr.GetAnnotations()[selfSignedAnnotation]; !ok {
-		secretUnstr.SetAnnotations(map[string]string{selfSignedAnnotation: "true"})
-	}
-
-	dataMap := map[string]interface{}{
-		rootCAKey: base64.StdEncoding.EncodeToString(caPEM.Certificate)}
-
-	if err := unstructured.SetNestedMap(secretUnstr.Object, dataMap, "data"); err != nil {
-		return err
-	}
-
-	_, err = c.UpdateResource("", Secrets, props.Namespace, secretUnstr, false)
-	if err != nil {
-		return err
-	}
-	logger.Info("secret updated", "name", name, "namespace", props.Namespace)
-	return nil
-}
-
-// WriteTLSPairToSecret Writes the pair of TLS certificate and key to the specified secret.
-// Updates existing secret or creates new one.
-func (c *Client) WriteTLSPairToSecret(props tls.CertificateProps, pemPair *tls.PemPair) error {
-	logger := c.log.WithName("WriteTLSPair")
-	name := generateTLSPairSecretName(props)
-	secretUnstr, err := c.GetResource("", Secrets, props.Namespace, name)
-	if err != nil {
-		secret := &v1.Secret{
-			TypeMeta: metav1.TypeMeta{
-				Kind:       "Secret",
-				APIVersion: "v1",
-			},
-			ObjectMeta: metav1.ObjectMeta{
-				Name:      name,
-				Namespace: props.Namespace,
-			},
-			Data: map[string][]byte{
-				v1.TLSCertKey:       pemPair.Certificate,
-				v1.TLSPrivateKeyKey: pemPair.PrivateKey,
-			},
-			Type: v1.SecretTypeTLS,
-		}
-
-		_, err := c.CreateResource("", Secrets, props.Namespace, secret, false)
-		if err == nil {
-			logger.Info("secret created", "name", name, "namespace", props.Namespace)
-		}
-		return err
-	}
-
-	dataMap := map[string]interface{}{
-		v1.TLSCertKey:       base64.StdEncoding.EncodeToString(pemPair.Certificate),
-		v1.TLSPrivateKeyKey: base64.StdEncoding.EncodeToString(pemPair.PrivateKey),
-	}
-
-	if err := unstructured.SetNestedMap(secretUnstr.Object, dataMap, "data"); err != nil {
-		return err
-	}
-
-	_, err = c.UpdateResource("", Secrets, props.Namespace, secretUnstr, false)
-	if err != nil {
-		return err
-	}
-
-	logger.Info("secret updated", "name", name, "namespace", props.Namespace)
-	return nil
-}
-
-func generateTLSPairSecretName(props tls.CertificateProps) string {
-	return tls.GenerateInClusterServiceName(props) + ".kyverno-tls-pair"
-}
-
-func generateRootCASecretName(props tls.CertificateProps) string {
-	return tls.GenerateInClusterServiceName(props) + ".kyverno-tls-ca"
-}
-
-//GetTLSCertProps provides the TLS Certificate Properties
-func (c *Client) GetTLSCertProps(configuration *rest.Config) (certProps tls.CertificateProps, err error) {
-	apiServerURL, err := url.Parse(configuration.Host)
-	if err != nil {
-		return certProps, err
-	}
-	certProps = tls.CertificateProps{
-		Service:       config.KyvernoServiceName,
-		Namespace:     config.KyvernoNamespace,
-		APIServerHost: apiServerURL.Hostname(),
-	}
-	return certProps, nil
-}
diff --git a/pkg/dclient/client.go b/pkg/dclient/client.go
index 3fa1cf66b..cbd31c42e 100644
--- a/pkg/dclient/client.go
+++ b/pkg/dclient/client.go
@@ -9,7 +9,6 @@ import (
 	"github.com/go-logr/logr"
 	openapiv2 "github.com/googleapis/gnostic/openapiv2"
 	certificates "k8s.io/api/certificates/v1beta1"
-	v1 "k8s.io/api/core/v1"
 	helperv1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	meta "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -198,15 +197,6 @@ func convertToUnstructured(obj interface{}) *unstructured.Unstructured {
 	return &unstructured.Unstructured{Object: unstructuredObj}
 }
 
-//To-Do remove this to use unstructured type
-func convertToSecret(obj *unstructured.Unstructured) (v1.Secret, error) {
-	secret := v1.Secret{}
-	if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), &secret); err != nil {
-		return secret, err
-	}
-	return secret, nil
-}
-
 //To-Do remove this to use unstructured type
 func convertToCSR(obj *unstructured.Unstructured) (*certificates.CertificateSigningRequest, error) {
 	csr := certificates.CertificateSigningRequest{}
diff --git a/pkg/dclient/utils.go b/pkg/dclient/utils.go
index d4cf657eb..6b6dc19b0 100644
--- a/pkg/dclient/utils.go
+++ b/pkg/dclient/utils.go
@@ -15,17 +15,6 @@ import (
 	kubernetesfake "k8s.io/client-go/kubernetes/fake"
 )
 
-const (
-	// CSRs CertificateSigningRequest
-	CSRs string = "CertificateSigningRequest"
-	// Secrets Secret
-	Secrets string = "Secret"
-	// ConfigMaps ConfigMap
-	ConfigMaps string = "ConfigMap"
-	// Namespaces Namespace
-	Namespaces string = "Namespace"
-)
-
 //NewMockClient ---testing utilities
 func NewMockClient(scheme *runtime.Scheme, gvrToListKind map[schema.GroupVersionResource]string, objects ...runtime.Object) (*Client, error) {
 	client := fake.NewSimpleDynamicClientWithCustomListKinds(scheme, gvrToListKind, objects...)
diff --git a/pkg/engine/apiPath.go b/pkg/engine/apiPath.go
index 3d64e66d9..691891138 100644
--- a/pkg/engine/apiPath.go
+++ b/pkg/engine/apiPath.go
@@ -81,7 +81,7 @@ func NewAPIPath(path string) (*APIPath, error) {
 		return &APIPath{
 			Root:         paths[0],
 			Group:        paths[1],
-			Version:      paths[2],
+			Version:      paths[1] + "/" + paths[2],
 			ResourceType: paths[3],
 		}, nil
 	}
@@ -91,7 +91,7 @@ func NewAPIPath(path string) (*APIPath, error) {
 		return &APIPath{
 			Root:         paths[0],
 			Group:        paths[1],
-			Version:      paths[2],
+			Version:      paths[1] + "/" + paths[2],
 			ResourceType: paths[3],
 			Name:         paths[4],
 		}, nil
@@ -102,7 +102,7 @@ func NewAPIPath(path string) (*APIPath, error) {
 		return &APIPath{
 			Root:         paths[0],
 			Group:        paths[1],
-			Version:      paths[2],
+			Version:      paths[1] + "/" + paths[2],
 			Namespace:    paths[4],
 			ResourceType: paths[5],
 		}, nil
@@ -113,7 +113,7 @@ func NewAPIPath(path string) (*APIPath, error) {
 		return &APIPath{
 			Root:         paths[0],
 			Group:        paths[1],
-			Version:      paths[2],
+			Version:      paths[1] + "/" + paths[2],
 			Namespace:    paths[4],
 			ResourceType: paths[5],
 			Name:         paths[6],
@@ -125,17 +125,33 @@ func NewAPIPath(path string) (*APIPath, error) {
 
 func (a *APIPath) String() string {
 	var paths []string
-	if a.Namespace != "" {
-		if a.Name == "" {
-			paths = []string{a.Root, a.Group, a.Version, "namespaces", a.Namespace, a.ResourceType}
+	if a.Root == "apis" {
+		if a.Namespace != "" {
+			if a.Name == "" {
+				paths = []string{a.Root, a.Version, "namespaces", a.Namespace, a.ResourceType}
+			} else {
+				paths = []string{a.Root, a.Version, "namespaces", a.Namespace, a.ResourceType, a.Name}
+			}
 		} else {
-			paths = []string{a.Root, a.Group, a.Version, "namespaces", a.Namespace, a.ResourceType, a.Name}
+			if a.Name != "" {
+				paths = []string{a.Root, a.Version, a.ResourceType, a.Name}
+			} else {
+				paths = []string{a.Root, a.Version, a.ResourceType}
+			}
 		}
 	} else {
-		if a.Name != "" {
-			paths = []string{a.Root, a.Group, a.Version, a.ResourceType, a.Name}
+		if a.Namespace != "" {
+			if a.Name == "" {
+				paths = []string{a.Root, a.Group, "namespaces", a.Namespace, a.ResourceType}
+			} else {
+				paths = []string{a.Root, a.Group, "namespaces", a.Namespace, a.ResourceType, a.Name}
+			}
 		} else {
-			paths = []string{a.Root, a.Group, a.Version, a.ResourceType}
+			if a.Name != "" {
+				paths = []string{a.Root, a.Group, a.ResourceType, a.Name}
+			} else {
+				paths = []string{a.Root, a.Group, a.ResourceType}
+			}
 		}
 	}
 
diff --git a/pkg/engine/jsonContext.go b/pkg/engine/jsonContext.go
index 7e5196c1d..98efd8f7f 100644
--- a/pkg/engine/jsonContext.go
+++ b/pkg/engine/jsonContext.go
@@ -13,6 +13,7 @@ import (
 	"github.com/kyverno/kyverno/pkg/resourcecache"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/client-go/dynamic/dynamiclister"
+	"strings"
 )
 
 // LoadContext - Fetches and adds external data to the Context.
@@ -193,6 +194,9 @@ func fetchConfigMap(logger logr.Logger, entry kyverno.ContextEntry, lister dynam
 		return nil, fmt.Errorf("failed to convert configmap %s/%s: %v", namespace, name, err)
 	}
 
+	// update the unstructuredObj["data"] to delimit and split the string value (containing "\n") with "\n"
+	unstructuredObj["data"] = parseMultilineBlockBody(unstructuredObj["data"].(map[string]interface{}))
+
 	// extract configmap data
 	contextData["data"] = unstructuredObj["data"]
 	contextData["metadata"] = unstructuredObj["metadata"]
@@ -205,3 +209,25 @@ func fetchConfigMap(logger logr.Logger, entry kyverno.ContextEntry, lister dynam
 
 	return data, nil
 }
+
+// parseMultilineBlockBody recursively iterates through a map and updates its values in the following way
+// whenever it encounters a string value containing "\n",
+// it converts it into a []string by splitting it by "\n"
+func parseMultilineBlockBody(m map[string]interface{}) map[string]interface{} {
+	for k, v := range m {
+		switch typedValue := v.(type) {
+		case string:
+			trimmedTypedValue := strings.Trim(typedValue, "\n")
+			if strings.Contains(trimmedTypedValue, "\n") {
+				m[k] = strings.Split(trimmedTypedValue, "\n")
+			} else {
+				m[k] = trimmedTypedValue // trimming a str if it has trailing newline characters
+			}
+		case map[string]interface{}:
+			m[k] = parseMultilineBlockBody(typedValue)
+		default:
+			continue
+		}
+	}
+	return m
+}
diff --git a/pkg/engine/mutate/mutation.go b/pkg/engine/mutate/mutation.go
index abeb26a00..4b32c5b89 100644
--- a/pkg/engine/mutate/mutation.go
+++ b/pkg/engine/mutate/mutation.go
@@ -64,6 +64,7 @@ func (h patchStrategicMergeHandler) Handle() (response.RuleResponse, unstructure
 	var err error
 	if PatchStrategicMerge, err = variables.SubstituteVars(log, h.evalCtx, PatchStrategicMerge); err != nil {
 		// variable subsitution failed
+		ruleResponse.Name = h.ruleName
 		ruleResponse.Success = false
 		ruleResponse.Message = err.Error()
 		return ruleResponse, h.patchedResource
@@ -121,16 +122,6 @@ func (h patchesJSON6902Handler) Handle() (resp response.RuleResponse, patchedRes
 		return resp, h.patchedResource
 	}
 
-	skip, err := preProcessJSONPatches(patchesJSON6902, h.patchedResource, h.logger)
-	if err != nil {
-		h.logger.Error(err, "failed to preProcessJSONPatches")
-	}
-
-	if skip {
-		resp.Success = true
-		return resp, h.patchedResource
-	}
-
 	return ProcessPatchJSON6902(h.ruleName, patchesJSON6902, h.patchedResource, h.logger)
 }
 
@@ -173,25 +164,6 @@ func (h patchesHandler) Handle() (resp response.RuleResponse, patchedResource un
 	resp.Name = h.ruleName
 	resp.Type = utils.Mutation.String()
 
-	// patches is already converted to patchesJSON6902
-	patchesJSON6902, err := convertPatchesToJSON(h.mutation.PatchesJSON6902)
-	if err != nil {
-		resp.Success = false
-		h.logger.Error(err, "error in type conversion")
-		resp.Message = err.Error()
-		return resp, h.patchedResource
-	}
-
-	skip, err := preProcessJSONPatches(patchesJSON6902, h.patchedResource, h.logger)
-	if err != nil {
-		h.logger.Error(err, "failed to preProcessJSONPatches")
-	}
-
-	if skip {
-		resp.Success = true
-		return resp, h.patchedResource
-	}
-
 	return ProcessPatches(h.logger, h.ruleName, *h.mutation, h.patchedResource)
 }
 
diff --git a/pkg/engine/mutate/patchesUtils.go b/pkg/engine/mutate/patchesUtils.go
index 4568eb2fd..f5deacc93 100644
--- a/pkg/engine/mutate/patchesUtils.go
+++ b/pkg/engine/mutate/patchesUtils.go
@@ -1,18 +1,12 @@
 package mutate
 
 import (
-	"fmt"
 	"path/filepath"
-	"reflect"
 	"regexp"
-	"strconv"
 	"strings"
 
-	evanjsonpatch "github.com/evanphx/json-patch/v5"
-	"github.com/go-logr/logr"
 	"github.com/mattbaird/jsonpatch"
 	"github.com/minio/minio/pkg/wildcard"
-	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 )
 
 func generatePatches(src, dst []byte) ([][]byte, error) {
@@ -152,135 +146,3 @@ func ignorePatch(path string) bool {
 
 	return false
 }
-
-// preProcessJSONPatches deals with the JsonPatch when reinvocation
-// policy is set in webhook, to avoid generating duplicate values.
-// This duplicate error only occurs on type array, if it's adding to a map
-// the value will be added to the map if nil, otherwise it overwrites the old value
-// return skip == true to skip the json patch application
-func preProcessJSONPatches(patchesJSON6902 []byte, resource unstructured.Unstructured,
-	log logr.Logger) (skip bool, err error) {
-	var patches evanjsonpatch.Patch
-	log = log.WithName("preProcessJSONPatches")
-
-	patches, err = evanjsonpatch.DecodePatch(patchesJSON6902)
-	if err != nil {
-		return false, fmt.Errorf("cannot decode patches as an RFC 6902 patch: %v", err)
-	}
-
-	for _, patch := range patches {
-		if patch.Kind() != "add" {
-			continue
-		}
-
-		path, err := patch.Path()
-		if err != nil {
-			return false, fmt.Errorf("failed to get path in JSON Patch: %v", err)
-		}
-
-		// check if the target is the list
-		if tail := filepath.Base(path); tail != "-" {
-			_, err := strconv.Atoi(tail)
-			if err != nil {
-				log.V(4).Info("JSON patch does not add to the list, skipping", "path", path)
-				continue
-			}
-		}
-
-		resourceObj, err := getObject(path, resource.UnstructuredContent())
-		if err != nil {
-			log.V(4).Info("unable to get object by the given path, proceed patchesJson6902 without preprocessing", "path", path, "error", err.Error())
-			continue
-		}
-
-		val, err := patch.ValueInterface()
-		if err != nil {
-			log.V(4).Info("unable to get value by the given path, proceed patchesJson6902 without preprocessing", "path", path, "error", err.Error())
-			continue
-		}
-
-		// if there's one patch exist in the resource, which indicates
-		// this is re-invoked JSON patches, skip application
-		if isSubsetObject(val, resourceObj) {
-			return true, nil
-		}
-	}
-
-	return false, nil
-}
-
-// - insert to the end of the list
-// {"op": "add", "path": "/spec/containers/-", {"value": "{"name":"busyboxx","image":"busybox:latest"}"}
-
-// - insert value to the certain element of the list
-// {"op": "add", "path": "/spec/containers/1", {"value": "{"name":"busyboxx","image":"busybox:latest"}"}
-func getObject(path string, resource map[string]interface{}) (interface{}, error) {
-	var strippedResource interface{}
-	strippedResource = resource
-	var ok bool
-
-	if strings.HasPrefix(path, "/") {
-		path = path[1:]
-	}
-	paths := strings.Split(path, "/")
-
-	for i, key := range paths {
-		switch strippedResource.(type) {
-		case map[string]interface{}:
-			strippedResource, ok = strippedResource.(map[string]interface{})[key]
-			if !ok {
-				return nil, fmt.Errorf("referenced value does not exist at %s", strings.Join(paths[:i+1], "/"))
-			}
-
-		case []interface{}:
-			var idx int
-
-			if key == "-" {
-				idx = len(strippedResource.([]interface{})) - 1
-			} else {
-				var err error
-				idx, err = strconv.Atoi(key)
-				if err != nil {
-					return nil, fmt.Errorf("cannot parse index in JSON Patch at %s: %v", strings.Join(paths[:i+1], "/"), err)
-				}
-				if idx < 0 {
-					idx = len(strippedResource.([]interface{})) - 1
-				}
-			}
-
-			if len(strippedResource.([]interface{})) <= idx {
-				return nil, nil
-			}
-
-			strippedResource = strippedResource.([]interface{})[idx]
-		}
-	}
-	return strippedResource, nil
-}
-
-// isSubsetObject returns true if object is subset of resource
-// the object/resource is the element inside the list, return false
-// if the type is mismatched (not map)
-func isSubsetObject(object, resource interface{}) bool {
-	objectMap, ok := object.(map[string]interface{})
-	if !ok {
-		return false
-	}
-
-	resourceMap, ok := resource.(map[string]interface{})
-	if !ok {
-		return false
-	}
-
-	for objKey, objVal := range objectMap {
-		rsrcVal, ok := resourceMap[objKey]
-		if !ok {
-			return false
-		}
-
-		if !reflect.DeepEqual(objVal, rsrcVal) {
-			return false
-		}
-	}
-	return true
-}
diff --git a/pkg/engine/variables/operator/in.go b/pkg/engine/variables/operator/in.go
index 055abd36d..bd510e101 100644
--- a/pkg/engine/variables/operator/in.go
+++ b/pkg/engine/variables/operator/in.go
@@ -110,19 +110,20 @@ func keyExistsInArray(key string, value interface{}, log logr.Logger) (invalidTy
 }
 
 func (in InHandler) validateValueWithStringSetPattern(key []string, value interface{}) (keyExists bool) {
-	invalidType, keyExists := setExistsInArray(key, value, in.log)
+	invalidType, isIn := setExistsInArray(key, value, in.log, false)
 	if invalidType {
 		in.log.Info("expected type []string", "value", value, "type", fmt.Sprintf("%T", value))
 		return false
 	}
 
-	return keyExists
+	return isIn
 }
 
 // setExistsInArray checks if the key is a subset of value
 // The value can be a string, an array of strings, or a JSON format
 // array of strings (e.g. ["val1", "val2", "val3"].
-func setExistsInArray(key []string, value interface{}, log logr.Logger) (invalidType bool, keyExists bool) {
+// notIn argument if set to true will check for NotIn
+func setExistsInArray(key []string, value interface{}, log logr.Logger, notIn bool) (invalidType bool, keyExists bool) {
 	switch valuesAvailable := value.(type) {
 
 	case []interface{}:
@@ -134,8 +135,10 @@ func setExistsInArray(key []string, value interface{}, log logr.Logger) (invalid
 			}
 			valueSlice = append(valueSlice, v)
 		}
-
-		return false, isSubset(key, valueSlice)
+		if notIn {
+			return false, isNotIn(key, valueSlice)
+		}
+		return false, isIn(key, valueSlice)
 
 	case string:
 
@@ -148,30 +151,47 @@ func setExistsInArray(key []string, value interface{}, log logr.Logger) (invalid
 			log.Error(err, "failed to unmarshal value to JSON string array", "key", key, "value", value)
 			return true, false
 		}
+		if notIn {
+			return false, isNotIn(key, arr)
+		}
 
-		return false, isSubset(key, arr)
+		return false, isIn(key, arr)
 
 	default:
 		return true, false
 	}
 }
 
-// isSubset checks if S1 is a subset of S2 i.e. ALL values of S1 are in S2
-func isSubset(key []string, value []string) bool {
-	set := make(map[string]int)
+// isIn checks if all values in S1 are in S2
+func isIn(key []string, value []string) bool {
+	set := make(map[string]bool)
 
 	for _, val := range value {
-		set[val]++
+		set[val] = true
 	}
 
 	for _, val := range key {
-		count, found := set[val]
+		_, found := set[val]
 		if !found {
 			return false
-		} else if count < 1 {
+		}
+	}
+
+	return true
+}
+
+// isNotIn checks if none of the values in S1 is in S2
+func isNotIn(key []string, value []string) bool {
+	set := make(map[string]bool)
+
+	for _, val := range value {
+		set[val] = true
+	}
+
+	for _, val := range key {
+		_, found := set[val]
+		if found {
 			return false
-		} else {
-			set[val] = count - 1
 		}
 	}
 
diff --git a/pkg/engine/variables/operator/notin.go b/pkg/engine/variables/operator/notin.go
index e75b89e86..d604c4b0d 100644
--- a/pkg/engine/variables/operator/notin.go
+++ b/pkg/engine/variables/operator/notin.go
@@ -64,13 +64,13 @@ func (nin NotInHandler) validateValueWithStringPattern(key string, value interfa
 }
 
 func (nin NotInHandler) validateValueWithStringSetPattern(key []string, value interface{}) bool {
-	invalidType, keyExists := setExistsInArray(key, value, nin.log)
+	invalidType, isNotIn := setExistsInArray(key, value, nin.log, true)
 	if invalidType {
 		nin.log.Info("expected type []string", "value", value, "type", fmt.Sprintf("%T", value))
 		return false
 	}
 
-	return !keyExists
+	return isNotIn
 }
 
 func (nin NotInHandler) validateValueWithBoolPattern(_ bool, _ interface{}) bool {
diff --git a/pkg/kyverno/apply/command.go b/pkg/kyverno/apply/command.go
index 6c53206f5..749e2b77b 100644
--- a/pkg/kyverno/apply/command.go
+++ b/pkg/kyverno/apply/command.go
@@ -205,6 +205,18 @@ func applyCommandHelper(resourcePaths []string, cluster bool, policyReport bool,
 		return validateEngineResponses, rc, resources, skippedPolicies, err
 	}
 
+	// empty the previous contents of the file just in case if the file already existed before with some content(so as to perform overwrites)
+	// the truncation of files for the case when mutateLogPath is dir, is handled under pkg/kyverno/apply/common.go
+	if !mutateLogPathIsDir {
+		_, err := os.OpenFile(mutateLogPath, os.O_TRUNC|os.O_WRONLY, 0644)
+		if err != nil {
+			if !sanitizederror.IsErrorSanitized(err) {
+				return validateEngineResponses, rc, resources, skippedPolicies, sanitizederror.NewWithError("failed to truncate the existing file at "+mutateLogPath, err)
+			}
+			return validateEngineResponses, rc, resources, skippedPolicies, err
+		}
+	}
+
 	mutatedPolicies, err := common.MutatePolices(policies)
 	if err != nil {
 		if !sanitizederror.IsErrorSanitized(err) {
diff --git a/pkg/kyverno/common/common.go b/pkg/kyverno/common/common.go
index 93c061ee2..c36ebd0c4 100644
--- a/pkg/kyverno/common/common.go
+++ b/pkg/kyverno/common/common.go
@@ -386,12 +386,24 @@ func ApplyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unst
 	rcError := false
 	engineResponses := make([]*response.EngineResponse, 0)
 	namespaceLabels := make(map[string]string)
-	resourceNamespace := resource.GetNamespace()
-	namespaceLabels = namespaceSelectorMap[resource.GetNamespace()]
 
-	if resourceNamespace != "default" && len(namespaceLabels) < 1 {
-		return engineResponses, &response.EngineResponse{}, responseError, rcError, sanitizederror.NewWithError(fmt.Sprintf("failed to get namesapce labels for resource %s. use --values-file flag to pass the namespace labels", resource.GetName()), nil)
+	policyWithNamespaceSelector := false
+	for _, p := range policy.Spec.Rules {
+		if p.MatchResources.ResourceDescription.NamespaceSelector != nil ||
+			p.ExcludeResources.ResourceDescription.NamespaceSelector != nil {
+			policyWithNamespaceSelector = true
+			break
+		}
+	}
+
+	if policyWithNamespaceSelector {
+		resourceNamespace := resource.GetNamespace()
+		namespaceLabels = namespaceSelectorMap[resource.GetNamespace()]
+		if resourceNamespace != "default" && len(namespaceLabels) < 1 {
+			return engineResponses, &response.EngineResponse{}, responseError, rcError, sanitizederror.NewWithError(fmt.Sprintf("failed to get namesapce labels for resource %s. use --values-file flag to pass the namespace labels", resource.GetName()), nil)
+		}
 	}
+
 	resPath := fmt.Sprintf("%s/%s/%s", resource.GetNamespace(), resource.GetKind(), resource.GetName())
 	log.Log.V(3).Info("applying policy on resource", "policy", policy.Name, "resource", resPath)
 
@@ -525,9 +537,10 @@ func PrintMutatedOutput(mutateLogPath string, mutateLogPathIsDir bool, yaml stri
 	yaml = yaml + ("\n---\n\n")
 
 	if !mutateLogPathIsDir {
+		// truncation for the case when mutateLogPath is a file (not a directory) is handled under pkg/kyverno/apply/command.go
 		f, err = os.OpenFile(mutateLogPath, os.O_APPEND|os.O_WRONLY, 0644)
 	} else {
-		f, err = os.OpenFile(mutateLogPath+"/"+fileName+".yaml", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
+		f, err = os.OpenFile(mutateLogPath+"/"+fileName+".yaml", os.O_CREATE|os.O_WRONLY, 0644)
 	}
 
 	if err != nil {
diff --git a/pkg/resourcecache/gvrcache.go b/pkg/resourcecache/gvrcache.go
index 8d8d76d0c..befc315a8 100644
--- a/pkg/resourcecache/gvrcache.go
+++ b/pkg/resourcecache/gvrcache.go
@@ -4,6 +4,7 @@ import (
 	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/client-go/dynamic/dynamiclister"
 	"k8s.io/client-go/informers"
+	"k8s.io/client-go/tools/cache"
 )
 
 // GenericCache - allows operation on a single resource
@@ -13,6 +14,7 @@ type GenericCache interface {
 	Lister() dynamiclister.Lister
 	NamespacedLister(namespace string) dynamiclister.NamespaceLister
 	GVR() schema.GroupVersionResource
+	GetInformer() cache.SharedIndexInformer
 }
 
 type genericCache struct {
@@ -56,3 +58,8 @@ func (gc *genericCache) Lister() dynamiclister.Lister {
 func (gc *genericCache) NamespacedLister(namespace string) dynamiclister.NamespaceLister {
 	return dynamiclister.New(gc.genericInformer.Informer().GetIndexer(), gc.GVR()).Namespace(namespace)
 }
+
+// GetInformer gets SharedIndexInformer
+func (gc *genericCache) GetInformer() cache.SharedIndexInformer {
+	return gc.genericInformer.Informer()
+}
diff --git a/pkg/resourcecache/main.go b/pkg/resourcecache/main.go
index b902c2f94..f8cc3c5f1 100644
--- a/pkg/resourcecache/main.go
+++ b/pkg/resourcecache/main.go
@@ -10,11 +10,15 @@ import (
 )
 
 // ResourceCache - allows the creation, deletion and saving the resource informers as a cache
+// the resource cache can be registered by gvks as follows:
+// - group/version/kind
+// - group/kind
+// - kind
 type ResourceCache interface {
-	CreateInformers(resources ...string) []error
-	CreateGVKInformer(kind string) (GenericCache, error)
-	StopResourceInformer(resource string)
-	GetGVRCache(resource string) (GenericCache, bool)
+	CreateInformers(gvks ...string) []error
+	CreateGVKInformer(gvk string) (GenericCache, error)
+	StopResourceInformer(gvk string)
+	GetGVRCache(gvk string) (GenericCache, bool)
 }
 
 type resourceCache struct {
diff --git a/pkg/tls/certRenewer.go b/pkg/tls/certRenewer.go
new file mode 100644
index 000000000..f4cb20581
--- /dev/null
+++ b/pkg/tls/certRenewer.go
@@ -0,0 +1,348 @@
+package tls
+
+import (
+	"crypto/tls"
+	"crypto/x509"
+	"encoding/base64"
+	"encoding/pem"
+	"fmt"
+	"time"
+
+	"github.com/cenkalti/backoff"
+	"github.com/go-logr/logr"
+	"github.com/kyverno/kyverno/pkg/config"
+	client "github.com/kyverno/kyverno/pkg/dclient"
+	"github.com/pkg/errors"
+	v1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	"k8s.io/client-go/rest"
+)
+
+const (
+	// ManagedByLabel is added to Kyverno managed secrets
+	ManagedByLabel string = "cert.kyverno.io/managed-by"
+
+	SelfSignedAnnotation    string = "self-signed-cert"
+	RootCAKey               string = "rootCA.crt"
+	rollingUpdateAnnotation string = "update.kyverno.io/force-rolling-update"
+)
+
+// CertRenewer creates rootCA and pem pair to register
+// webhook configurations and webhook server
+// renews RootCA at the given interval
+type CertRenewer struct {
+	client               *client.Client
+	clientConfig         *rest.Config
+	certRenewalInterval  time.Duration
+	certValidityDuration time.Duration
+	log                  logr.Logger
+}
+
+// NewCertRenewer returns an instance of CertRenewer
+func NewCertRenewer(client *client.Client, clientConfig *rest.Config, certRenewalInterval, certValidityDuration time.Duration, log logr.Logger) *CertRenewer {
+	return &CertRenewer{
+		client:               client,
+		clientConfig:         clientConfig,
+		certRenewalInterval:  certRenewalInterval,
+		certValidityDuration: certValidityDuration,
+		log:                  log,
+	}
+}
+
+// InitTLSPemPair Loads or creates PEM private key and TLS certificate for webhook server.
+// Created pair is stored in cluster's secret.
+// Returns struct with key/certificate pair.
+func (c *CertRenewer) InitTLSPemPair(serverIP string) (*PemPair, error) {
+	logger := c.log.WithName("InitTLSPemPair")
+	certProps, err := GetTLSCertProps(c.clientConfig)
+	if err != nil {
+		return nil, err
+	}
+
+	if valid, err := c.ValidCert(); err == nil && valid {
+		if tlsPair, err := ReadTLSPair(c.clientConfig, c.client); err == nil {
+			logger.Info("using existing TLS key/certificate pair")
+			return tlsPair, nil
+		}
+	} else {
+		logger.V(3).Info("unable to find TLS pair", "reason", err.Error())
+	}
+
+	logger.Info("building key/certificate pair for TLS")
+	return c.buildTLSPemPairAndWriteToSecrets(certProps, serverIP)
+}
+
+// buildTLSPemPairAndWriteToSecrets Issues TLS certificate for webhook server using self-signed CA cert
+// Returns signed and approved TLS certificate in PEM format
+func (c *CertRenewer) buildTLSPemPairAndWriteToSecrets(props CertificateProps, serverIP string) (*PemPair, error) {
+	caCert, caPEM, err := GenerateCACert(c.certValidityDuration)
+	if err != nil {
+		return nil, err
+	}
+
+	if err := c.WriteCACertToSecret(caPEM, props); err != nil {
+		return nil, fmt.Errorf("failed to write CA cert to secret: %v", err)
+	}
+
+	tlsPair, err := GenerateCertPem(caCert, props, serverIP, c.certValidityDuration)
+	if err != nil {
+		return nil, err
+	}
+
+	if err = c.WriteTLSPairToSecret(props, tlsPair); err != nil {
+		return nil, fmt.Errorf("unable to save TLS pair to the cluster: %v", err)
+	}
+
+	return tlsPair, nil
+}
+
+// ReadTLSPair Reads the pair of TLS certificate and key from the specified secret.
+
+// WriteCACertToSecret stores the CA cert in secret
+func (c *CertRenewer) WriteCACertToSecret(caPEM *PemPair, props CertificateProps) error {
+	logger := c.log.WithName("CAcert")
+	name := generateRootCASecretName(props)
+
+	secretUnstr, err := c.client.GetResource("", "Secret", props.Namespace, name)
+	if err != nil {
+		secret := &v1.Secret{
+			TypeMeta: metav1.TypeMeta{
+				Kind:       "Secret",
+				APIVersion: "v1",
+			},
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      name,
+				Namespace: props.Namespace,
+				Annotations: map[string]string{
+					SelfSignedAnnotation: "true",
+				},
+				Labels: map[string]string{
+					ManagedByLabel: "kyverno",
+				},
+			},
+			Data: map[string][]byte{
+				RootCAKey: caPEM.Certificate,
+			},
+			Type: v1.SecretTypeOpaque,
+		}
+
+		_, err := c.client.CreateResource("", "Secret", props.Namespace, secret, false)
+		if err == nil {
+			logger.Info("secret created", "name", name, "namespace", props.Namespace)
+		}
+		return err
+	}
+
+	if _, ok := secretUnstr.GetAnnotations()[SelfSignedAnnotation]; !ok {
+		secretUnstr.SetAnnotations(map[string]string{SelfSignedAnnotation: "true"})
+	}
+
+	dataMap := map[string]interface{}{
+		RootCAKey: base64.StdEncoding.EncodeToString(caPEM.Certificate)}
+
+	if err := unstructured.SetNestedMap(secretUnstr.Object, dataMap, "data"); err != nil {
+		return err
+	}
+
+	_, err = c.client.UpdateResource("", "Secret", props.Namespace, secretUnstr, false)
+	if err != nil {
+		return err
+	}
+	logger.Info("secret updated", "name", name, "namespace", props.Namespace)
+	return nil
+}
+
+// WriteTLSPairToSecret Writes the pair of TLS certificate and key to the specified secret.
+// Updates existing secret or creates new one.
+func (c *CertRenewer) WriteTLSPairToSecret(props CertificateProps, pemPair *PemPair) error {
+	logger := c.log.WithName("WriteTLSPair")
+
+	name := generateTLSPairSecretName(props)
+	secretUnstr, err := c.client.GetResource("", "Secret", props.Namespace, name)
+	if err != nil {
+		secret := &v1.Secret{
+			TypeMeta: metav1.TypeMeta{
+				Kind:       "Secret",
+				APIVersion: "v1",
+			},
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      name,
+				Namespace: props.Namespace,
+				Labels: map[string]string{
+					ManagedByLabel: "kyverno",
+				},
+			},
+			Data: map[string][]byte{
+				v1.TLSCertKey:       pemPair.Certificate,
+				v1.TLSPrivateKeyKey: pemPair.PrivateKey,
+			},
+			Type: v1.SecretTypeTLS,
+		}
+
+		_, err := c.client.CreateResource("", "Secret", props.Namespace, secret, false)
+		if err == nil {
+			logger.Info("secret created", "name", name, "namespace", props.Namespace)
+		}
+		return err
+	}
+
+	dataMap := map[string][]byte{
+		v1.TLSCertKey:       pemPair.Certificate,
+		v1.TLSPrivateKeyKey: pemPair.PrivateKey,
+	}
+
+	secret, err := convertToSecret(secretUnstr)
+	if err != nil {
+		return err
+	}
+
+	secret.Data = dataMap
+	_, err = c.client.UpdateResource("", "Secret", props.Namespace, secret, false)
+	if err != nil {
+		return err
+	}
+
+	logger.Info("secret updated", "name", name, "namespace", props.Namespace)
+	return nil
+}
+
+// RollingUpdate triggers a rolling update of Kyverno pod.
+// It is used when the rootCA is renewed, the restart of
+// Kyverno pod will register webhook server with new cert
+func (c *CertRenewer) RollingUpdate() error {
+
+	update := func() error {
+		deploy, err := c.client.GetResource("", "Deployment", config.KyvernoNamespace, config.KyvernoDeploymentName)
+		if err != nil {
+			return errors.Wrap(err, "failed to find Kyverno")
+		}
+
+		if IsKyvernoIsInRollingUpdate(deploy.UnstructuredContent(), c.log) {
+			return nil
+		}
+
+		annotations, ok, err := unstructured.NestedStringMap(deploy.UnstructuredContent(), "spec", "template", "metadata", "annotations")
+		if err != nil {
+			return errors.Wrap(err, "bad annotations")
+		}
+
+		if !ok {
+			annotations = map[string]string{}
+		}
+
+		annotations[rollingUpdateAnnotation] = time.Now().String()
+		if err = unstructured.SetNestedStringMap(deploy.UnstructuredContent(),
+			annotations,
+			"spec", "template", "metadata", "annotations",
+		); err != nil {
+			return errors.Wrapf(err, "set annotation %s", rollingUpdateAnnotation)
+		}
+
+		if _, err = c.client.UpdateResource("", "Deployment", config.KyvernoNamespace, deploy, false); err != nil {
+			return errors.Wrap(err, "update Kyverno deployment")
+		}
+		return nil
+	}
+
+	exbackoff := &backoff.ExponentialBackOff{
+		InitialInterval:     500 * time.Millisecond,
+		RandomizationFactor: 0.5,
+		Multiplier:          1.5,
+		MaxInterval:         time.Second,
+		MaxElapsedTime:      3 * time.Second,
+		Clock:               backoff.SystemClock,
+	}
+
+	exbackoff.Reset()
+	return backoff.Retry(update, exbackoff)
+}
+
+// ValidCert validates the CA Cert
+func (c *CertRenewer) ValidCert() (bool, error) {
+	logger := c.log.WithName("ValidCert")
+
+	rootCA, err := ReadRootCASecret(c.clientConfig, c.client)
+	if err != nil {
+		return false, errors.Wrap(err, "unable to read CA from secret")
+	}
+
+	tlsPair, err := ReadTLSPair(c.clientConfig, c.client)
+	if err != nil {
+		// wait till next reconcile
+		logger.Info("unable to read TLS PEM Pair from secret", "reason", err.Error())
+		return false, errors.Wrap(err, "unable to read TLS PEM Pair from secret")
+	}
+
+	// build cert pool
+	pool := x509.NewCertPool()
+	caPem, _ := pem.Decode(rootCA)
+	if caPem == nil {
+		logger.Error(err, "bad certificate")
+		return false, nil
+	}
+
+	cac, err := x509.ParseCertificate(caPem.Bytes)
+	if err != nil {
+		logger.Error(err, "failed to parse CA cert")
+		return false, nil
+	}
+	pool.AddCert(cac)
+
+	// valid PEM pair
+	_, err = tls.X509KeyPair(tlsPair.Certificate, tlsPair.PrivateKey)
+	if err != nil {
+		logger.Error(err, "invalid PEM pair")
+		return false, nil
+	}
+
+	certPem, _ := pem.Decode(tlsPair.Certificate)
+	if certPem == nil {
+		logger.Error(err, "bad private key")
+		return false, nil
+	}
+
+	cert, err := x509.ParseCertificate(certPem.Bytes)
+	if err != nil {
+		logger.Error(err, "failed to parse cert")
+		return false, nil
+	}
+
+	if _, err = cert.Verify(x509.VerifyOptions{
+		Roots:       pool,
+		CurrentTime: time.Now().Add(c.certRenewalInterval),
+	}); err != nil {
+		logger.Error(err, "invalid cert")
+		return false, nil
+	}
+
+	return true, nil
+}
+
+// IsKyvernoIsInRollingUpdate returns true if Kyverno is in rolling update
+func IsKyvernoIsInRollingUpdate(deploy map[string]interface{}, logger logr.Logger) bool {
+	replicas, _, err := unstructured.NestedInt64(deploy, "spec", "replicas")
+	if err != nil {
+		logger.Error(err, "unable to fetch spec.replicas")
+	}
+
+	nonTerminatedReplicas, _, err := unstructured.NestedInt64(deploy, "status", "replicas")
+	if err != nil {
+		logger.Error(err, "unable to fetch status.replicas")
+	}
+
+	if nonTerminatedReplicas > replicas {
+		logger.Info("detect Kyverno is in rolling update, won't trigger the update again")
+		return true
+	}
+
+	return false
+}
+
+func generateTLSPairSecretName(props CertificateProps) string {
+	return generateInClusterServiceName(props) + ".kyverno-tls-pair"
+}
+
+func generateRootCASecretName(props CertificateProps) string {
+	return generateInClusterServiceName(props) + ".kyverno-tls-ca"
+}
diff --git a/pkg/tls/reader.go b/pkg/tls/reader.go
new file mode 100644
index 000000000..4ddebc9a2
--- /dev/null
+++ b/pkg/tls/reader.go
@@ -0,0 +1,106 @@
+package tls
+
+import (
+	"fmt"
+	"net/url"
+
+	"github.com/kyverno/kyverno/pkg/config"
+	client "github.com/kyverno/kyverno/pkg/dclient"
+	"github.com/pkg/errors"
+	v1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/client-go/rest"
+)
+
+// ReadRootCASecret returns the RootCA from the pre-defined secret
+func ReadRootCASecret(restConfig *rest.Config, client *client.Client) (result []byte, err error) {
+	certProps, err := GetTLSCertProps(restConfig)
+	if err != nil {
+		return nil, errors.Wrap(err, "failed to get TLS Cert Properties")
+	}
+
+	sname := generateRootCASecretName(certProps)
+	stlsca, err := client.GetResource("", "Secret", certProps.Namespace, sname)
+	if err != nil {
+		return nil, err
+	}
+
+	tlsca, err := convertToSecret(stlsca)
+	if err != nil {
+		return nil, errors.Wrapf(err, "failed to convert secret %s/%s", certProps.Namespace, sname)
+	}
+
+	result = tlsca.Data[RootCAKey]
+	if len(result) == 0 {
+		return nil, errors.Errorf("root CA certificate not found in secret %s/%s", certProps.Namespace, tlsca.Name)
+	}
+
+	return result, nil
+}
+
+// ReadTLSPair returns the pem pair from the pre-defined secret
+func ReadTLSPair(restConfig *rest.Config, client *client.Client) (*PemPair, error) {
+	certProps, err := GetTLSCertProps(restConfig)
+	if err != nil {
+		return nil, errors.Wrap(err, "failed to get TLS Cert Properties")
+	}
+
+	sname := generateTLSPairSecretName(certProps)
+	unstrSecret, err := client.GetResource("", "Secret", certProps.Namespace, sname)
+	if err != nil {
+		return nil, fmt.Errorf("failed to get secret %s/%s: %v", certProps.Namespace, sname, err)
+	}
+
+	// If secret contains annotation 'self-signed-cert', then it's created using helper scripts to setup self-signed certificates.
+	// As the root CA used to sign the certificate is required for webhook configuration, check if the corresponding secret is created
+	annotations := unstrSecret.GetAnnotations()
+	if _, ok := annotations[SelfSignedAnnotation]; ok {
+		sname := generateRootCASecretName(certProps)
+		_, err := client.GetResource("", "Secret", certProps.Namespace, sname)
+		if err != nil {
+			return nil, fmt.Errorf("rootCA secret is required while using self-signed certificate TLS pair, defaulting to generating new TLS pair  %s/%s", certProps.Namespace, sname)
+		}
+	}
+	secret, err := convertToSecret(unstrSecret)
+	if err != nil {
+		return nil, err
+	}
+
+	pemPair := PemPair{
+		Certificate: secret.Data[v1.TLSCertKey],
+		PrivateKey:  secret.Data[v1.TLSPrivateKeyKey],
+	}
+
+	if len(pemPair.Certificate) == 0 {
+		return nil, fmt.Errorf("TLS Certificate not found in secret %s/%s", certProps.Namespace, sname)
+	}
+	if len(pemPair.PrivateKey) == 0 {
+		return nil, fmt.Errorf("TLS PrivateKey not found in secret %s/%s", certProps.Namespace, sname)
+	}
+
+	return &pemPair, nil
+}
+
+//GetTLSCertProps provides the TLS Certificate Properties
+func GetTLSCertProps(configuration *rest.Config) (certProps CertificateProps, err error) {
+	apiServerURL, err := url.Parse(configuration.Host)
+	if err != nil {
+		return certProps, err
+	}
+
+	certProps = CertificateProps{
+		Service:       config.KyvernoServiceName,
+		Namespace:     config.KyvernoNamespace,
+		APIServerHost: apiServerURL.Hostname(),
+	}
+	return certProps, nil
+}
+
+func convertToSecret(obj *unstructured.Unstructured) (v1.Secret, error) {
+	secret := v1.Secret{}
+	if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), &secret); err != nil {
+		return secret, err
+	}
+	return secret, nil
+}
diff --git a/pkg/tls/tls.go b/pkg/tls/tls.go
index 023db9e69..880dc9f6e 100644
--- a/pkg/tls/tls.go
+++ b/pkg/tls/tls.go
@@ -14,7 +14,11 @@ import (
 	"time"
 )
 
-const certValidityDuration = 10 * 365 * 24 * time.Hour
+// CertRenewalInterval is the renewal interval for rootCA
+const CertRenewalInterval time.Duration = 12 * time.Hour
+
+// CertValidityDuration is the valid duration for a new cert
+const CertValidityDuration time.Duration = 365 * 24 * time.Hour
 
 // CertificateProps Properties of TLS certificate which should be issued for webhook server
 type CertificateProps struct {
@@ -63,7 +67,7 @@ func CertificateToPem(certificateDER []byte) []byte {
 
 // GenerateCACert creates the self-signed CA cert and private key
 // it will be used to sign the webhook server certificate
-func GenerateCACert() (*KeyPair, *PemPair, error) {
+func GenerateCACert(certValidityDuration time.Duration) (*KeyPair, *PemPair, error) {
 	now := time.Now()
 	begin := now.Add(-1 * time.Hour)
 	end := now.Add(certValidityDuration)
@@ -110,7 +114,7 @@ func GenerateCACert() (*KeyPair, *PemPair, error) {
 
 // GenerateCertPem takes the results of GenerateCACert and uses it to create the
 // PEM-encoded public certificate and private key, respectively
-func GenerateCertPem(caCert *KeyPair, props CertificateProps, serverIP string) (*PemPair, error) {
+func GenerateCertPem(caCert *KeyPair, props CertificateProps, serverIP string, certValidityDuration time.Duration) (*PemPair, error) {
 	now := time.Now()
 	begin := now.Add(-1 * time.Hour)
 	end := now.Add(certValidityDuration)
@@ -121,7 +125,7 @@ func GenerateCertPem(caCert *KeyPair, props CertificateProps, serverIP string) (
 
 	dnsNames[1] = fmt.Sprintf("%s.%s", props.Service, props.Namespace)
 	// The full service name is the CommonName for the certificate
-	commonName := GenerateInClusterServiceName(props)
+	commonName := generateInClusterServiceName(props)
 	dnsNames[2] = fmt.Sprintf("%s", commonName)
 
 	var ips []net.IP
@@ -174,7 +178,7 @@ func GenerateCertPem(caCert *KeyPair, props CertificateProps, serverIP string) (
 }
 
 //GenerateInClusterServiceName The generated service name should be the common name for TLS certificate
-func GenerateInClusterServiceName(props CertificateProps) string {
+func generateInClusterServiceName(props CertificateProps) string {
 	return props.Service + "." + props.Namespace + ".svc"
 }
 
diff --git a/pkg/webhookconfig/common.go b/pkg/webhookconfig/common.go
index 0ec76c895..58a3a2b0d 100644
--- a/pkg/webhookconfig/common.go
+++ b/pkg/webhookconfig/common.go
@@ -4,28 +4,34 @@ import (
 	"io/ioutil"
 
 	"github.com/kyverno/kyverno/pkg/config"
+	"github.com/kyverno/kyverno/pkg/tls"
 	admregapi "k8s.io/api/admissionregistration/v1beta1"
 	apps "k8s.io/api/apps/v1"
 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/runtime"
 	rest "k8s.io/client-go/rest"
 )
 
 func (wrc *Register) readCaData() []byte {
-	logger := wrc.log
+	logger := wrc.log.WithName("readCaData")
 	var caData []byte
+	var err error
+
 	// Check if ca is defined in the secret tls-ca
 	// assume the key and signed cert have been defined in secret tls.kyverno
-	if caData = wrc.client.ReadRootCASecret(); len(caData) != 0 {
+	if caData, err = tls.ReadRootCASecret(wrc.clientConfig, wrc.client); err == nil {
 		logger.V(4).Info("read CA from secret")
 		return caData
 	}
-	logger.V(4).Info("failed to read CA from secret, reading from kubeconfig")
+
+	logger.V(4).Info("failed to read CA from secret, reading from kubeconfig", "reason", err.Error())
 	// load the CA from kubeconfig
 	if caData = extractCA(wrc.clientConfig); len(caData) != 0 {
 		logger.V(4).Info("read CA from kubeconfig")
 		return caData
 	}
+
 	logger.V(4).Info("failed to read CA from kubeconfig")
 	return nil
 }
@@ -49,8 +55,8 @@ func extractCA(config *rest.Config) (result []byte) {
 
 func (wrc *Register) constructOwner() v1.OwnerReference {
 	logger := wrc.log
-	kubePolicyDeployment, err := wrc.getKubePolicyDeployment()
 
+	kubePolicyDeployment, _, err := wrc.GetKubePolicyDeployment()
 	if err != nil {
 		logger.Error(err, "failed to construct OwnerReference")
 		return v1.OwnerReference{}
@@ -64,17 +70,18 @@ func (wrc *Register) constructOwner() v1.OwnerReference {
 	}
 }
 
-func (wrc *Register) getKubePolicyDeployment() (*apps.Deployment, error) {
+// GetKubePolicyDeployment gets Kyverno deployment
+func (wrc *Register) GetKubePolicyDeployment() (*apps.Deployment, *unstructured.Unstructured, error) {
 	lister, _ := wrc.resCache.GetGVRCache("Deployment")
 	kubePolicyDeployment, err := lister.NamespacedLister(config.KyvernoNamespace).Get(config.KyvernoDeploymentName)
 	if err != nil {
-		return nil, err
+		return nil, nil, err
 	}
 	deploy := apps.Deployment{}
 	if err = runtime.DefaultUnstructuredConverter.FromUnstructured(kubePolicyDeployment.UnstructuredContent(), &deploy); err != nil {
-		return nil, err
+		return nil, kubePolicyDeployment, err
 	}
-	return &deploy, nil
+	return &deploy, kubePolicyDeployment, nil
 }
 
 // debug mutating webhook
diff --git a/pkg/webhookconfig/monitor.go b/pkg/webhookconfig/monitor.go
index af59210c9..b39ecbe96 100644
--- a/pkg/webhookconfig/monitor.go
+++ b/pkg/webhookconfig/monitor.go
@@ -2,12 +2,18 @@ package webhookconfig
 
 import (
 	"fmt"
+	"os"
+	"reflect"
 	"sync"
 	"time"
 
 	"github.com/go-logr/logr"
-	dclient "github.com/kyverno/kyverno/pkg/dclient"
+	"github.com/kyverno/kyverno/pkg/config"
 	"github.com/kyverno/kyverno/pkg/event"
+	"github.com/kyverno/kyverno/pkg/resourcecache"
+	"github.com/kyverno/kyverno/pkg/tls"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	"k8s.io/client-go/tools/cache"
 )
 
 //maxRetryCount defines the max deadline count
@@ -28,17 +34,34 @@ const (
 // like the webhook settings.
 //
 type Monitor struct {
-	t   time.Time
-	mu  sync.RWMutex
-	log logr.Logger
+	t           time.Time
+	mu          sync.RWMutex
+	secretQueue chan bool
+	log         logr.Logger
 }
 
-//NewMonitor returns a new instance of LastRequestTime store
-func NewMonitor(log logr.Logger) *Monitor {
-	return &Monitor{
-		t:   time.Now(),
-		log: log,
+//NewMonitor returns a new instance of webhook monitor
+func NewMonitor(resCache resourcecache.ResourceCache, log logr.Logger) *Monitor {
+	monitor := &Monitor{
+		t:           time.Now(),
+		secretQueue: make(chan bool, 1),
+		log:         log,
 	}
+
+	var err error
+	secretCache, ok := resCache.GetGVRCache("Secret")
+	if !ok {
+		if secretCache, err = resCache.CreateGVKInformer("Secret"); err != nil {
+			log.Error(err, "unable to start Secret's informer")
+		}
+	}
+
+	secretCache.GetInformer().AddEventHandler(cache.ResourceEventHandlerFuncs{
+		AddFunc:    monitor.addSecretFunc,
+		UpdateFunc: monitor.updateSecretFunc,
+	})
+
+	return monitor
 }
 
 //Time returns the last request time
@@ -56,18 +79,59 @@ func (t *Monitor) SetTime(tm time.Time) {
 	t.t = tm
 }
 
+func (t *Monitor) addSecretFunc(obj interface{}) {
+	secret := obj.(*unstructured.Unstructured)
+	if secret.GetNamespace() != config.KyvernoNamespace {
+		return
+	}
+
+	val, ok := secret.GetAnnotations()[tls.SelfSignedAnnotation]
+	if !ok || val != "true" {
+		return
+	}
+
+	t.secretQueue <- true
+}
+
+func (t *Monitor) updateSecretFunc(oldObj interface{}, newObj interface{}) {
+	old := oldObj.(*unstructured.Unstructured)
+	new := newObj.(*unstructured.Unstructured)
+	if new.GetNamespace() != config.KyvernoNamespace {
+		return
+	}
+
+	val, ok := new.GetAnnotations()[tls.SelfSignedAnnotation]
+	if !ok || val != "true" {
+		return
+	}
+
+	if reflect.DeepEqual(old.UnstructuredContent()["data"], new.UnstructuredContent()["data"]) {
+		return
+	}
+
+	t.secretQueue <- true
+	t.log.V(4).Info("secret updated, reconciling webhook configurations")
+}
+
 //Run runs the checker and verify the resource update
-func (t *Monitor) Run(register *Register, eventGen event.Interface, client *dclient.Client, stopCh <-chan struct{}) {
+func (t *Monitor) Run(register *Register, certRenewer *tls.CertRenewer, eventGen event.Interface, stopCh <-chan struct{}) {
 	logger := t.log
 	logger.V(4).Info("starting webhook monitor", "interval", idleCheckInterval)
-	status := newStatusControl(client, eventGen, logger.WithName("WebhookStatusControl"))
+	status := newStatusControl(register.client, eventGen, logger.WithName("WebhookStatusControl"))
 
 	ticker := time.NewTicker(tickerInterval)
 	defer ticker.Stop()
 
+	certsRenewalTicker := time.NewTicker(tls.CertRenewalInterval)
+	defer certsRenewalTicker.Stop()
+
 	for {
 		select {
 		case <-ticker.C:
+			if skipWebhookCheck(register, logger.WithName("statusCheck/skipWebhookCheck")) {
+				logger.Info("skip validating webhook status, Kyverno is in rolling update")
+				continue
+			}
 
 			if err := register.Check(); err != nil {
 				t.log.Error(err, "missing webhooks")
@@ -95,6 +159,10 @@ func (t *Monitor) Run(register *Register, eventGen event.Interface, client *dcli
 
 			if timeDiff > idleCheckInterval {
 				logger.V(1).Info("webhook idle time exceeded", "deadline", idleCheckInterval)
+				if skipWebhookCheck(register, logger.WithName("skipWebhookCheck")) {
+					logger.Info("skip validating webhook status, Kyverno is in rolling update")
+					continue
+				}
 
 				// send request to update the Kyverno deployment
 				if err := status.IncrementAnnotation(); err != nil {
@@ -110,6 +178,40 @@ func (t *Monitor) Run(register *Register, eventGen event.Interface, client *dcli
 				logger.Error(err, "failed to annotate deployment webhook status to success")
 			}
 
+		case <-certsRenewalTicker.C:
+			valid, err := certRenewer.ValidCert()
+			if err != nil {
+				logger.Error(err, "failed to validate cert")
+				continue
+			}
+
+			if valid {
+				continue
+			}
+
+			logger.Info("rootCA is about to expire, trigger a rolling update to renew the cert")
+			if err := certRenewer.RollingUpdate(); err != nil {
+				logger.Error(err, "unable to trigger a rolling update to renew rootCA, force restarting")
+				os.Exit(1)
+			}
+
+		case <-t.secretQueue:
+			valid, err := certRenewer.ValidCert()
+			if err != nil {
+				logger.Error(err, "failed to validate cert")
+				continue
+			}
+
+			if valid {
+				continue
+			}
+
+			logger.Info("rootCA has changed, updating webhook configurations")
+			if err := certRenewer.RollingUpdate(); err != nil {
+				logger.Error(err, "unable to trigger a rolling update to re-register webhook server, force restarting")
+				os.Exit(1)
+			}
+
 		case <-stopCh:
 			// handler termination signal
 			logger.V(2).Info("stopping webhook monitor")
@@ -117,3 +219,14 @@ func (t *Monitor) Run(register *Register, eventGen event.Interface, client *dcli
 		}
 	}
 }
+
+// skipWebhookCheck returns true if Kyverno is in rolling update
+func skipWebhookCheck(register *Register, logger logr.Logger) bool {
+	_, deploy, err := register.GetKubePolicyDeployment()
+	if err != nil {
+		logger.Info("unable to get Kyverno deployment", "reason", err.Error())
+		return false
+	}
+
+	return tls.IsKyvernoIsInRollingUpdate(deploy.UnstructuredContent(), logger)
+}
diff --git a/pkg/webhookconfig/registration.go b/pkg/webhookconfig/registration.go
index 64ace56bf..aef5331a4 100644
--- a/pkg/webhookconfig/registration.go
+++ b/pkg/webhookconfig/registration.go
@@ -11,9 +11,11 @@ import (
 	"github.com/kyverno/kyverno/pkg/config"
 	client "github.com/kyverno/kyverno/pkg/dclient"
 	"github.com/kyverno/kyverno/pkg/resourcecache"
+	"github.com/kyverno/kyverno/pkg/tls"
 	admregapi "k8s.io/api/admissionregistration/v1beta1"
 	errorsapi "k8s.io/apimachinery/pkg/api/errors"
 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	rest "k8s.io/client-go/rest"
 )
 
@@ -64,24 +66,29 @@ func (wrc *Register) Register() error {
 
 	wrc.removeWebhookConfigurations()
 
+	caData := wrc.readCaData()
+	if caData == nil {
+		return errors.New("Unable to extract CA data from configuration")
+	}
+
 	errors := make([]string, 0)
-	if err := wrc.createVerifyMutatingWebhookConfiguration(); err != nil {
+	if err := wrc.createVerifyMutatingWebhookConfiguration(caData); err != nil {
 		errors = append(errors, err.Error())
 	}
 
-	if err := wrc.createPolicyValidatingWebhookConfiguration(); err != nil {
+	if err := wrc.createPolicyValidatingWebhookConfiguration(caData); err != nil {
 		errors = append(errors, err.Error())
 	}
 
-	if err := wrc.createPolicyMutatingWebhookConfiguration(); err != nil {
+	if err := wrc.createPolicyMutatingWebhookConfiguration(caData); err != nil {
 		errors = append(errors, err.Error())
 	}
 
-	if err := wrc.createResourceValidatingWebhookConfiguration(); err != nil {
+	if err := wrc.createResourceValidatingWebhookConfiguration(caData); err != nil {
 		errors = append(errors, err.Error())
 	}
 
-	if err := wrc.createResourceMutatingWebhookConfiguration(); err != nil {
+	if err := wrc.createResourceMutatingWebhookConfiguration(caData); err != nil {
 		errors = append(errors, err.Error())
 	}
 
@@ -122,19 +129,46 @@ func (wrc *Register) Check() error {
 
 // Remove removes all webhook configurations
 func (wrc *Register) Remove(cleanUp chan<- struct{}) {
+	defer close(cleanUp)
+	if !wrc.cleanupKyvernoResource() {
+		return
+	}
+
 	wrc.removeWebhookConfigurations()
-	close(cleanUp)
+	wrc.removeSecrets()
 }
 
-func (wrc *Register) createResourceMutatingWebhookConfiguration() error {
+// cleanupKyvernoResource returns true if Kyverno deployment is terminating
+func (wrc *Register) cleanupKyvernoResource() bool {
+	logger := wrc.log.WithName("cleanupKyvernoResource")
+	deploy, err := wrc.client.GetResource("", "Deployment", deployNamespace, deployName)
+	if err != nil {
+		logger.Error(err, "failed to get deployment")
+		return false
+	}
 
-	var caData []byte
-	var config *admregapi.MutatingWebhookConfiguration
+	if deploy.GetDeletionTimestamp() != nil {
+		logger.Info("Kyverno is terminating, clean up Kyverno resources")
+		return true
+	}
 
-	if caData = wrc.readCaData(); caData == nil {
-		return errors.New("Unable to extract CA data from configuration")
+	replicas, _, err := unstructured.NestedInt64(deploy.UnstructuredContent(), "spec", "replicas")
+	if err != nil {
+		logger.Error(err, "unable to fetch spec.replicas of Kyverno deployment")
 	}
 
+	if replicas == 0 {
+		logger.Info("Kyverno is scaled to zero, clean up Kyverno resources")
+		return true
+	}
+
+	logger.Info("updating Kyverno Pod, won't clean up Kyverno resources")
+	return false
+}
+
+func (wrc *Register) createResourceMutatingWebhookConfiguration(caData []byte) error {
+	var config *admregapi.MutatingWebhookConfiguration
+
 	if wrc.serverIP != "" {
 		config = wrc.constructDebugMutatingWebhookConfig(caData)
 	} else {
@@ -158,13 +192,9 @@ func (wrc *Register) createResourceMutatingWebhookConfiguration() error {
 	return nil
 }
 
-func (wrc *Register) createResourceValidatingWebhookConfiguration() error {
-	var caData []byte
+func (wrc *Register) createResourceValidatingWebhookConfiguration(caData []byte) error {
 	var config *admregapi.ValidatingWebhookConfiguration
 
-	if caData = wrc.readCaData(); caData == nil {
-		return errors.New("Unable to extract CA data from configuration")
-	}
 	if wrc.serverIP != "" {
 		config = wrc.constructDebugValidatingWebhookConfig(caData)
 	} else {
@@ -189,15 +219,9 @@ func (wrc *Register) createResourceValidatingWebhookConfiguration() error {
 }
 
 //registerPolicyValidatingWebhookConfiguration create a Validating webhook configuration for Policy CRD
-func (wrc *Register) createPolicyValidatingWebhookConfiguration() error {
-	var caData []byte
+func (wrc *Register) createPolicyValidatingWebhookConfiguration(caData []byte) error {
 	var config *admregapi.ValidatingWebhookConfiguration
 
-	// read certificate data
-	if caData = wrc.readCaData(); caData == nil {
-		return errors.New("Unable to extract CA data from configuration")
-	}
-
 	if wrc.serverIP != "" {
 		config = wrc.contructDebugPolicyValidatingWebhookConfig(caData)
 	} else {
@@ -217,14 +241,9 @@ func (wrc *Register) createPolicyValidatingWebhookConfiguration() error {
 	return nil
 }
 
-func (wrc *Register) createPolicyMutatingWebhookConfiguration() error {
-	var caData []byte
+func (wrc *Register) createPolicyMutatingWebhookConfiguration(caData []byte) error {
 	var config *admregapi.MutatingWebhookConfiguration
 
-	if caData = wrc.readCaData(); caData == nil {
-		return errors.New("Unable to extract CA data from configuration")
-	}
-
 	if wrc.serverIP != "" {
 		config = wrc.contructDebugPolicyMutatingWebhookConfig(caData)
 	} else {
@@ -245,14 +264,9 @@ func (wrc *Register) createPolicyMutatingWebhookConfiguration() error {
 	return nil
 }
 
-func (wrc *Register) createVerifyMutatingWebhookConfiguration() error {
-	var caData []byte
+func (wrc *Register) createVerifyMutatingWebhookConfiguration(caData []byte) error {
 	var config *admregapi.MutatingWebhookConfiguration
 
-	if caData = wrc.readCaData(); caData == nil {
-		return errors.New("Unable to extract CA data from configuration")
-	}
-
 	if wrc.serverIP != "" {
 		config = wrc.constructDebugVerifyMutatingWebhookConfig(caData)
 	} else {
@@ -435,3 +449,24 @@ func (wrc *Register) getVerifyWebhookMutatingWebhookName() string {
 func (wrc *Register) GetWebhookTimeOut() time.Duration {
 	return time.Duration(wrc.timeoutSeconds)
 }
+
+// removeSecrets removes Kyverno managed secrets
+func (wrc *Register) removeSecrets() {
+	selector := &v1.LabelSelector{
+		MatchLabels: map[string]string{
+			tls.ManagedByLabel: "kyverno",
+		},
+	}
+
+	secretList, err := wrc.client.ListResource("", "Secret", config.KyvernoNamespace, selector)
+	if err != nil && errorsapi.IsNotFound(err) {
+		wrc.log.Error(err, "failed to clean up Kyverno managed secrets")
+		return
+	}
+
+	for _, secret := range secretList.Items {
+		if err := wrc.client.DeleteResource("", "Secret", secret.GetNamespace(), secret.GetName(), false); err != nil {
+			wrc.log.Error(err, "failed to delete secret", "ns", secret.GetNamespace(), "name", secret.GetName())
+		}
+	}
+}
diff --git a/pkg/webhooks/mutation.go b/pkg/webhooks/mutation.go
index 5efad0131..ccc590fd1 100644
--- a/pkg/webhooks/mutation.go
+++ b/pkg/webhooks/mutation.go
@@ -1,6 +1,7 @@
 package webhooks
 
 import (
+	"errors"
 	"reflect"
 	"sort"
 	"time"
@@ -68,7 +69,7 @@ func (ws *WebhookServer) HandleMutation(
 		}
 
 		if !engineResponse.IsSuccessful() && len(engineResponse.GetFailedRules()) > 0 {
-			logger.Info("failed to apply policy", "policy", policy.Name, "failed rules", engineResponse.GetFailedRules())
+			logger.Error(errors.New("some rules failed"), "failed to apply policy", "policy", policy.Name, "failed rules", engineResponse.GetFailedRules())
 			continue
 		}
 
@@ -112,7 +113,7 @@ func (ws *WebhookServer) HandleMutation(
 
 		// if any of the policies fails, print out the error
 		if !isResponseSuccessful(engineResponses) {
-			logger.Info("failed to apply mutation rules on the resource, reporting policy violation", "errors", getErrorMsg(engineResponses))
+			logger.Error(errors.New(getErrorMsg(engineResponses)), "failed to apply mutation rules on the resource, reporting policy violation")
 		}
 	}()
 
diff --git a/pkg/webhooks/server.go b/pkg/webhooks/server.go
index 14d279135..7a4873067 100644
--- a/pkg/webhooks/server.go
+++ b/pkg/webhooks/server.go
@@ -27,6 +27,7 @@ import (
 	"github.com/kyverno/kyverno/pkg/policyreport"
 	"github.com/kyverno/kyverno/pkg/policystatus"
 	"github.com/kyverno/kyverno/pkg/resourcecache"
+	ktls "github.com/kyverno/kyverno/pkg/tls"
 	tlsutils "github.com/kyverno/kyverno/pkg/tls"
 	userinfo "github.com/kyverno/kyverno/pkg/userinfo"
 	"github.com/kyverno/kyverno/pkg/utils"
@@ -104,6 +105,8 @@ type WebhookServer struct {
 	// last request time
 	webhookMonitor *webhookconfig.Monitor
 
+	certRenewer *ktls.CertRenewer
+
 	// policy report generator
 	prGenerator policyreport.GeneratorInterface
 
@@ -148,6 +151,7 @@ func NewWebhookServer(
 	pCache policycache.Interface,
 	webhookRegistrationClient *webhookconfig.Register,
 	webhookMonitor *webhookconfig.Monitor,
+	certRenewer *ktls.CertRenewer,
 	statusSync policystatus.Listener,
 	configHandler config.Interface,
 	prGenerator policyreport.GeneratorInterface,
@@ -198,6 +202,7 @@ func NewWebhookServer(
 		configHandler:         configHandler,
 		cleanUp:               cleanUp,
 		webhookMonitor:        webhookMonitor,
+		certRenewer:           certRenewer,
 		prGenerator:           prGenerator,
 		grGenerator:           grGenerator,
 		grController:          grc,
@@ -512,7 +517,7 @@ func (ws *WebhookServer) RunAsync(stopCh <-chan struct{}) {
 	logger.Info("starting service")
 
 	if !ws.debug {
-		go ws.webhookMonitor.Run(ws.webhookRegister, ws.eventGen, ws.client, stopCh)
+		go ws.webhookMonitor.Run(ws.webhookRegister, ws.certRenewer, ws.eventGen, stopCh)
 	}
 }
 


Test patch:
diff --git a/pkg/engine/apiPath_test.go b/pkg/engine/apiPath_test.go
index 8879b377f..8942c12b4 100644
--- a/pkg/engine/apiPath_test.go
+++ b/pkg/engine/apiPath_test.go
@@ -26,3 +26,26 @@ func Test_Paths(t *testing.T) {
 	f("/apis/gloo.solo.io/v1/namespaces/gloo-system/upstreams/  ", "/apis/gloo.solo.io/v1/namespaces/gloo-system/upstreams")
 	f("  /apis/gloo.solo.io/v1/namespaces/gloo-system/upstreams", "/apis/gloo.solo.io/v1/namespaces/gloo-system/upstreams")
 }
+
+func Test_GroupVersions(t *testing.T) {
+	f := func(path, expected string) {
+		p, err := NewAPIPath(path)
+		if err != nil {
+			t.Error(err)
+			return
+		}
+
+		if p.Root == "api" {
+			if p.Group != expected {
+				t.Errorf("expected %s got %s", expected, p.Group)
+			}
+		} else {
+			if p.Version != expected {
+				t.Errorf("expected %s got %s", expected, p.Version)
+			}
+		}
+	}
+
+	f("/api/v1/namespace/{{ request.namespace }}", "v1")
+	f("/apis/extensions/v1beta1/namespaces/example/ingresses", "extensions/v1beta1")
+}
diff --git a/pkg/engine/jsonContext_test.go b/pkg/engine/jsonContext_test.go
new file mode 100644
index 000000000..0bb4c6545
--- /dev/null
+++ b/pkg/engine/jsonContext_test.go
@@ -0,0 +1,71 @@
+package engine
+
+import (
+	"bytes"
+	"encoding/json"
+	"gotest.tools/assert"
+	"testing"
+)
+
+func Test_parseMultilineBlockBody(t *testing.T) {
+	tcs := []struct {
+		multilineBlockRaw         []byte
+		expectedMultilineBlockRaw []byte
+		expectedErr               bool
+	}{
+		{
+			multilineBlockRaw: []byte(`{
+				"key1": "value",
+				"key2": "value2",
+				"key3": "word1\nword2\nword3",
+				"key4": "word4\n"
+			}`),
+			expectedMultilineBlockRaw: []byte(`{"key1":"value","key2":"value2","key3":["word1","word2","word3"],"key4":"word4"}`),
+			expectedErr:               false,
+		},
+		{
+			multilineBlockRaw: []byte(`{
+				"key1": "value",
+				"key2": "value2",
+				"key3": "word1\nword2\nword3",
+				"key4": "word4"
+			}`),
+			expectedMultilineBlockRaw: []byte(`{"key1":"value","key2":"value2","key3":["word1","word2","word3"],"key4":"word4"}`),
+			expectedErr:               false,
+		},
+		{
+			multilineBlockRaw: []byte(`{
+				"key1": "value1",
+				"key2": "value2\n",
+				"key3": "word1",
+				"key4": "word2"
+			}`),
+			expectedMultilineBlockRaw: []byte(`{"key1":"value1","key2":["value2",""]}`),
+			expectedErr:               true,
+		},
+		{
+			multilineBlockRaw: []byte(`{
+				"key1": "value1",
+				"key2": "[\"cluster-admin\", \"cluster-operator\", \"tenant-admin\"]"
+			}`),
+			expectedMultilineBlockRaw: []byte(`{"key1":"value1","key2":"[\"cluster-admin\", \"cluster-operator\", \"tenant-admin\"]"}`),
+			expectedErr:               false,
+		},
+	}
+
+	for _, tc := range tcs {
+		var multilineBlock map[string]interface{}
+		err := json.Unmarshal(tc.multilineBlockRaw, &multilineBlock)
+		assert.NilError(t, err)
+
+		parsedMultilineBlock := parseMultilineBlockBody(multilineBlock)
+		parsedMultilineBlockRaw, err := json.Marshal(parsedMultilineBlock)
+		assert.NilError(t, err)
+
+		if tc.expectedErr {
+			assert.Assert(t, bytes.Compare(parsedMultilineBlockRaw, tc.expectedMultilineBlockRaw) != 0)
+		} else {
+			assert.Assert(t, bytes.Compare(parsedMultilineBlockRaw, tc.expectedMultilineBlockRaw) == 0)
+		}
+	}
+}
diff --git a/pkg/engine/mutate/patchesUtils_test.go b/pkg/engine/mutate/patchesUtils_test.go
index 75ad93a06..c49ee138e 100644
--- a/pkg/engine/mutate/patchesUtils_test.go
+++ b/pkg/engine/mutate/patchesUtils_test.go
@@ -1,16 +1,12 @@
 package mutate
 
 import (
-	"encoding/json"
 	"fmt"
 	"testing"
 
 	"github.com/mattbaird/jsonpatch"
 	assertnew "github.com/stretchr/testify/assert"
 	"gotest.tools/assert"
-	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
-	"sigs.k8s.io/controller-runtime/pkg/log"
-	yaml "sigs.k8s.io/yaml"
 )
 
 func Test_GeneratePatches(t *testing.T) {
@@ -139,120 +135,6 @@ var overlayBytes = []byte(`
 
 var expectBytes = []byte(`{"apiVersion": "apps/v1","kind": "Deployment","metadata": {"name": "wordpress","labels": {"app": "wordpress"}},"spec": {"selector": {"matchLabels": {"app": "wordpress"}},"strategy": {"type": "Recreate"},"template": {"metadata": {"labels": {"app": "wordpress"}},"spec": {"containers": [{"name": "nginx","image": "nginx"},{"image": "wordpress:4.8-apache","name": "wordpress","ports": [{"containerPort": 80,"name": "wordpress"}],"volumeMounts": [{"name": "wordpress-persistent-storage","mountPath": "/var/www/html"}],"env": [{"name": "WORDPRESS_DB_HOST","value": "$(MYSQL_SERVICE)"},{"name": "WORDPRESS_DB_PASSWORD","valueFrom": {"secretKeyRef": {"name": "mysql-pass","key": "password"}}}]}],"volumes": [{"name": "wordpress-persistent-storage"}],"initContainers": [{"name": "init-command","image": "debian","command": ["echo $(WORDPRESS_SERVICE)","echo $(MYSQL_SERVICE)"]}]}}}}`)
 
-var podBytes = []byte(`
-{
-  "kind": "Pod",
-  "apiVersion": "v1",
-  "metadata": {
-      "name": "nginx"
-  },
-  "spec": {
-      "containers": [
-          {
-              "name": "nginx",
-              "image": "nginx:latest"
-          },
-          {
-            "name": "nginx-new",
-            "image": "nginx:latest"
-          }
-      ]
-  }
-}
-`)
-
-func Test_preProcessJSONPatches_skip(t *testing.T) {
-	patchesJSON6902 := []byte(`
-- op: add
-  path: /spec/containers/1
-  value: {"name":"nginx-new","image":"nginx:latest"}
-`)
-	var pod unstructured.Unstructured
-	assertnew.Nil(t, json.Unmarshal(podBytes, &pod))
-
-	patches, err := yaml.YAMLToJSON(patchesJSON6902)
-	assertnew.Nil(t, err)
-
-	skip, err := preProcessJSONPatches(patches, pod, log.Log)
-	assertnew.Nil(t, err)
-	assertnew.Equal(t, true, skip)
-}
-
-func Test_preProcessJSONPatches_not_skip(t *testing.T) {
-	patchesJSON6902 := []byte(`
-- op: add
-  path: /spec/containers/1
-  value: {"name":"my-new-container","image":"nginx:latest"}
-`)
-
-	patches, err := yaml.YAMLToJSON(patchesJSON6902)
-	assertnew.Nil(t, err)
-
-	var pod unstructured.Unstructured
-	assertnew.Nil(t, json.Unmarshal(podBytes, &pod))
-
-	skip, err := preProcessJSONPatches(patches, pod, log.Log)
-	assertnew.Nil(t, err)
-	assertnew.Equal(t, false, skip)
-}
-
-func Test_isSubsetObject_true(t *testing.T) {
-	var object, resource interface{}
-
-	objectRaw := []byte(`{"image": "nginx:latest","name": "nginx-new"}`)
-	resourceRaw := []byte(`{"image": "nginx:latest","name": "random-name"}`)
-	assertnew.Nil(t, json.Unmarshal(objectRaw, &object))
-	assertnew.Nil(t, json.Unmarshal(resourceRaw, &resource))
-	assertnew.Equal(t, false, isSubsetObject(object, resource))
-
-	resourceRawNew := []byte(`{"image": "nginx:latest","name": "nginx-new"}`)
-	assertnew.Nil(t, json.Unmarshal(resourceRawNew, &resource))
-	assertnew.Equal(t, true, isSubsetObject(object, resource))
-}
-
-func Test_getObject_notPresent(t *testing.T) {
-	path := "/spec/random/1"
-	var pod unstructured.Unstructured
-
-	assertnew.Nil(t, json.Unmarshal(podBytes, &pod))
-	_, err := getObject(path, pod.UnstructuredContent())
-	expectedErr := "referenced value does not exist at spec/random"
-	assertnew.Equal(t, err.Error(), expectedErr)
-}
-
-func Test_getObject_outOfIndex(t *testing.T) {
-	path := "/spec/containers/2"
-	var pod unstructured.Unstructured
-
-	assertnew.Nil(t, json.Unmarshal(podBytes, &pod))
-	object, err := getObject(path, pod.UnstructuredContent())
-	assertnew.Nil(t, err)
-	assertnew.Nil(t, object)
-
-}
-
-func Test_getObject_success(t *testing.T) {
-	path := "/spec/containers/1"
-	var pod unstructured.Unstructured
-	expectedObject := map[string]interface{}{"image": "nginx:latest", "name": "nginx-new"}
-
-	assertnew.Nil(t, json.Unmarshal(podBytes, &pod))
-	object, err := getObject(path, pod.UnstructuredContent())
-	assertnew.Nil(t, err)
-	assertnew.Equal(t, expectedObject, object)
-}
-
-func Test_getObject_get_last_element(t *testing.T) {
-	path := "/spec/containers/-"
-	var pod unstructured.Unstructured
-	expectedObject := map[string]interface{}{"image": "nginx:latest", "name": "nginx-new"}
-
-	assertnew.Nil(t, json.Unmarshal(podBytes, &pod))
-	object, err := getObject(path, pod.UnstructuredContent())
-	assertnew.Nil(t, err)
-	assertnew.Equal(t, expectedObject, object)
-}
-
 func Test_ignorePath(t *testing.T) {
 	tests := []struct {
 		path   string
diff --git a/pkg/engine/variables/evaluate_test.go b/pkg/engine/variables/evaluate_test.go
index bbdcace2a..723c21319 100644
--- a/pkg/engine/variables/evaluate_test.go
+++ b/pkg/engine/variables/evaluate_test.go
@@ -1069,7 +1069,7 @@ func Test_Eval_In_String_Set_Fail(t *testing.T) {
 // test passes if ALL of the values in "key" are NOT in "value" ("key" is not a subset of "value")
 func Test_Eval_NotIn_String_Set_Pass(t *testing.T) {
 	ctx := context.NewContext()
-	key := [2]string{"1.1.1.1", "4.4.4.4"}
+	key := [2]string{"4.4.4.4", "5.5.5.5"}
 	keyInterface := make([]interface{}, len(key), len(key))
 	for i := range key {
 		keyInterface[i] = key[i]
@@ -1094,7 +1094,7 @@ func Test_Eval_NotIn_String_Set_Pass(t *testing.T) {
 // test passes if ALL of the values in "key" are in "value" ("key" is a subset of "value")
 func Test_Eval_NotIn_String_Set_Fail(t *testing.T) {
 	ctx := context.NewContext()
-	key := [2]string{"1.1.1.1", "2.2.2.2"}
+	key := [2]string{"1.1.1.1", "4.4.4.4"}
 	keyInterface := make([]interface{}, len(key), len(key))
 	for i := range key {
 		keyInterface[i] = key[i]
diff --git a/pkg/kyverno/test/command.go b/pkg/kyverno/test/command.go
index 5544dff31..fa589a991 100644
--- a/pkg/kyverno/test/command.go
+++ b/pkg/kyverno/test/command.go
@@ -114,6 +114,7 @@ func testCommandExecute(dirPath []string, valuesFile string, fileName string) (r
 	var errors []error
 	fs := memfs.New()
 	rc = &resultCounts{}
+	var testYamlCount int
 	if len(dirPath) == 0 {
 		return rc, sanitizederror.NewWithError(fmt.Sprintf("a directory is required"), err)
 	}
@@ -123,19 +124,20 @@ func testCommandExecute(dirPath []string, valuesFile string, fileName string) (r
 			return rc, sanitizederror.NewWithError("failed to parse URL", err)
 		}
 		pathElems := strings.Split(gitURL.Path[1:], "/")
-		if len(pathElems) != 3 {
+		if len(pathElems) <= 2 {
 			err := fmt.Errorf("invalid URL path %s - expected https://github.com/:owner/:repository/:branch", gitURL.Path)
 			fmt.Printf("Error: failed to parse URL \nCause: %s\n", err)
 			os.Exit(1)
 		}
-		gitURL.Path = strings.Join([]string{"/", pathElems[0], pathElems[1]}, "/")
+		gitURL.Path = strings.Join([]string{pathElems[0], pathElems[1]}, "/")
 		repoURL := gitURL.String()
-		cloneRepo, err := clone(repoURL, fs)
-		if err != nil {
-			fmt.Printf("Error: failed to clone repository \nCause: %s\n", err)
+		branch := strings.ReplaceAll(dirPath[0], repoURL+"/", "")
+		_, cloneErr := clone(repoURL, fs, branch)
+		if cloneErr != nil {
+			fmt.Printf("Error: failed to clone repository \nCause: %s\n", cloneErr)
+			log.Log.V(3).Info(fmt.Sprintf("failed to clone repository  %v as it is not valid", repoURL), "error", cloneErr)
 			os.Exit(1)
 		}
-		log.Log.V(3).Info(" clone repository", cloneRepo)
 		policyYamls, err := listYAMLs(fs, "/")
 		if err != nil {
 			return rc, sanitizederror.NewWithError("failed to list YAMLs in repository", err)
@@ -144,6 +146,7 @@ func testCommandExecute(dirPath []string, valuesFile string, fileName string) (r
 		for _, yamlFilePath := range policyYamls {
 			file, err := fs.Open(yamlFilePath)
 			if strings.Contains(file.Name(), fileName) {
+				testYamlCount++
 				policyresoucePath := strings.Trim(yamlFilePath, fileName)
 				bytes, err := ioutil.ReadAll(file)
 				if err != nil {
@@ -169,7 +172,7 @@ func testCommandExecute(dirPath []string, valuesFile string, fileName string) (r
 		if err != nil {
 			errors = append(errors, err)
 		}
-		err := getLocalDirTestFiles(fs, path, fileName, valuesFile, rc)
+		err := getLocalDirTestFiles(fs, path, fileName, valuesFile, rc, testYamlCount)
 		if err != nil {
 			errors = append(errors, err)
 		}
@@ -183,21 +186,25 @@ func testCommandExecute(dirPath []string, valuesFile string, fileName string) (r
 	if rc.fail > 0 {
 		os.Exit(1)
 	}
+	if testYamlCount == 0 {
+		fmt.Printf("\n No test yamls available \n")
+	}
 	os.Exit(0)
 	return rc, nil
 }
 
-func getLocalDirTestFiles(fs billy.Filesystem, path, fileName, valuesFile string, rc *resultCounts) error {
+func getLocalDirTestFiles(fs billy.Filesystem, path, fileName, valuesFile string, rc *resultCounts, testYamlCount int) error {
 	files, err := ioutil.ReadDir(path)
 	if err != nil {
 		return fmt.Errorf("failed to read %v: %v", path, err.Error())
 	}
 	for _, file := range files {
 		if file.IsDir() {
-			getLocalDirTestFiles(fs, filepath.Join(path, file.Name()), fileName, valuesFile, rc)
+			getLocalDirTestFiles(fs, filepath.Join(path, file.Name()), fileName, valuesFile, rc, testYamlCount)
 			continue
 		}
 		if strings.Contains(file.Name(), fileName) {
+			testYamlCount++
 			yamlFile, err := ioutil.ReadFile(filepath.Join(path, file.Name()))
 			if err != nil {
 				sanitizederror.NewWithError("unable to read yaml", err)
diff --git a/pkg/kyverno/test/git.go b/pkg/kyverno/test/git.go
index c6fc8adf8..efd28f66d 100644
--- a/pkg/kyverno/test/git.go
+++ b/pkg/kyverno/test/git.go
@@ -1,18 +1,22 @@
 package test
 
 import (
+	"fmt"
 	"os"
 	"path/filepath"
 
 	"github.com/go-git/go-billy/v5"
 	"github.com/go-git/go-git/v5"
+	"github.com/go-git/go-git/v5/plumbing"
 	"github.com/go-git/go-git/v5/storage/memory"
 )
 
-func clone(path string, fs billy.Filesystem) (*git.Repository, error) {
+func clone(path string, fs billy.Filesystem, branch string) (*git.Repository, error) {
 	return git.Clone(memory.NewStorage(), fs, &git.CloneOptions{
-		URL:      path,
-		Progress: os.Stdout,
+		URL:           path,
+		ReferenceName: plumbing.ReferenceName(fmt.Sprintf("refs/heads/%s", branch)),
+		Progress:      os.Stdout,
+		SingleBranch:  true,
 	})
 }