Repository: flant/shell-operator
Pull request #536 (2023-10-06 19:21:46)

Refactor internals. Make the operator more lib-oriented
<!--
Thank you for sending a pull request! Here some tips for contributors:

1. Fill the description template below.
2. Include appropriate tests (if necessary). Make sure that all CI checks passed.
3. If the Pull Request is a work in progress, make use of GitHub's "Draft PR" feature and mark it as such.
-->

#### Overview

Refactor everything:
- golangci-lint updated to 1.54.2
- matrix test now have kubernetes versions 1.23-1.27
- `gopkg.in/satori/go.uuid.v1` lib changed with `github.com/gofrs/uuid/v5`
- kube-client lib updated from 0.25.4 to 0.26.9
- `HookMetricsListenPort` was removed
- debug server refactored
- unused Interfaces were removed
- package level structured was moved to unexported
- dump of the `main` queue respects output format
- start of the api-http server was moved to the operator Start() function

#### What this PR does / why we need it

Hide unused structs / methods. Make the shell-operator more lib-oriented to reuse in other projects

#### Special notes for your reviewer

```NOTE
`--hook-metrics-listen-port`  was removed. HTTP handler `/metrics/hooks` integrated into base http server, configured via the `--listen-port` flag
```



Patch:
diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml
index a1e24a5..9033248 100644
--- a/.github/workflows/lint.yaml
+++ b/.github/workflows/lint.yaml
@@ -36,7 +36,7 @@ jobs:
 
       - name: Run golangci-lint
         run: |
-          curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b . v1.52.2
+          curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b . v1.54.2
           ./golangci-lint run --sort-results --build-tags integration,test
 
 
diff --git a/.golangci.yaml b/.golangci.yaml
index 2bf8930..4ec3d5e 100644
--- a/.golangci.yaml
+++ b/.golangci.yaml
@@ -37,6 +37,16 @@ linters-settings:
       - prefix(github.com/flant/)
   goimports:
     local-prefixes: github.com/flant/
+  nolintlint:
+    allow-unused: true
+  depguard:
+    rules:
+      Main:
+        files:
+          - $all
+        deny:
+          - pkg: "gopkg.in/satori/go.uuid.v1"
+            desc: "Use https://github.com/gofrs/uuid instead. Satori/go.uuid is no longer maintained and has critical vulnerabilities."
 issues:
   exclude:
     # Using underscores is a common practice, refactor in the future
diff --git a/go.mod b/go.mod
index 373e4f8..a5c7703 100644
--- a/go.mod
+++ b/go.mod
@@ -3,13 +3,14 @@ module github.com/flant/shell-operator
 go 1.19
 
 require (
-	github.com/flant/kube-client v0.26.1
+	github.com/flant/kube-client v1.0.0
 	github.com/flant/libjq-go v1.6.3-0.20201126171326-c46a40ff22ee // branch: master
 	github.com/go-chi/chi/v5 v5.0.10
 	github.com/go-openapi/spec v0.19.8
 	github.com/go-openapi/strfmt v0.19.5
-	github.com/go-openapi/swag v0.19.14
+	github.com/go-openapi/swag v0.21.1
 	github.com/go-openapi/validate v0.19.12
+	github.com/gofrs/uuid/v5 v5.0.0
 	github.com/hashicorp/go-multierror v1.1.1
 	github.com/kennygrant/sanitize v1.2.4
 	github.com/onsi/ginkgo v1.16.5
@@ -21,12 +22,11 @@ require (
 	golang.org/x/time v0.3.0
 	gopkg.in/alecthomas/kingpin.v2 v2.2.6
 	gopkg.in/robfig/cron.v2 v2.0.0-20150107220207-be2e0b0deed5
-	gopkg.in/satori/go.uuid.v1 v1.2.0
 	gopkg.in/yaml.v3 v3.0.1
-	k8s.io/api v0.25.4
-	k8s.io/apiextensions-apiserver v0.25.4
-	k8s.io/apimachinery v0.25.4
-	k8s.io/client-go v0.25.4
+	k8s.io/api v0.26.9
+	k8s.io/apiextensions-apiserver v0.26.9
+	k8s.io/apimachinery v0.26.9
+	k8s.io/client-go v0.26.9
 	sigs.k8s.io/yaml v1.3.0
 )
 
@@ -34,23 +34,20 @@ require (
 replace github.com/go-openapi/validate => github.com/flant/go-openapi-validate v0.19.12-flant.0
 
 require (
-	cloud.google.com/go v0.97.0 // indirect
-	github.com/PuerkitoBio/purell v1.1.1 // indirect
-	github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
 	github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
 	github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
 	github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
-	github.com/emicklei/go-restful/v3 v3.8.0 // indirect
-	github.com/evanphx/json-patch v4.12.0+incompatible // indirect
-	github.com/fsnotify/fsnotify v1.4.9 // indirect
+	github.com/emicklei/go-restful/v3 v3.9.0 // indirect
+	github.com/evanphx/json-patch v5.6.0+incompatible // indirect
+	github.com/fsnotify/fsnotify v1.6.0 // indirect
 	github.com/go-logr/logr v1.2.4 // indirect
 	github.com/go-openapi/analysis v0.19.10 // indirect
 	github.com/go-openapi/errors v0.19.7 // indirect
 	github.com/go-openapi/jsonpointer v0.19.5 // indirect
-	github.com/go-openapi/jsonreference v0.19.5 // indirect
+	github.com/go-openapi/jsonreference v0.20.0 // indirect
 	github.com/go-openapi/loads v0.19.5 // indirect
 	github.com/go-openapi/runtime v0.19.16 // indirect
 	github.com/go-stack/stack v1.8.0 // indirect
@@ -60,13 +57,14 @@ require (
 	github.com/google/btree v1.0.1 // indirect
 	github.com/google/gnostic v0.5.7-v3refs // indirect
 	github.com/google/go-cmp v0.5.9 // indirect
-	github.com/google/gofuzz v1.1.0 // indirect
+	github.com/google/gofuzz v1.2.0 // indirect
+	github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
 	github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
-	github.com/hashicorp/errwrap v1.0.0 // indirect
-	github.com/imdario/mergo v0.3.7 // indirect
+	github.com/hashicorp/errwrap v1.1.0 // indirect
+	github.com/imdario/mergo v0.3.15 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
-	github.com/mailru/easyjson v0.7.6 // indirect
+	github.com/mailru/easyjson v0.7.7 // indirect
 	github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
 	github.com/mitchellh/mapstructure v1.4.1 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
@@ -80,6 +78,7 @@ require (
 	github.com/prometheus/procfs v0.10.1 // indirect
 	github.com/rogpeppe/go-internal v1.10.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
+	github.com/tidwall/pretty v1.2.0 // indirect
 	go.mongodb.org/mongo-driver v1.5.4 // indirect
 	golang.org/x/net v0.12.0 // indirect
 	golang.org/x/oauth2 v0.5.0 // indirect
@@ -92,9 +91,9 @@ require (
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
-	k8s.io/klog/v2 v2.70.1 // indirect
-	k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect
-	k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect
+	k8s.io/klog/v2 v2.80.1 // indirect
+	k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
+	k8s.io/utils v0.0.0-20221107191617-1a15be271d1d // indirect
 	sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
 	sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
 
diff --git a/go.sum b/go.sum
index 39f9ca4..cbd1252 100644
--- a/go.sum
+++ b/go.sum
@@ -1,56 +1,7 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
-cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
-cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
-cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
-cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
-cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
-cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
-cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
-cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
-cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
-cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
-cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
-cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
-cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
-cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
-cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
-cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
-cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
-cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
-cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
-cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
-cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
-cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
-cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
-cloud.google.com/go v0.97.0 h1:3DXvAyifywvq64LfkKaMOmkWPS1CikIQdMe2lY9vxU8=
-cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
-cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
-cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
-cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
-cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
-cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
-cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
-cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
-cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
-cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
-cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
-cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
-cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
-cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
-cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
-cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
-cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
-cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
-dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
-github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
 github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
-github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
 github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
-github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
 github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
 github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
@@ -58,7 +9,6 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
 github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
 github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
 github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
-github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
 github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
 github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
@@ -68,52 +18,37 @@ github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
 github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
 github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
 github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
-github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
-github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
-github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
-github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
-github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw=
-github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
-github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE=
+github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
 github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
-github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
-github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
-github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
-github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
-github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
-github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84=
-github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
+github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
+github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 github.com/flant/go-openapi-validate v0.19.12-flant.0 h1:xk6kvc9fHKMgUdB6J7kbpbLR5vJOUzKAK8p3nrD7mDk=
 github.com/flant/go-openapi-validate v0.19.12-flant.0/go.mod h1:Rzou8hA/CBw8donlS6WNEUQupNvUZ0waH08tGe6kAQ4=
-github.com/flant/kube-client v0.26.1 h1:QIT/Skmdv5Mpu8OWBzncmZdtlKXDKzkyhte7wlXnbVE=
-github.com/flant/kube-client v0.26.1/go.mod h1:BPNhiy57FgJmnSBXy0l8AwBN6F9SHOfgFgHi3UG2Jrw=
+github.com/flant/kube-client v1.0.0 h1:hoP0qB75cb3qQZw5N29rgPNhX3KC2MuxT/By3IkXxxc=
+github.com/flant/kube-client v1.0.0/go.mod h1:YVcJ8PxomM0iYsK7nj2I3lmog2D0j/GloJfLYnhjlls=
 github.com/flant/libjq-go v1.6.3-0.20201126171326-c46a40ff22ee h1:evii83J+/6QGNvyf6tjQ/p27DPY9iftxIBb37ALJRTg=
 github.com/flant/libjq-go v1.6.3-0.20201126171326-c46a40ff22ee/go.mod h1:f+REaGl/+pZR97rbTcwHEka/MAipoQQ2Mc0iQUj4ak0=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
-github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
-github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
+github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
 github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
 github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk=
 github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
-github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
-github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
 github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
 github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
 github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
@@ -134,8 +69,8 @@ github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34
 github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
 github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
 github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
-github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=
-github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
+github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA=
+github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
 github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
 github.com/go-openapi/loads v0.19.5 h1:jZVYWawIQiA1NBnHla28ktg6hrcfTHsCE+3QLVRBIls=
 github.com/go-openapi/loads v0.19.5/go.mod h1:dswLCAdonkRufe/gSUC3gN8nTSaB9uaS2es0x5/IbjY=
@@ -154,8 +89,8 @@ github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh
 github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
 github.com/go-openapi/swag v0.19.7/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
 github.com/go-openapi/swag v0.19.9/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
-github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng=
-github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
+github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU=
+github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
 github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
 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=
@@ -186,26 +121,15 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe
 github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
 github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
 github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
+github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M=
+github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-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=
-github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
-github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
-github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
-github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
-github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
-github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
-github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
 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/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=
 github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
 github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
 github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
@@ -214,16 +138,11 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
 github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
 github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
 github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
 github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
-github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
 github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
 github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54=
@@ -232,60 +151,29 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
 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/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.4.1/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.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
 github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 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=
-github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
-github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
-github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
-github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
-github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
+github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
 github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 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/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
 github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=
 github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
-github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
-github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
 github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
+github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
 github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
 github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
-github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
-github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
-github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
-github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI=
-github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
+github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM=
+github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
 github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
@@ -294,8 +182,6 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm
 github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
 github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
 github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
-github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
-github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
 github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
 github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
 github.com/kennygrant/sanitize v1.2.4 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o=
@@ -318,8 +204,9 @@ github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN
 github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
-github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
 github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
 github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
 github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
 github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
@@ -369,7 +256,6 @@ github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI
 github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
 github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
 github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
-github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@@ -381,8 +267,6 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
 github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
-github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
-github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
 github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@@ -399,8 +283,9 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
 github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
+github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
 github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
 github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
 github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
@@ -408,128 +293,47 @@ github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6
 github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
 github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
 github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
-github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
 go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE=
 go.mongodb.org/mongo-driver v1.3.4/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE=
 go.mongodb.org/mongo-driver v1.5.4 h1:NPIBF/lxEcKNfWwoCJRX8+dMVwecWf9q3qUJkuh75oM=
 go.mongodb.org/mongo-driver v1.5.4/go.mod h1:gRXCHX4Jo7J0IJ1oDQyUxF7jfy19UfxniMS4xxMmUqw=
-go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
-go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
-go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
-go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
-go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
-golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
-golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
-golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
-golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
-golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
-golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
-golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
-golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
-golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
-golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
-golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
-golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
-golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
-golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
-golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
-golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
 golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-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-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200513185701-a91f0712d120/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-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
-golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
 golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
-golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
 golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s=
 golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -539,86 +343,36 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/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-20200113162924-86b910548bc1/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=
-golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
 golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
 golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
-golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 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.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
 golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-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/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
 golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -627,185 +381,33 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm
 golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
-golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
-golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
-golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
-golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
-golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
 golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
 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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
-google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
-google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
-google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
-google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
-google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
-google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
-google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
-google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
-google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
-google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
-google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
-google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
-google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
-google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
-google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
-google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
-google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
-google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
-google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
-google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
-google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
-google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/appengine v1.5.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/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
 google.golang.org/appengine v1.6.7/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=
-google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
-google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
-google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
-google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
-google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
-google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
-google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
-google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
-google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
-google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
-google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
-google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
-google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
-google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
-google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
-google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
-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=
-google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
-google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
-google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
-google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
-google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
-google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
-google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
-google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
-google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -815,10 +417,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
-google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
 google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
@@ -834,13 +434,10 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 gopkg.in/robfig/cron.v2 v2.0.0-20150107220207-be2e0b0deed5 h1:E846t8CnR+lv5nE+VuiKTDG/v1U2stad0QzddfJC7kY=
 gopkg.in/robfig/cron.v2 v2.0.0-20150107220207-be2e0b0deed5/go.mod h1:hiOFpYm0ZJbusNj2ywpbrXowU3G8U6GIQzqn2mw1UIE=
-gopkg.in/satori/go.uuid.v1 v1.2.0 h1:AH9uksa7bGe9rluapecRKBCpZvxaBEyu0RepitcD0Hw=
-gopkg.in/satori/go.uuid.v1 v1.2.0/go.mod h1:kjjdhYBBaa5W5DYP+OcVG3fRM6VWu14hqDYST4Zvw+E=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -852,30 +449,21 @@ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
-honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-k8s.io/api v0.25.4 h1:3YO8J4RtmG7elEgaWMb4HgmpS2CfY1QlaOz9nwB+ZSs=
-k8s.io/api v0.25.4/go.mod h1:IG2+RzyPQLllQxnhzD8KQNEu4c4YvyDTpSMztf4A0OQ=
-k8s.io/apiextensions-apiserver v0.25.4 h1:7hu9pF+xikxQuQZ7/30z/qxIPZc2J1lFElPtr7f+B6U=
-k8s.io/apiextensions-apiserver v0.25.4/go.mod h1:bkSGki5YBoZWdn5pWtNIdGvDrrsRWlmnvl9a+tAw5vQ=
-k8s.io/apimachinery v0.25.4 h1:CtXsuaitMESSu339tfhVXhQrPET+EiWnIY1rcurKnAc=
-k8s.io/apimachinery v0.25.4/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo=
-k8s.io/client-go v0.25.4 h1:3RNRDffAkNU56M/a7gUfXaEzdhZlYhoW8dgViGy5fn8=
-k8s.io/client-go v0.25.4/go.mod h1:8trHCAC83XKY0wsBIpbirZU4NTUpbuhc2JnI7OruGZw=
-k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
-k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ=
-k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
-k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA=
-k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU=
-k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4=
-k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
-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=
+k8s.io/api v0.26.9 h1:s8Y+G1u2JM55b90+Yo2RVb3PGT/hkWNVPN4idPERxJg=
+k8s.io/api v0.26.9/go.mod h1:W/W4fEWRVzPD36820LlVUQfNBiSbiq0VPWRFJKwzmUg=
+k8s.io/apiextensions-apiserver v0.26.9 h1:aJqWRuBj9i9J6tIDniqUDYM5QCRajTKXK/GO+zEccGQ=
+k8s.io/apiextensions-apiserver v0.26.9/go.mod h1:L1uysxOP2kC1vkZTlHGUlUl5WSpa7e4GHJmGEZY7yLg=
+k8s.io/apimachinery v0.26.9 h1:5yAV9cFR7Z4gIorKcAjWnx4uxtxiFsERwq4Pvmx0CCg=
+k8s.io/apimachinery v0.26.9/go.mod h1:qYzLkrQ9lhrZRh0jNKo2cfvf/R1/kQONnSiyB7NUJU0=
+k8s.io/client-go v0.26.9 h1:TGWi/6guEjIgT0Hg871Gsmx0qFuoGyGFjlFedrk7It0=
+k8s.io/client-go v0.26.9/go.mod h1:tU1FZS0bwAmAFyPYpZycUQrQnUMzQ5MHloop7EbX6ow=
+k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4=
+k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
+k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E=
+k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4=
+k8s.io/utils v0.0.0-20221107191617-1a15be271d1d h1:0Smp/HP1OH4Rvhe+4B8nWGERtlqAGSftbSbbmm45oFs=
+k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
 sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k=
 sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
 sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
diff --git a/pkg/app/app.go b/pkg/app/app.go
index 3f80cb3..2431870 100644
--- a/pkg/app/app.go
+++ b/pkg/app/app.go
@@ -20,10 +20,9 @@ var (
 )
 
 var (
-	Namespace             = ""
-	ListenAddress         = "0.0.0.0"
-	ListenPort            = "9115"
-	HookMetricsListenPort = ""
+	Namespace     = ""
+	ListenAddress = "0.0.0.0"
+	ListenPort    = "9115"
 )
 
 var PrometheusMetricsPrefix = "shell_operator_"
@@ -124,14 +123,6 @@ func DefineStartCommandFlags(kpApp *kingpin.Application, cmd *kingpin.CmdClause)
 			StringVar(&PrometheusMetricsPrefix)
 	}
 
-	flag = CommonFlagsInfo["hook-metrics-listen-port"]
-	if flag.Define {
-		cmd.Flag(flag.Name, flag.Help).
-			Envar(flag.Envar).
-			Default(HookMetricsListenPort).
-			StringVar(&HookMetricsListenPort)
-	}
-
 	flag = CommonFlagsInfo["namespace"]
 	if flag.Define {
 		cmd.Flag(flag.Name, flag.Help).
diff --git a/pkg/debug/server.go b/pkg/debug/server.go
index e3aef25..ace07e4 100644
--- a/pkg/debug/server.go
+++ b/pkg/debug/server.go
@@ -3,6 +3,7 @@ package debug
 import (
 	"encoding/json"
 	"fmt"
+	"io"
 	"net"
 	"net/http"
 	"os"
@@ -11,7 +12,7 @@ import (
 	"github.com/go-chi/chi/v5"
 	"github.com/go-chi/chi/v5/middleware"
 	log "github.com/sirupsen/logrus"
-	"sigs.k8s.io/yaml"
+	"gopkg.in/yaml.v3"
 
 	utils "github.com/flant/shell-operator/pkg/utils/file"
 	structured_logger "github.com/flant/shell-operator/pkg/utils/structured-logger"
@@ -26,10 +27,15 @@ type Server struct {
 }
 
 func NewServer(prefix, socketPath, httpAddr string) *Server {
+	router := chi.NewRouter()
+	router.Use(structured_logger.NewStructuredLogger(log.StandardLogger(), "debugEndpoint"))
+	router.Use(middleware.Recoverer)
+
 	return &Server{
 		Prefix:     prefix,
 		SocketPath: socketPath,
 		HttpAddr:   httpAddr,
+		Router:     router,
 	}
 }
 
@@ -64,10 +70,6 @@ func (s *Server) Init() (err error) {
 
 	log.Infof("Debug endpoint listen on %s", address)
 
-	s.Router = chi.NewRouter()
-	s.Router.Use(structured_logger.NewStructuredLogger(log.StandardLogger(), "debugEndpoint"))
-	s.Router.Use(middleware.Recoverer)
-
 	go func() {
 		if err := http.Serve(listener, s.Router); err != nil {
 			log.Errorf("Error starting Debug socket server: %s", err)
@@ -87,85 +89,94 @@ func (s *Server) Init() (err error) {
 	return nil
 }
 
-func (s *Server) Route(pattern string, handler func(request *http.Request) (interface{}, error)) {
-	// Should not happen.
-	if handler == nil {
+// RegisterHandler registers http handler for unix/http debug server
+func (s *Server) RegisterHandler(method, pattern string, handler func(request *http.Request) (interface{}, error)) {
+	if method == "" {
+		return
+	}
+	if pattern == "" {
 		return
 	}
-	s.Router.Get(pattern, func(writer http.ResponseWriter, request *http.Request) {
-		handleFormattedOutput(writer, request, handler)
-	})
-}
-
-func (s *Server) RoutePOST(pattern string, handler func(request *http.Request) (interface{}, error)) {
-	// Should not happen.
 	if handler == nil {
 		return
 	}
-	s.Router.Post(pattern, func(writer http.ResponseWriter, request *http.Request) {
-		//
-		err := request.ParseForm()
-		if err != nil {
-			writer.WriteHeader(http.StatusInternalServerError)
-			_, _ = fmt.Fprintf(writer, "Error: %s", err)
-			return
-		}
 
-		handleFormattedOutput(writer, request, handler)
-	})
+	switch method {
+	case http.MethodGet:
+		s.Router.Get(pattern, func(writer http.ResponseWriter, request *http.Request) {
+			handleFormattedOutput(writer, request, handler)
+		})
+
+	case http.MethodPost:
+		s.Router.Post(pattern, func(writer http.ResponseWriter, request *http.Request) {
+			handleFormattedOutput(writer, request, handler)
+		})
+	}
 }
 
 func handleFormattedOutput(writer http.ResponseWriter, request *http.Request, handler func(request *http.Request) (interface{}, error)) {
 	out, err := handler(request)
 	if err != nil {
-		writer.WriteHeader(http.StatusInternalServerError)
-		_, _ = fmt.Fprintf(writer, "Error: %s", err)
+		if _, ok := err.(*BadRequestError); ok {
+			http.Error(writer, err.Error(), http.StatusBadRequest)
+			return
+		}
+
+		http.Error(writer, err.Error(), http.StatusInternalServerError)
 		return
 	}
-	if out == nil && err == nil {
+	if out == nil {
+		writer.WriteHeader(http.StatusOK)
 		return
 	}
 
 	format := FormatFromRequest(request)
 	structured_logger.GetLogEntry(request).Debugf("use format '%s'", format)
 
-	outBytes, err := transformUsingFormat(out, format)
-	if err != nil {
-		writer.WriteHeader(http.StatusInternalServerError)
-		_, _ = fmt.Fprintf(writer, "Error '%s' transform: %s", format, err)
-		return
+	switch format {
+	case "text":
+		writer.Header().Set("Content-Type", "text/plain; charset=utf-8")
+	case "json":
+		writer.Header().Set("Content-Type", "application/json")
+	case "yaml":
+		writer.Header().Set("Content-Type", "application/yaml")
 	}
+	writer.WriteHeader(http.StatusOK)
 
-	_, _ = writer.Write(outBytes)
+	err = transformUsingFormat(writer, out, format)
+	if err != nil {
+		http.Error(writer, fmt.Sprintf("Error '%s' transform: %s", format, err), http.StatusInternalServerError)
+	}
 }
 
-func transformUsingFormat(val interface{}, format string) ([]byte, error) {
-	var outBytes []byte
-	var err error
-
+func transformUsingFormat(w io.Writer, val interface{}, format string) (err error) {
 	switch format {
 	case "yaml":
-		outBytes, err = yaml.Marshal(val)
+		enc := yaml.NewEncoder(w)
+		enc.SetIndent(2)
+		err = enc.Encode(val)
 	case "text":
 		switch v := val.(type) {
 		case string:
-			outBytes = []byte(v)
+			_, err = w.Write([]byte(v))
 		case fmt.Stringer:
-			outBytes = []byte(v.String())
+			_, err = w.Write([]byte(v.String()))
 		case []byte:
-			outBytes = v
+			_, err = w.Write(v)
+		default:
+			err = json.NewEncoder(w).Encode(val)
 		}
-		if outBytes != nil {
+		if err == nil {
 			break
 		}
 		fallthrough
 	case "json":
 		fallthrough
 	default:
-		outBytes, err = json.Marshal(val)
+		err = json.NewEncoder(w).Encode(val)
 	}
 
-	return outBytes, err
+	return err
 }
 
 func FormatFromRequest(request *http.Request) string {
@@ -175,3 +186,11 @@ func FormatFromRequest(request *http.Request) string {
 	}
 	return format
 }
+
+type BadRequestError struct {
+	Msg string
+}
+
+func (be *BadRequestError) Error() string {
+	return be.Msg
+}
diff --git a/pkg/hook/config/util.go b/pkg/hook/config/util.go
index e5b4ad4..b4950cd 100644
--- a/pkg/hook/config/util.go
+++ b/pkg/hook/config/util.go
@@ -3,7 +3,7 @@ package config
 import (
 	"fmt"
 
-	uuid "gopkg.in/satori/go.uuid.v1"
+	uuid "github.com/gofrs/uuid/v5"
 )
 
 func ConvertFloatForBinding(value interface{}, bindingName string) (*float64, error) {
@@ -45,7 +45,7 @@ func MonitorDebugName(configName string, configIndex int) string {
 
 // TODO uuid is not a good choice here. Make it more readable.
 func MonitorConfigID() string {
-	return uuid.NewV4().String()
+	return uuid.Must(uuid.NewV4()).String()
 	// ei.DebugName = uuid.NewV4().String()
 	// if ei.Monitor.ConfigIdPrefix != "" {
 	//	ei.DebugName = ei.Monitor.ConfigIdPrefix + "-" + ei.DebugName[len(ei.Monitor.ConfigIdPrefix)+1:]
@@ -55,5 +55,5 @@ func MonitorConfigID() string {
 
 // TODO uuid is not a good choice here. Make it more readable.
 func ScheduleID() string {
-	return uuid.NewV4().String()
+	return uuid.Must(uuid.NewV4()).String()
 }
diff --git a/pkg/hook/hook.go b/pkg/hook/hook.go
index 935dc4a..e0001f0 100644
--- a/pkg/hook/hook.go
+++ b/pkg/hook/hook.go
@@ -8,9 +8,9 @@ import (
 	"path/filepath"
 	"strings"
 
+	uuid "github.com/gofrs/uuid/v5"
 	"github.com/kennygrant/sanitize"
 	"golang.org/x/time/rate"
-	uuid "gopkg.in/satori/go.uuid.v1"
 
 	"github.com/flant/shell-operator/pkg/app"
 	"github.com/flant/shell-operator/pkg/executor"
@@ -261,7 +261,7 @@ func (h *Hook) prepareBindingContextJsonFile(context BindingContextList) (string
 		return "", err
 	}
 
-	bindingContextPath := filepath.Join(h.TmpDir, fmt.Sprintf("hook-%s-binding-context-%s.json", h.SafeName(), uuid.NewV4().String()))
+	bindingContextPath := filepath.Join(h.TmpDir, fmt.Sprintf("hook-%s-binding-context-%s.json", h.SafeName(), uuid.Must(uuid.NewV4()).String()))
 
 	err = os.WriteFile(bindingContextPath, data, 0o644)
 	if err != nil {
@@ -272,7 +272,7 @@ func (h *Hook) prepareBindingContextJsonFile(context BindingContextList) (string
 }
 
 func (h *Hook) prepareMetricsFile() (string, error) {
-	metricsPath := filepath.Join(h.TmpDir, fmt.Sprintf("hook-%s-metrics-%s.json", h.SafeName(), uuid.NewV4().String()))
+	metricsPath := filepath.Join(h.TmpDir, fmt.Sprintf("hook-%s-metrics-%s.json", h.SafeName(), uuid.Must(uuid.NewV4()).String()))
 
 	err := os.WriteFile(metricsPath, []byte{}, 0o644)
 	if err != nil {
@@ -284,7 +284,7 @@ func (h *Hook) prepareMetricsFile() (string, error) {
 
 // prepareAdmissionResponseFile create file to store response from validating and mutating hooks.
 func (h *Hook) prepareAdmissionResponseFile() (string, error) {
-	filePath := filepath.Join(h.TmpDir, fmt.Sprintf("hook-%s-admission-response-%s.json", h.SafeName(), uuid.NewV4().String()))
+	filePath := filepath.Join(h.TmpDir, fmt.Sprintf("hook-%s-admission-response-%s.json", h.SafeName(), uuid.Must(uuid.NewV4()).String()))
 
 	err := os.WriteFile(filePath, []byte{}, 0o644)
 	if err != nil {
@@ -295,7 +295,7 @@ func (h *Hook) prepareAdmissionResponseFile() (string, error) {
 }
 
 func (h *Hook) prepareConversionResponseFile() (string, error) {
-	conversionPath := filepath.Join(h.TmpDir, fmt.Sprintf("hook-%s-conversion-response-%s.json", h.SafeName(), uuid.NewV4().String()))
+	conversionPath := filepath.Join(h.TmpDir, fmt.Sprintf("hook-%s-conversion-response-%s.json", h.SafeName(), uuid.Must(uuid.NewV4()).String()))
 
 	err := os.WriteFile(conversionPath, []byte{}, 0o644)
 	if err != nil {
@@ -321,7 +321,7 @@ func CreateRateLimiter(cfg *config.HookConfig) *rate.Limiter {
 }
 
 func (h *Hook) prepareObjectPatchFile() (string, error) {
-	objectPatchPath := filepath.Join(h.TmpDir, fmt.Sprintf("%s-object-patch-%s", h.SafeName(), uuid.NewV4().String()))
+	objectPatchPath := filepath.Join(h.TmpDir, fmt.Sprintf("%s-object-patch-%s", h.SafeName(), uuid.Must(uuid.NewV4()).String()))
 
 	err := os.WriteFile(objectPatchPath, []byte{}, 0o644)
 	if err != nil {
diff --git a/pkg/hook/hook_manager.go b/pkg/hook/hook_manager.go
index 906497e..5e726a8 100644
--- a/pkg/hook/hook_manager.go
+++ b/pkg/hook/hook_manager.go
@@ -25,11 +25,6 @@ import (
 type HookManager interface {
 	Init() error
 	Run()
-	WithDirectories(workingDir string, tempDir string)
-	WithKubeEventManager(kube_events_manager.KubeEventsManager)
-	WithScheduleManager(schedule_manager.ScheduleManager)
-	WithConversionWebhookManager(*conversion.WebhookManager)
-	WithAdmissionWebhookManager(*admission.WebhookManager)
 	WorkingDir() string
 	TempDir() string
 	GetHook(name string) *Hook
@@ -67,34 +62,30 @@ type hookManager struct {
 // hookManager should implement HookManager
 var _ HookManager = &hookManager{}
 
-func NewHookManager() *hookManager {
+// HookManagerConfig sets configuration for HookManager
+type HookManagerConfig struct {
+	WorkingDir string
+	TempDir    string
+	Kmgr       kube_events_manager.KubeEventsManager
+	Smgr       schedule_manager.ScheduleManager
+	Wmgr       *admission.WebhookManager
+	Cmgr       *conversion.WebhookManager
+}
+
+func NewHookManager(config *HookManagerConfig) *hookManager {
 	return &hookManager{
 		hooksByName:      make(map[string]*Hook),
 		hookNamesInOrder: make([]string, 0),
 		hooksInOrder:     make(map[BindingType][]*Hook),
 		conversionChains: conversion.NewChainStorage(),
-	}
-}
 
-func (hm *hookManager) WithDirectories(workingDir string, tempDir string) {
-	hm.workingDir = workingDir
-	hm.tempDir = tempDir
-}
-
-func (hm *hookManager) WithKubeEventManager(mgr kube_events_manager.KubeEventsManager) {
-	hm.kubeEventsManager = mgr
-}
-
-func (hm *hookManager) WithScheduleManager(mgr schedule_manager.ScheduleManager) {
-	hm.scheduleManager = mgr
-}
-
-func (hm *hookManager) WithAdmissionWebhookManager(mgr *admission.WebhookManager) {
-	hm.admissionWebhookManager = mgr
-}
-
-func (hm *hookManager) WithConversionWebhookManager(mgr *conversion.WebhookManager) {
-	hm.conversionWebhookManager = mgr
+		workingDir:               config.WorkingDir,
+		tempDir:                  config.TempDir,
+		kubeEventsManager:        config.Kmgr,
+		scheduleManager:          config.Smgr,
+		admissionWebhookManager:  config.Wmgr,
+		conversionWebhookManager: config.Cmgr,
+	}
 }
 
 func (hm *hookManager) WorkingDir() string {
diff --git a/pkg/kube/object_patch/operation.go b/pkg/kube/object_patch/operation.go
index b7e1f62..dd69192 100644
--- a/pkg/kube/object_patch/operation.go
+++ b/pkg/kube/object_patch/operation.go
@@ -25,6 +25,7 @@ type OperationSpec struct {
 	JSONPatch  interface{} `json:"jsonPatch,omitempty" yaml:"jsonPatch,omitempty"`
 
 	IgnoreMissingObject bool `json:"ignoreMissingObject" yaml:"ignoreMissingObject"`
+	IgnoreHookError     bool `json:"ignoreHookError" yaml:"ignoreHookError"`
 }
 
 type OperationType string
@@ -43,6 +44,25 @@ const (
 	JSONPatch  OperationType = "JSONPatch"
 )
 
+// GetPatchStatusOperationsOnHookError returns list of Patch/Filter operations eligible for execution on Hook Error
+func GetPatchStatusOperationsOnHookError(operations []Operation) []Operation {
+	patchStatusOperations := make([]Operation, 0)
+	for _, op := range operations {
+		switch operation := op.(type) {
+		case *filterOperation:
+			if operation.subresource == "/status" && operation.ignoreHookError {
+				patchStatusOperations = append(patchStatusOperations, operation)
+			}
+		case *patchOperation:
+			if operation.subresource == "/status" && operation.ignoreHookError {
+				patchStatusOperations = append(patchStatusOperations, operation)
+			}
+		}
+	}
+
+	return patchStatusOperations
+}
+
 func ParseOperations(specBytes []byte) ([]Operation, error) {
 	log.Debugf("parsing patcher operations:\n%s", specBytes)
 
@@ -120,6 +140,7 @@ type patchOperation struct {
 	patchType           types.PatchType
 	patch               interface{}
 	ignoreMissingObject bool
+	ignoreHookError     bool
 }
 
 func (op *patchOperation) Description() string {
@@ -137,6 +158,7 @@ type filterOperation struct {
 	// Patch options.
 	filterFunc          func(*unstructured.Unstructured) (*unstructured.Unstructured, error)
 	ignoreMissingObject bool
+	ignoreHookError     bool
 }
 
 func (op *filterOperation) Description() string {
@@ -175,18 +197,21 @@ func NewFromOperationSpec(spec OperationSpec) Operation {
 			spec.ApiVersion, spec.Kind, spec.Namespace, spec.Name,
 			WithSubresource(spec.Subresource),
 			WithIgnoreMissingObject(spec.IgnoreMissingObject),
+			WithIgnoreHookError(spec.IgnoreHookError),
 		)
 	case MergePatch:
 		return NewMergePatchOperation(spec.MergePatch,
 			spec.ApiVersion, spec.Kind, spec.Namespace, spec.Name,
 			WithSubresource(spec.Subresource),
 			WithIgnoreMissingObject(spec.IgnoreMissingObject),
+			WithIgnoreHookError(spec.IgnoreHookError),
 		)
 	case JSONPatch:
 		return NewJSONPatchOperation(spec.JSONPatch,
 			spec.ApiVersion, spec.Kind, spec.Namespace, spec.Name,
 			WithSubresource(spec.Subresource),
 			WithIgnoreMissingObject(spec.IgnoreMissingObject),
+			WithIgnoreHookError(spec.IgnoreHookError),
 		)
 	}
 
diff --git a/pkg/kube/object_patch/options.go b/pkg/kube/object_patch/options.go
index fed6d6d..c6900ee 100644
--- a/pkg/kube/object_patch/options.go
+++ b/pkg/kube/object_patch/options.go
@@ -45,10 +45,31 @@ func (s *subresourceHolder) applyToFilter(operation *filterOperation) {
 	operation.subresource = s.subresource
 }
 
+type ignoreHookError struct {
+	ignoreError bool
+}
+
+// IgnoreHookError allows applying patches for a Status subresource even if the hook fails
+func IgnoreHookError() *ignoreHookError {
+	return WithIgnoreHookError(true)
+}
+
+func WithIgnoreHookError(ignoreError bool) *ignoreHookError {
+	return &ignoreHookError{ignoreError: ignoreError}
+}
+
 type ignoreMissingObject struct {
 	ignore bool
 }
 
+func (i *ignoreHookError) applyToPatch(operation *patchOperation) {
+	operation.ignoreHookError = i.ignoreError
+}
+
+func (i *ignoreHookError) applyToFilter(operation *filterOperation) {
+	operation.ignoreHookError = i.ignoreError
+}
+
 // IgnoreMissingObject do not return error if object exists for Patch and Filter operations.
 func IgnoreMissingObject() *ignoreMissingObject {
 	return WithIgnoreMissingObject(true)
diff --git a/pkg/kube/object_patch/patch.go b/pkg/kube/object_patch/patch.go
index f87a485..2a0410e 100644
--- a/pkg/kube/object_patch/patch.go
+++ b/pkg/kube/object_patch/patch.go
@@ -152,6 +152,7 @@ func (o *ObjectPatcher) executeCreateOperation(op *createOperation) error {
 // Other options:
 // - WithSubresource — a subresource argument for Patch or Update API call.
 // - IgnoreMissingObject — do not return error if the specified object is missing.
+// - IgnoreHookError — allows applying patches for a Status subresource even if the hook fails
 func (o *ObjectPatcher) executePatchOperation(op *patchOperation) error {
 	if op.patchType == types.MergePatchType {
 		log.Debug("Started MergePatchObject")
@@ -190,6 +191,11 @@ func (o *ObjectPatcher) executePatchOperation(op *patchOperation) error {
 
 // executeFilterOperation retrieves a specified object, modified it with
 // filterFunc and calls update.
+
+// Other options:
+// - WithSubresource — a subresource argument for Patch or Update API call.
+// - IgnoreMissingObject — do not return error if the specified object is missing.
+// - IgnoreHookError — allows applying patches for a Status subresource even if the hook fails
 func (o *ObjectPatcher) executeFilterOperation(op *filterOperation) error {
 	var err error
 
diff --git a/pkg/kube/object_patch/patch_collector.go b/pkg/kube/object_patch/patch_collector.go
index 87dba47..0d2c365 100644
--- a/pkg/kube/object_patch/patch_collector.go
+++ b/pkg/kube/object_patch/patch_collector.go
@@ -43,6 +43,7 @@ func (dop *PatchCollector) Delete(apiVersion, kind, namespace, name string, opti
 // Options:
 //   - WithSubresource — a subresource argument for Patch call.
 //   - IgnoreMissingObject — do not return error if the specified object is missing.
+//   - IgnoreHookError — allows applying patches for a Status subresource even if the hook fails
 func (dop *PatchCollector) MergePatch(mergePatch interface{}, apiVersion, kind, namespace, name string, options ...PatchOption) {
 	dop.add(NewMergePatchOperation(mergePatch, apiVersion, kind, namespace, name, options...))
 }
@@ -52,6 +53,7 @@ func (dop *PatchCollector) MergePatch(mergePatch interface{}, apiVersion, kind,
 // Options:
 //   - WithSubresource — a subresource argument for Patch call.
 //   - IgnoreMissingObject — do not return error if the specified object is missing.
+//   - IgnoreHookError — allows applying patches for a Status subresource even if the hook fails
 func (dop *PatchCollector) JSONPatch(jsonPatch interface{}, apiVersion, kind, namespace, name string, options ...PatchOption) {
 	dop.add(NewJSONPatchOperation(jsonPatch, apiVersion, kind, namespace, name, options...))
 }
@@ -62,6 +64,7 @@ func (dop *PatchCollector) JSONPatch(jsonPatch interface{}, apiVersion, kind, na
 // Options:
 //   - WithSubresource — a subresource argument for Patch call.
 //   - IgnoreMissingObject — do not return error if the specified object is missing.
+//   - IgnoreHookError — allows applying patches for a Status subresource even if the hook fails
 //
 // Note: do not modify and return argument in filterFunc,
 // use FromUnstructured to instantiate a concrete type or modify after DeepCopy.
diff --git a/pkg/kube/object_patch/validation.go b/pkg/kube/object_patch/validation.go
index 1a5233d..e8055a6 100644
--- a/pkg/kube/object_patch/validation.go
+++ b/pkg/kube/object_patch/validation.go
@@ -56,6 +56,8 @@ definitions:
         type: string
       ignoreMissingObject:
         type: boolean
+      ignoreHookError:
+        type: boolean
 
 type: object
 additionalProperties: false
@@ -71,6 +73,7 @@ properties:
   jqFilter: {}
   mergePatch: {}
   ignoreMissingObject: {}
+  ignoreHookError: {}
 
 oneOf:
 - allOf:
diff --git a/pkg/kube_events_manager/error_handler.go b/pkg/kube_events_manager/error_handler.go
index 785af71..8ae8d56 100644
--- a/pkg/kube_events_manager/error_handler.go
+++ b/pkg/kube_events_manager/error_handler.go
@@ -18,7 +18,7 @@ type WatchErrorHandler struct {
 	metricStorage *metric_storage.MetricStorage
 }
 
-func NewWatchErrorHandler(description string, kind string, logLabels map[string]string, metricStorage *metric_storage.MetricStorage) *WatchErrorHandler {
+func newWatchErrorHandler(description string, kind string, logLabels map[string]string, metricStorage *metric_storage.MetricStorage) *WatchErrorHandler {
 	return &WatchErrorHandler{
 		description:   description,
 		kind:          kind,
@@ -28,7 +28,7 @@ func NewWatchErrorHandler(description string, kind string, logLabels map[string]
 }
 
 // Handler is the implementation of WatchErrorHandler that is aware of monitors and metricStorage
-func (weh *WatchErrorHandler) Handler(_ *cache.Reflector, err error) {
+func (weh *WatchErrorHandler) handler(_ *cache.Reflector, err error) {
 	errorType := "nil"
 
 	switch {
diff --git a/pkg/kube_events_manager/factory.go b/pkg/kube_events_manager/factory.go
index 7502b10..645e776 100644
--- a/pkg/kube_events_manager/factory.go
+++ b/pkg/kube_events_manager/factory.go
@@ -61,7 +61,7 @@ func (c *FactoryStore) get(client dynamic.Interface, index FactoryIndex) Factory
 	}
 
 	// define resyncPeriod for informer
-	resyncPeriod := RandomizedResyncPeriod()
+	resyncPeriod := randomizedResyncPeriod()
 
 	tweakListOptions := func(options *metav1.ListOptions) {
 		if index.FieldSelector != "" {
@@ -88,7 +88,7 @@ func (c *FactoryStore) Start(client dynamic.Interface, index FactoryIndex, handl
 
 	informer := factory.shared.ForResource(index.GVR).Informer()
 	// Add error handler, ignore "already started" error.
-	_ = informer.SetWatchErrorHandler(errorHandler.Handler)
+	_ = informer.SetWatchErrorHandler(errorHandler.handler)
 	// TODO(nabokihms): think about what will happen if we stop and then start the monitor
 	informer.AddEventHandler(handler)
 
diff --git a/pkg/kube_events_manager/filter.go b/pkg/kube_events_manager/filter.go
index fdf7d44..2165f2c 100644
--- a/pkg/kube_events_manager/filter.go
+++ b/pkg/kube_events_manager/filter.go
@@ -16,17 +16,17 @@ import (
 	utils_checksum "github.com/flant/shell-operator/pkg/utils/checksum"
 )
 
-// ApplyFilter filters object json representation with jq expression, calculate checksum
+// applyFilter filters object json representation with jq expression, calculate checksum
 // over result and return ObjectAndFilterResult. If jqFilter is empty, no filter
 // is required and checksum is calculated over full json representation of the object.
-func ApplyFilter(jqFilter string, filterFn func(obj *unstructured.Unstructured) (result interface{}, err error), obj *unstructured.Unstructured) (*ObjectAndFilterResult, error) {
+func applyFilter(jqFilter string, filterFn func(obj *unstructured.Unstructured) (result interface{}, err error), obj *unstructured.Unstructured) (*ObjectAndFilterResult, error) {
 	defer trace.StartRegion(context.Background(), "ApplyJqFilter").End()
 
 	res := &ObjectAndFilterResult{
 		Object: obj,
 	}
 	res.Metadata.JqFilter = jqFilter
-	res.Metadata.ResourceId = ResourceId(obj)
+	res.Metadata.ResourceId = resourceId(obj)
 
 	// If filterFn is passed, run it and return result.
 	if filterFn != nil {
diff --git a/pkg/kube_events_manager/kube_events_manager.go b/pkg/kube_events_manager/kube_events_manager.go
index ff09288..9181cf1 100644
--- a/pkg/kube_events_manager/kube_events_manager.go
+++ b/pkg/kube_events_manager/kube_events_manager.go
@@ -13,9 +13,7 @@ import (
 )
 
 type KubeEventsManager interface {
-	WithContext(ctx context.Context)
 	WithMetricStorage(mstor *metric_storage.MetricStorage)
-	WithKubeClient(client klient.Client)
 	AddMonitor(monitorConfig *MonitorConfig) error
 	HasMonitor(monitorID string) bool
 	GetMonitor(monitorID string) Monitor
@@ -31,7 +29,7 @@ type kubeEventsManager struct {
 	// channel to emit KubeEvent objects
 	KubeEventCh chan KubeEvent
 
-	KubeClient klient.Client
+	KubeClient *klient.Client
 
 	ctx           context.Context
 	cancel        context.CancelFunc
@@ -45,8 +43,12 @@ type kubeEventsManager struct {
 var _ KubeEventsManager = &kubeEventsManager{}
 
 // NewKubeEventsManager returns an implementation of KubeEventsManager.
-var NewKubeEventsManager = func() *kubeEventsManager {
+func NewKubeEventsManager(ctx context.Context, client *klient.Client) *kubeEventsManager {
+	cctx, cancel := context.WithCancel(ctx)
 	em := &kubeEventsManager{
+		ctx:         cctx,
+		cancel:      cancel,
+		KubeClient:  client,
 		m:           sync.RWMutex{},
 		Monitors:    make(map[string]Monitor),
 		KubeEventCh: make(chan KubeEvent, 1),
@@ -54,32 +56,24 @@ var NewKubeEventsManager = func() *kubeEventsManager {
 	return em
 }
 
-func (mgr *kubeEventsManager) WithContext(ctx context.Context) {
-	mgr.ctx, mgr.cancel = context.WithCancel(ctx)
-}
-
 func (mgr *kubeEventsManager) WithMetricStorage(mstor *metric_storage.MetricStorage) {
 	mgr.metricStorage = mstor
 }
 
-func (mgr *kubeEventsManager) WithKubeClient(client klient.Client) {
-	mgr.KubeClient = client
-}
-
 // AddMonitor creates a monitor with informers and return a KubeEvent with existing objects.
 // TODO cleanup informers in case of error
 // TODO use Context to stop informers
 func (mgr *kubeEventsManager) AddMonitor(monitorConfig *MonitorConfig) error {
 	log.Debugf("Add MONITOR %+v", monitorConfig)
-	monitor := NewMonitor()
-	monitor.WithContext(mgr.ctx)
-	monitor.WithKubeClient(mgr.KubeClient)
-	monitor.WithMetricStorage(mgr.metricStorage)
-	monitor.WithConfig(monitorConfig)
-	monitor.WithKubeEventCb(func(ev KubeEvent) {
-		defer trace.StartRegion(context.Background(), "EmitKubeEvent").End()
-		mgr.KubeEventCh <- ev
-	})
+	monitor := NewMonitor(
+		mgr.ctx,
+		mgr.KubeClient,
+		mgr.metricStorage,
+		monitorConfig,
+		func(ev KubeEvent) {
+			defer trace.StartRegion(context.Background(), "EmitKubeEvent").End()
+			mgr.KubeEventCh <- ev
+		})
 
 	err := monitor.CreateInformers()
 	if err != nil {
diff --git a/pkg/kube_events_manager/monitor.go b/pkg/kube_events_manager/monitor.go
index 3f50e18..a4fc5bb 100644
--- a/pkg/kube_events_manager/monitor.go
+++ b/pkg/kube_events_manager/monitor.go
@@ -14,11 +14,6 @@ import (
 )
 
 type Monitor interface {
-	WithContext(ctx context.Context)
-	WithKubeClient(client klient.Client)
-	WithMetricStorage(mstor *metric_storage.MetricStorage)
-	WithConfig(config *MonitorConfig)
-	WithKubeEventCb(eventCb func(KubeEvent))
 	CreateInformers() error
 	Start(context.Context)
 	Stop()
@@ -33,13 +28,13 @@ type Monitor interface {
 type monitor struct {
 	Name       string
 	Config     *MonitorConfig
-	KubeClient klient.Client
+	KubeClient *klient.Client
 	// Static list of informers
-	ResourceInformers []ResourceInformer
+	ResourceInformers []*resourceInformer
 	// Namespace informer to get new namespaces
-	NamespaceInformer NamespaceInformer
+	NamespaceInformer *namespaceInformer
 	// map of dynamically starting informers
-	VaryingInformers map[string][]ResourceInformer
+	VaryingInformers map[string][]*resourceInformer
 
 	eventCb       func(KubeEvent)
 	eventsEnabled bool
@@ -53,39 +48,27 @@ type monitor struct {
 	metricStorage *metric_storage.MetricStorage
 }
 
-var NewMonitor = func() Monitor {
+func NewMonitor(ctx context.Context, client *klient.Client, mstor *metric_storage.MetricStorage, config *MonitorConfig, eventCb func(KubeEvent)) *monitor {
+	cctx, cancel := context.WithCancel(ctx)
+
 	return &monitor{
-		ResourceInformers: make([]ResourceInformer, 0),
-		VaryingInformers:  make(map[string][]ResourceInformer),
+		ctx:               cctx,
+		cancel:            cancel,
+		KubeClient:        client,
+		metricStorage:     mstor,
+		Config:            config,
+		eventCb:           eventCb,
+		ResourceInformers: make([]*resourceInformer, 0),
+		VaryingInformers:  make(map[string][]*resourceInformer),
 		cancelForNs:       make(map[string]context.CancelFunc),
 		staticNamespaces:  make(map[string]bool),
 	}
 }
 
-func (m *monitor) WithContext(ctx context.Context) {
-	m.ctx, m.cancel = context.WithCancel(ctx)
-}
-
-func (m *monitor) WithKubeClient(client klient.Client) {
-	m.KubeClient = client
-}
-
-func (m *monitor) WithMetricStorage(mstor *metric_storage.MetricStorage) {
-	m.metricStorage = mstor
-}
-
-func (m *monitor) WithConfig(config *MonitorConfig) {
-	m.Config = config
-}
-
 func (m *monitor) GetConfig() *MonitorConfig {
 	return m.Config
 }
 
-func (m *monitor) WithKubeEventCb(eventCb func(KubeEvent)) {
-	m.eventCb = eventCb
-}
-
 // CreateInformers creates all informers and
 // a namespace informer if namespace.labelSelector is defined.
 // If MonitorConfig.NamespaceSelector.MatchNames is defined, then
@@ -102,7 +85,7 @@ func (m *monitor) CreateInformers() error {
 	}
 
 	logEntry.Debugf("Create Informers Config: %+v", m.Config)
-	nsNames := m.Config.Namespaces()
+	nsNames := m.Config.namespaces()
 	if len(nsNames) > 0 {
 		logEntry.Debugf("create static ResourceInformers")
 
@@ -122,10 +105,8 @@ func (m *monitor) CreateInformers() error {
 
 	if m.Config.NamespaceSelector != nil && m.Config.NamespaceSelector.LabelSelector != nil {
 		logEntry.Debugf("Create NamespaceInformer for namespace.labelSelector")
-		m.NamespaceInformer = NewNamespaceInformer(m.Config)
-		m.NamespaceInformer.WithContext(m.ctx)
-		m.NamespaceInformer.WithKubeClient(m.KubeClient)
-		err := m.NamespaceInformer.CreateSharedInformer(
+		m.NamespaceInformer = NewNamespaceInformer(m.ctx, m.KubeClient, m.Config)
+		err := m.NamespaceInformer.createSharedInformer(
 			func(nsName string) {
 				// Added/Modified event: check, create and run informers for Ns
 				// ignore event if namespace is already has static ResourceInformers
@@ -150,11 +131,11 @@ func (m *monitor) CreateInformers() error {
 				ctx, m.cancelForNs[nsName] = context.WithCancel(m.ctx)
 
 				for _, informer := range m.VaryingInformers[nsName] {
-					informer.WithContext(ctx)
+					informer.withContext(ctx)
 					if m.eventsEnabled {
-						informer.EnableKubeEventCb()
+						informer.enableKubeEventCb()
 					}
-					informer.Start()
+					informer.start()
 				}
 			},
 			func(nsName string) {
@@ -183,7 +164,7 @@ func (m *monitor) CreateInformers() error {
 		if err != nil {
 			return fmt.Errorf("create namespace informer: %v", err)
 		}
-		for nsName := range m.NamespaceInformer.GetExistedObjects() {
+		for nsName := range m.NamespaceInformer.getExistedObjects() {
 			logEntry.Infof("got ns/%s, create dynamic ResourceInformers", nsName)
 
 			// ignore event if namespace is already has static ResourceInformers
@@ -207,12 +188,12 @@ func (m *monitor) Snapshot() []ObjectAndFilterResult {
 	objects := make([]ObjectAndFilterResult, 0)
 
 	for _, informer := range m.ResourceInformers {
-		objects = append(objects, informer.CachedObjects()...)
+		objects = append(objects, informer.getCachedObjects()...)
 	}
 
 	for nsName := range m.VaryingInformers {
 		for _, informer := range m.VaryingInformers[nsName] {
-			objects = append(objects, informer.CachedObjects()...)
+			objects = append(objects, informer.getCachedObjects()...)
 		}
 	}
 
@@ -226,11 +207,11 @@ func (m *monitor) Snapshot() []ObjectAndFilterResult {
 // Also executes eventCb for events accumulated during "Synchronization" phase.
 func (m *monitor) EnableKubeEventCb() {
 	for _, informer := range m.ResourceInformers {
-		informer.EnableKubeEventCb()
+		informer.enableKubeEventCb()
 	}
 	for nsName := range m.VaryingInformers {
 		for _, informer := range m.VaryingInformers[nsName] {
-			informer.EnableKubeEventCb()
+			informer.enableKubeEventCb()
 		}
 	}
 	// Enable events for future VaryingInformers.
@@ -241,24 +222,25 @@ func (m *monitor) EnableKubeEventCb() {
 // it is only one informer. If matchName is specified, then multiple informers are created.
 //
 // If namespace is empty, then informer is bounded to all namespaces.
-func (m *monitor) CreateInformersForNamespace(namespace string) (informers []ResourceInformer, err error) {
-	informers = make([]ResourceInformer, 0)
+func (m *monitor) CreateInformersForNamespace(namespace string) (informers []*resourceInformer, err error) {
+	informers = make([]*resourceInformer, 0)
+	cfg := &resourceInformerConfig{
+		client:  m.KubeClient,
+		mstor:   m.metricStorage,
+		eventCb: m.eventCb,
+		monitor: m.Config,
+	}
 
 	objNames := []string{""}
 
-	if len(m.Config.Names()) > 0 {
-		objNames = m.Config.Names()
+	if len(m.Config.names()) > 0 {
+		objNames = m.Config.names()
 	}
 
 	for _, objName := range objNames {
-		informer := NewResourceInformer(m.Config)
-		informer.WithKubeClient(m.KubeClient)
-		informer.WithMetricStorage(m.metricStorage)
-		informer.WithNamespace(namespace)
-		informer.WithName(objName)
-		informer.WithKubeEventCb(m.eventCb)
-
-		err := informer.CreateSharedInformer()
+		informer := newResourceInformer(namespace, objName, cfg)
+
+		err := informer.createSharedInformer()
 		if err != nil {
 			return nil, err
 		}
@@ -273,22 +255,22 @@ func (m *monitor) Start(parentCtx context.Context) {
 	m.ctx, m.cancel = context.WithCancel(parentCtx)
 
 	for _, informer := range m.ResourceInformers {
-		informer.WithContext(m.ctx)
-		informer.Start()
+		informer.withContext(m.ctx)
+		informer.start()
 	}
 
 	for nsName := range m.VaryingInformers {
 		var ctx context.Context
 		ctx, m.cancelForNs[nsName] = context.WithCancel(m.ctx)
 		for _, informer := range m.VaryingInformers[nsName] {
-			informer.WithContext(ctx)
-			informer.Start()
+			informer.withContext(ctx)
+			informer.start()
 		}
 	}
 
 	if m.NamespaceInformer != nil {
-		m.NamespaceInformer.WithContext(m.ctx)
-		m.NamespaceInformer.Start()
+		m.NamespaceInformer.withContext(m.ctx)
+		m.NamespaceInformer.start()
 	}
 }
 
@@ -304,17 +286,17 @@ func (m *monitor) Stop() {
 // Calling cancel() leads to a race and panicking, see https://github.com/kubernetes/kubernetes/issues/59822
 func (m *monitor) PauseHandleEvents() {
 	for _, informer := range m.ResourceInformers {
-		informer.PauseHandleEvents()
+		informer.pauseHandleEvents()
 	}
 
 	for _, informers := range m.VaryingInformers {
 		for _, informer := range informers {
-			informer.PauseHandleEvents()
+			informer.pauseHandleEvents()
 		}
 	}
 
 	if m.NamespaceInformer != nil {
-		m.NamespaceInformer.PauseHandleEvents()
+		m.NamespaceInformer.pauseHandleEvents()
 	}
 }
 
@@ -323,14 +305,14 @@ func (m *monitor) SnapshotOperations() (total *CachedObjectsInfo, last *CachedOb
 	last = &CachedObjectsInfo{}
 
 	for _, informer := range m.ResourceInformers {
-		total.Add(informer.CachedObjectsInfo())
-		last.Add(informer.CachedObjectsInfoIncrement())
+		total.add(informer.getCachedObjectsInfo())
+		last.add(informer.getCachedObjectsInfoIncrement())
 	}
 
 	for nsName := range m.VaryingInformers {
 		for _, informer := range m.VaryingInformers[nsName] {
-			total.Add(informer.CachedObjectsInfo())
-			last.Add(informer.CachedObjectsInfoIncrement())
+			total.add(informer.getCachedObjectsInfo())
+			last.add(informer.getCachedObjectsInfoIncrement())
 		}
 	}
 
diff --git a/pkg/kube_events_manager/monitor_config.go b/pkg/kube_events_manager/monitor_config.go
index d9dd6b8..5c33c95 100644
--- a/pkg/kube_events_manager/monitor_config.go
+++ b/pkg/kube_events_manager/monitor_config.go
@@ -8,7 +8,7 @@ import (
 	. "github.com/flant/shell-operator/pkg/kube_events_manager/types"
 )
 
-// KubeEventMonitorConfig is a config that suits the latest
+// MonitorConfig is a config that suits the latest
 // version of OnKubernetesEventConfig.
 type MonitorConfig struct {
 	Metadata struct {
@@ -45,7 +45,7 @@ func (c *MonitorConfig) WithEventTypes(types []WatchEventType) *MonitorConfig {
 	return c
 }
 
-// WithNamespaceSelector copies input NamespaceSelector into monitor.NamespaceSelector
+// WithNameSelector copies input NameSelector into monitor.NameSelector
 func (c *MonitorConfig) WithNameSelector(nSel *NameSelector) {
 	if nSel != nil {
 		c.NameSelector = &NameSelector{
@@ -81,25 +81,6 @@ func (c *MonitorConfig) WithFieldSelector(fieldSel *FieldSelector) {
 	}
 }
 
-func (c *MonitorConfig) AddFieldSelectorRequirement(field string, op string, value string) {
-	if c.FieldSelector == nil {
-		c.FieldSelector = &FieldSelector{
-			MatchExpressions: []FieldSelectorRequirement{},
-		}
-	}
-	if c.FieldSelector.MatchExpressions == nil {
-		c.FieldSelector.MatchExpressions = make([]FieldSelectorRequirement, 0)
-	}
-
-	req := FieldSelectorRequirement{
-		Field:    field,
-		Operator: op,
-		Value:    value,
-	}
-
-	c.FieldSelector.MatchExpressions = append(c.FieldSelector.MatchExpressions, req)
-}
-
 // WithLabelSelector copies input LabelSelector into monitor.LabelSelector
 func (c *MonitorConfig) WithLabelSelector(labelSel *metav1.LabelSelector) {
 	if labelSel != nil {
@@ -110,15 +91,9 @@ func (c *MonitorConfig) WithLabelSelector(labelSel *metav1.LabelSelector) {
 	}
 }
 
-func (c *MonitorConfig) IsAnyNamespace() bool {
-	return c.NamespaceSelector == nil ||
-		(c.NamespaceSelector.NameSelector == nil && c.NamespaceSelector.LabelSelector == nil) ||
-		(c.NamespaceSelector.NameSelector != nil && len(c.NamespaceSelector.NameSelector.MatchNames) == 0)
-}
-
-// Names returns names of monitored objects if nameSelector.matchNames is defined in config.
-func (c *MonitorConfig) Names() []string {
-	res := []string{}
+// names returns names of monitored objects if nameSelector.matchNames is defined in config.
+func (c *MonitorConfig) names() []string {
+	res := make([]string, 0)
 
 	if c.NameSelector != nil {
 		res = c.NameSelector.MatchNames
@@ -135,7 +110,7 @@ func (c *MonitorConfig) Names() []string {
 // then empty string is returned to monitor all namespaces.
 //
 // If namespace.labelSelector is specified, then return empty array.
-func (c *MonitorConfig) Namespaces() (nsNames []string) {
+func (c *MonitorConfig) namespaces() (nsNames []string) {
 	if c.NamespaceSelector == nil {
 		return []string{""}
 	}
diff --git a/pkg/kube_events_manager/namespace_informer.go b/pkg/kube_events_manager/namespace_informer.go
index bb4f8be..38ac461 100644
--- a/pkg/kube_events_manager/namespace_informer.go
+++ b/pkg/kube_events_manager/namespace_informer.go
@@ -16,22 +16,12 @@ import (
 	klient "github.com/flant/kube-client/client"
 )
 
-type NamespaceInformer interface {
-	WithContext(ctx context.Context)
-	WithKubeClient(client klient.Client)
-	CreateSharedInformer(addFn func(string), delFn func(string)) error
-	GetExistedObjects() map[string]bool
-	Start()
-	Stop()
-	PauseHandleEvents()
-}
-
 type namespaceInformer struct {
 	ctx     context.Context
 	cancel  context.CancelFunc
 	stopped bool
 
-	KubeClient     klient.Client
+	KubeClient     *klient.Client
 	Monitor        *MonitorConfig
 	SharedInformer cache.SharedInformer
 
@@ -41,28 +31,26 @@ type namespaceInformer struct {
 	delFn func(string)
 }
 
-// namespaceInformer implements NamespaceInformer interface
-var _ NamespaceInformer = &namespaceInformer{}
+func NewNamespaceInformer(ctx context.Context, client *klient.Client, monitor *MonitorConfig) *namespaceInformer {
+	cctx, cancel := context.WithCancel(ctx)
 
-var NewNamespaceInformer = func(monitor *MonitorConfig) NamespaceInformer {
 	informer := &namespaceInformer{
+		ctx:            cctx,
+		cancel:         cancel,
+		KubeClient:     client,
 		Monitor:        monitor,
 		ExistedObjects: make(map[string]bool),
 	}
 	return informer
 }
 
-func (ni *namespaceInformer) WithContext(ctx context.Context) {
+func (ni *namespaceInformer) withContext(ctx context.Context) {
 	ni.ctx, ni.cancel = context.WithCancel(ctx)
 }
 
-func (ni *namespaceInformer) WithKubeClient(client klient.Client) {
-	ni.KubeClient = client
-}
-
-func (ni *namespaceInformer) CreateSharedInformer(addFn func(string), delFn func(string)) error {
+func (ni *namespaceInformer) createSharedInformer(addFn func(string), delFn func(string)) error {
 	// define resyncPeriod for informer
-	resyncPeriod := RandomizedResyncPeriod()
+	resyncPeriod := randomizedResyncPeriod()
 
 	// define indexers for informer
 	indexers := cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}
@@ -98,7 +86,7 @@ func (ni *namespaceInformer) CreateSharedInformer(addFn func(string), delFn func
 	return nil
 }
 
-func (ni *namespaceInformer) GetExistedObjects() map[string]bool {
+func (ni *namespaceInformer) getExistedObjects() map[string]bool {
 	return ni.ExistedObjects
 }
 
@@ -131,10 +119,10 @@ func (ni *namespaceInformer) OnDelete(obj interface{}) {
 	}
 }
 
-func (ni *namespaceInformer) Start() {
+func (ni *namespaceInformer) start() {
 	log.Debugf("%s: Run namespace informer", ni.Monitor.Metadata.DebugName)
 	if ni.SharedInformer == nil {
-		log.Errorf("%s: Possible BUG!!! Start called before CreateSharedInformer, ShredInformer is nil", ni.Monitor.Metadata.DebugName)
+		log.Errorf("%s: Possible BUG!!! Start called before createSharedInformer, ShredInformer is nil", ni.Monitor.Metadata.DebugName)
 		return
 	}
 	stopCh := make(chan struct{}, 1)
@@ -154,13 +142,6 @@ func (ni *namespaceInformer) Start() {
 	log.Debugf("%s: informer is ready", ni.Monitor.Metadata.DebugName)
 }
 
-func (ni *namespaceInformer) Stop() {
-	if ni.cancel != nil {
-		ni.cancel()
-	}
-	ni.stopped = true
-}
-
-func (ni *namespaceInformer) PauseHandleEvents() {
+func (ni *namespaceInformer) pauseHandleEvents() {
 	ni.stopped = true
 }
diff --git a/pkg/kube_events_manager/resource_informer.go b/pkg/kube_events_manager/resource_informer.go
index db75f57..29042d8 100644
--- a/pkg/kube_events_manager/resource_informer.go
+++ b/pkg/kube_events_manager/resource_informer.go
@@ -19,26 +19,8 @@ import (
 	"github.com/flant/shell-operator/pkg/utils/measure"
 )
 
-// ResourceInformer is a kube informer for particular onKubernetesEvent
-type ResourceInformer interface {
-	WithContext(ctx context.Context)
-	WithKubeClient(client klient.Client)
-	WithMetricStorage(mstor *metric_storage.MetricStorage)
-	WithNamespace(string)
-	WithName(string)
-	WithKubeEventCb(eventCb func(KubeEvent))
-	CreateSharedInformer() error
-	CachedObjects() []ObjectAndFilterResult
-	EnableKubeEventCb() // Call it to use KubeEventCb to emit events.
-	Start()
-	Stop()
-	PauseHandleEvents()
-	CachedObjectsInfo() CachedObjectsInfo
-	CachedObjectsInfoIncrement() CachedObjectsInfo
-}
-
 type resourceInformer struct {
-	KubeClient klient.Client
+	KubeClient *klient.Client
 	Monitor    *MonitorConfig
 	// Filter by namespace
 	Namespace string
@@ -59,7 +41,7 @@ type resourceInformer struct {
 	// Cached objects operations since last access
 	cachedObjectsIncrement *CachedObjectsInfo
 
-	// Events buffer for "Synchronization" mode: it stores events between CachedObjects call and EnableKubeEventCb call
+	// Events buffer for "Synchronization" mode: it stores events between CachedObjects call and enableKubeEventCb call
 	// to replay them when "Synchronization" hook is done.
 	eventBuf     []KubeEvent
 	eventBufLock sync.Mutex
@@ -79,11 +61,21 @@ type resourceInformer struct {
 }
 
 // resourceInformer should implement ResourceInformer
-var _ ResourceInformer = &resourceInformer{}
+type resourceInformerConfig struct {
+	client  *klient.Client
+	mstor   *metric_storage.MetricStorage
+	eventCb func(KubeEvent)
+	monitor *MonitorConfig
+}
 
-var NewResourceInformer = func(monitor *MonitorConfig) ResourceInformer {
+func newResourceInformer(ns, name string, cfg *resourceInformerConfig) *resourceInformer {
 	informer := &resourceInformer{
-		Monitor:                monitor,
+		KubeClient:             cfg.client,
+		metricStorage:          cfg.mstor,
+		Namespace:              ns,
+		Name:                   name,
+		eventCb:                cfg.eventCb,
+		Monitor:                cfg.monitor,
 		cachedObjects:          make(map[string]*ObjectAndFilterResult),
 		cacheLock:              sync.RWMutex{},
 		eventBufLock:           sync.Mutex{},
@@ -93,37 +85,17 @@ var NewResourceInformer = func(monitor *MonitorConfig) ResourceInformer {
 	return informer
 }
 
-func (ei *resourceInformer) WithContext(ctx context.Context) {
+func (ei *resourceInformer) withContext(ctx context.Context) {
 	ei.ctx, ei.cancel = context.WithCancel(ctx)
 }
 
-func (ei *resourceInformer) WithKubeClient(client klient.Client) {
-	ei.KubeClient = client
-}
-
-func (ei *resourceInformer) WithMetricStorage(mstor *metric_storage.MetricStorage) {
-	ei.metricStorage = mstor
-}
-
-func (ei *resourceInformer) WithNamespace(ns string) {
-	ei.Namespace = ns
-}
-
-func (ei *resourceInformer) WithName(name string) {
-	ei.Name = name
-}
-
-func (ei *resourceInformer) WithKubeEventCb(eventCb func(KubeEvent)) {
-	ei.eventCb = eventCb
-}
-
-func (ei *resourceInformer) EventCb(ev KubeEvent) {
+func (ei *resourceInformer) putEvent(ev KubeEvent) {
 	if ei.eventCb != nil {
 		ei.eventCb(ev)
 	}
 }
 
-func (ei *resourceInformer) CreateSharedInformer() (err error) {
+func (ei *resourceInformer) createSharedInformer() (err error) {
 	// discover GroupVersionResource for informer
 	log.Debugf("%s: discover GVR for apiVersion '%s' kind '%s'...", ei.Monitor.Metadata.DebugName, ei.Monitor.ApiVersion, ei.Monitor.Kind)
 	ei.GroupVersionResource, err = ei.KubeClient.GroupVersionResource(ei.Monitor.ApiVersion, ei.Monitor.Kind)
@@ -157,7 +129,7 @@ func (ei *resourceInformer) CreateSharedInformer() (err error) {
 		LabelSelector: ei.ListOptions.LabelSelector,
 	}
 
-	err = ei.LoadExistedObjects()
+	err = ei.loadExistedObjects()
 	if err != nil {
 		log.Errorf("load existing objects: %v", err)
 		return err
@@ -167,7 +139,7 @@ func (ei *resourceInformer) CreateSharedInformer() (err error) {
 }
 
 // Snapshot returns all cached objects for this informer
-func (ei *resourceInformer) CachedObjects() []ObjectAndFilterResult {
+func (ei *resourceInformer) getCachedObjects() []ObjectAndFilterResult {
 	ei.cacheLock.RLock()
 	res := make([]ObjectAndFilterResult, 0)
 	for _, obj := range ei.cachedObjects {
@@ -184,7 +156,7 @@ func (ei *resourceInformer) CachedObjects() []ObjectAndFilterResult {
 	return res
 }
 
-func (ei *resourceInformer) EnableKubeEventCb() {
+func (ei *resourceInformer) enableKubeEventCb() {
 	if ei.eventCbEnabled {
 		return
 	}
@@ -193,15 +165,15 @@ func (ei *resourceInformer) EnableKubeEventCb() {
 	ei.eventCbEnabled = true
 	for _, kubeEvent := range ei.eventBuf {
 		// Handle saved kube events.
-		ei.EventCb(kubeEvent)
+		ei.putEvent(kubeEvent)
 	}
 	ei.eventBuf = nil
 }
 
-// LoadExistedObjects get a list of existed objects in namespace that match selectors and
+// loadExistedObjects get a list of existed objects in namespace that match selectors and
 // fills Checksum map with checksums of existing objects.
-func (ei *resourceInformer) LoadExistedObjects() error {
-	defer trace.StartRegion(context.Background(), "LoadExistedObjects").End()
+func (ei *resourceInformer) loadExistedObjects() error {
+	defer trace.StartRegion(context.Background(), "loadExistedObjects").End()
 
 	objList, err := ei.KubeClient.Dynamic().
 		Resource(ei.GroupVersionResource).
@@ -233,7 +205,7 @@ func (ei *resourceInformer) LoadExistedObjects() error {
 			defer measure.Duration(func(d time.Duration) {
 				ei.metricStorage.HistogramObserve("{PREFIX}kube_jq_filter_duration_seconds", d.Seconds(), ei.Monitor.Metadata.MetricLabels, nil)
 			})()
-			objFilterRes, err = ApplyFilter(ei.Monitor.JqFilter, ei.Monitor.FilterFunc, &obj)
+			objFilterRes, err = applyFilter(ei.Monitor.JqFilter, ei.Monitor.FilterFunc, &obj)
 		}()
 
 		if err != nil {
@@ -266,22 +238,22 @@ func (ei *resourceInformer) LoadExistedObjects() error {
 }
 
 func (ei *resourceInformer) OnAdd(obj interface{}) {
-	ei.HandleWatchEvent(obj, WatchEventAdded)
+	ei.handleWatchEvent(obj, WatchEventAdded)
 }
 
 func (ei *resourceInformer) OnUpdate(_, newObj interface{}) {
-	ei.HandleWatchEvent(newObj, WatchEventModified)
+	ei.handleWatchEvent(newObj, WatchEventModified)
 }
 
 func (ei *resourceInformer) OnDelete(obj interface{}) {
-	ei.HandleWatchEvent(obj, WatchEventDeleted)
+	ei.handleWatchEvent(obj, WatchEventDeleted)
 }
 
 // HandleKubeEvent register object in cache. Pass object to callback if object's checksum is changed.
 // TODO refactor: pass KubeEvent as argument
 // TODO add delay to merge Added and Modified events (node added and then labels applied — one hook run on Added+Modified is enough)
 // func (ei *resourceInformer) HandleKubeEvent(obj *unstructured.Unstructured, objectId string, filterResult string, newChecksum string, eventType WatchEventType) {
-func (ei *resourceInformer) HandleWatchEvent(object interface{}, eventType WatchEventType) {
+func (ei *resourceInformer) handleWatchEvent(object interface{}, eventType WatchEventType) {
 	// check if stop
 	if ei.stopped {
 		return
@@ -290,14 +262,14 @@ func (ei *resourceInformer) HandleWatchEvent(object interface{}, eventType Watch
 	defer measure.Duration(func(d time.Duration) {
 		ei.metricStorage.HistogramObserve("{PREFIX}kube_event_duration_seconds", d.Seconds(), ei.Monitor.Metadata.MetricLabels, nil)
 	})()
-	defer trace.StartRegion(context.Background(), "HandleWatchEvent").End()
+	defer trace.StartRegion(context.Background(), "handleWatchEvent").End()
 
 	if staleObj, stale := object.(cache.DeletedFinalStateUnknown); stale {
 		object = staleObj.Obj
 	}
 	obj := object.(*unstructured.Unstructured)
 
-	resourceId := ResourceId(obj)
+	resourceId := resourceId(obj)
 
 	// Always calculate checksum and update cache, because we need an actual state in ei.cachedObjects.
 
@@ -307,7 +279,7 @@ func (ei *resourceInformer) HandleWatchEvent(object interface{}, eventType Watch
 		defer measure.Duration(func(d time.Duration) {
 			ei.metricStorage.HistogramObserve("{PREFIX}kube_jq_filter_duration_seconds", d.Seconds(), ei.Monitor.Metadata.MetricLabels, nil)
 		})()
-		objFilterRes, err = ApplyFilter(ei.Monitor.JqFilter, ei.Monitor.FilterFunc, obj)
+		objFilterRes, err = applyFilter(ei.Monitor.JqFilter, ei.Monitor.FilterFunc, obj)
 	}()
 	if err != nil {
 		log.Errorf("%s: WATCH %s: %s",
@@ -374,7 +346,7 @@ func (ei *resourceInformer) HandleWatchEvent(object interface{}, eventType Watch
 	}
 
 	// Fire KubeEvent only if needed.
-	if ei.ShouldFireEvent(eventType) {
+	if ei.shouldFireEvent(eventType) {
 		log.Debugf("%s: %s %s: send KubeEvent",
 			ei.Monitor.Metadata.DebugName,
 			string(eventType),
@@ -390,7 +362,7 @@ func (ei *resourceInformer) HandleWatchEvent(object interface{}, eventType Watch
 			Objects:     []ObjectAndFilterResult{*objFilterRes},
 		}
 
-		// fix race with EnableKubeEventCb.
+		// fix race with enableKubeEventCb.
 		eventCbEnabled := false
 		ei.eventBufLock.Lock()
 		eventCbEnabled = ei.eventCbEnabled
@@ -398,7 +370,7 @@ func (ei *resourceInformer) HandleWatchEvent(object interface{}, eventType Watch
 
 		if eventCbEnabled {
 			// Pass event info to callback.
-			ei.EventCb(kubeEvent)
+			ei.putEvent(kubeEvent)
 		} else {
 			ei.eventBufLock.Lock()
 			// Save event in buffer until the callback is enabled.
@@ -440,7 +412,7 @@ func (ei *resourceInformer) adjustFieldSelector(selector *FieldSelector, objName
 	return selectorCopy
 }
 
-func (ei *resourceInformer) ShouldFireEvent(checkEvent WatchEventType) bool {
+func (ei *resourceInformer) shouldFireEvent(checkEvent WatchEventType) bool {
 	for _, event := range ei.Monitor.EventTypes {
 		if event == checkEvent {
 			return true
@@ -449,7 +421,7 @@ func (ei *resourceInformer) ShouldFireEvent(checkEvent WatchEventType) bool {
 	return false
 }
 
-func (ei *resourceInformer) Start() {
+func (ei *resourceInformer) start() {
 	log.Debugf("%s: RUN resource informer", ei.Monitor.Metadata.DebugName)
 
 	go func() {
@@ -460,7 +432,7 @@ func (ei *resourceInformer) Start() {
 	}()
 
 	// TODO: separate handler and informer
-	errorHandler := NewWatchErrorHandler(ei.Monitor.Metadata.DebugName, ei.Monitor.Kind, ei.Monitor.Metadata.LogLabels, ei.metricStorage)
+	errorHandler := newWatchErrorHandler(ei.Monitor.Metadata.DebugName, ei.Monitor.Kind, ei.Monitor.Metadata.LogLabels, ei.metricStorage)
 	err := DefaultFactoryStore.Start(ei.KubeClient.Dynamic(), ei.FactoryIndex, ei, errorHandler)
 	if err != nil {
 		ei.Monitor.LogEntry.Errorf("%s: cache is not synced for informer", ei.Monitor.Metadata.DebugName)
@@ -470,28 +442,20 @@ func (ei *resourceInformer) Start() {
 	log.Debugf("%s: informer is ready", ei.Monitor.Metadata.DebugName)
 }
 
-func (ei *resourceInformer) Stop() {
-	log.Debugf("%s: STOP resource informer", ei.Monitor.Metadata.DebugName)
-	if ei.cancel != nil {
-		ei.cancel()
-	}
-	ei.stopped = true
-}
-
-func (ei *resourceInformer) PauseHandleEvents() {
+func (ei *resourceInformer) pauseHandleEvents() {
 	log.Debugf("%s: PAUSE resource informer", ei.Monitor.Metadata.DebugName)
 	ei.stopped = true
 }
 
 // CachedObjectsInfo returns info accumulated from start.
-func (ei *resourceInformer) CachedObjectsInfo() CachedObjectsInfo {
+func (ei *resourceInformer) getCachedObjectsInfo() CachedObjectsInfo {
 	ei.cacheLock.RLock()
 	defer ei.cacheLock.RUnlock()
 	return *ei.cachedObjectsInfo
 }
 
-// CachedObjectsInfoIncrement returns info accumulated from last call and clean it.
-func (ei *resourceInformer) CachedObjectsInfoIncrement() CachedObjectsInfo {
+// getCachedObjectsInfoIncrement returns info accumulated from last call and clean it.
+func (ei *resourceInformer) getCachedObjectsInfoIncrement() CachedObjectsInfo {
 	ei.cacheLock.Lock()
 	defer ei.cacheLock.Unlock()
 	info := *ei.cachedObjectsIncrement
diff --git a/pkg/kube_events_manager/types/types.go b/pkg/kube_events_manager/types/types.go
index 63f53b8..134eff5 100644
--- a/pkg/kube_events_manager/types/types.go
+++ b/pkg/kube_events_manager/types/types.go
@@ -131,7 +131,7 @@ type KubeEvent struct {
 }
 
 func (k KubeEvent) String() string {
-	msgs := []string{}
+	msgs := make([]string, 0)
 	switch k.Type {
 	case TypeSynchronization:
 		if len(k.Objects) > 0 {
diff --git a/pkg/kube_events_manager/util.go b/pkg/kube_events_manager/util.go
index 1fec774..f37869e 100644
--- a/pkg/kube_events_manager/util.go
+++ b/pkg/kube_events_manager/util.go
@@ -15,7 +15,7 @@ import (
 // ResourceId describes object with namespace, kind and name
 //
 // Change with caution, as this string is used for sorting objects and snapshots.
-func ResourceId(obj *unstructured.Unstructured) string {
+func resourceId(obj *unstructured.Unstructured) string {
 	return fmt.Sprintf("%s/%s/%s", obj.GetNamespace(), obj.GetKind(), obj.GetName())
 }
 
@@ -56,8 +56,8 @@ const (
 	ResyncPeriodJitterGranularity = time.Duration(15) * time.Second
 )
 
-// RandomizedResyncPeriod returns a time.Duration between 2 hours and 4 hours with jitter and granularity
-func RandomizedResyncPeriod() time.Duration {
+// randomizedResyncPeriod returns a time.Duration between 2 hours and 4 hours with jitter and granularity
+func randomizedResyncPeriod() time.Duration {
 	spreadCount := ResyncPeriodSpread.Nanoseconds() / ResyncPeriodGranularity.Nanoseconds()
 	rndSpreadDelta := time.Duration(rand.Int63n(spreadCount)) * ResyncPeriodGranularity
 	jitterCount := ResyncPeriodGranularity.Nanoseconds() / ResyncPeriodJitterGranularity.Nanoseconds()
@@ -75,7 +75,7 @@ type CachedObjectsInfo struct {
 	Cleaned  uint64 `json:"cleaned"`
 }
 
-func (c *CachedObjectsInfo) Add(in CachedObjectsInfo) {
+func (c *CachedObjectsInfo) add(in CachedObjectsInfo) {
 	c.Count += in.Count
 	c.Added += in.Added
 	c.Deleted += in.Deleted
diff --git a/pkg/metric_storage/metric_storage.go b/pkg/metric_storage/metric_storage.go
index 4da4844..1ca34e7 100644
--- a/pkg/metric_storage/metric_storage.go
+++ b/pkg/metric_storage/metric_storage.go
@@ -43,8 +43,13 @@ type MetricStorage struct {
 	Registerer prometheus.Registerer
 }
 
-func NewMetricStorage() *MetricStorage {
+func NewMetricStorage(ctx context.Context, prefix string, newRegistry bool) *MetricStorage {
+	cctx, cancel := context.WithCancel(ctx)
 	m := &MetricStorage{
+		ctx:    cctx,
+		cancel: cancel,
+
+		Prefix:           prefix,
 		Gauges:           make(map[string]*prometheus.GaugeVec),
 		Counters:         make(map[string]*prometheus.CounterVec),
 		Histograms:       make(map[string]*prometheus.HistogramVec),
@@ -54,38 +59,18 @@ func NewMetricStorage() *MetricStorage {
 		Registerer:       prometheus.DefaultRegisterer,
 	}
 	m.GroupedVault.Registerer = m.Registerer
-	return m
-}
 
-func (m *MetricStorage) WithContext(ctx context.Context) {
-	m.ctx, m.cancel = context.WithCancel(ctx)
-}
-
-func (m *MetricStorage) WithPrefix(prefix string) {
-	m.Prefix = prefix
-}
-
-func (m *MetricStorage) WithNewRegistry() {
-	m.Registry = prometheus.NewRegistry()
-	m.Gatherer = m.Registry
-	m.Registerer = m.Registry
-	m.GroupedVault.Registerer = m.Registry
-}
-
-func (m *MetricStorage) Stop() {
-	if m.cancel != nil {
-		m.cancel()
+	if newRegistry {
+		m.Registry = prometheus.NewRegistry()
+		m.Gatherer = m.Registry
+		m.Registerer = m.Registry
+		m.GroupedVault.Registerer = m.Registry
 	}
-}
 
-func (m *MetricStorage) Start() {
-	// go func() {
-	//	<-m.ctx.Done()
-	//	return
-	// }()
+	return m
 }
 
-func (m *MetricStorage) ResolveMetricName(name string) string {
+func (m *MetricStorage) resolveMetricName(name string) string {
 	if strings.Contains(name, PrefixTemplate) {
 		return strings.Replace(name, PrefixTemplate, m.Prefix, 1)
 	}
@@ -101,7 +86,7 @@ func (m *MetricStorage) GaugeSet(metric string, value float64, labels map[string
 	defer func() {
 		if r := recover(); r != nil {
 			log.WithField("operator.component", "metricsStorage").
-				Errorf("Metric gauge set %s %v with %v: %v", m.ResolveMetricName(metric), LabelNames(labels), labels, r)
+				Errorf("Metric gauge set %s %v with %v: %v", m.resolveMetricName(metric), LabelNames(labels), labels, r)
 		}
 	}()
 
@@ -115,7 +100,7 @@ func (m *MetricStorage) GaugeAdd(metric string, value float64, labels map[string
 	defer func() {
 		if r := recover(); r != nil {
 			log.WithField("operator.component", "metricsStorage").
-				Errorf("Metric gauge add %s %v with %v: %v", m.ResolveMetricName(metric), LabelNames(labels), labels, r)
+				Errorf("Metric gauge add %s %v with %v: %v", m.resolveMetricName(metric), LabelNames(labels), labels, r)
 		}
 	}()
 
@@ -136,7 +121,7 @@ func (m *MetricStorage) Gauge(metric string, labels map[string]string) *promethe
 
 // RegisterGauge registers a gauge.
 func (m *MetricStorage) RegisterGauge(metric string, labels map[string]string) *prometheus.GaugeVec {
-	metricName := m.ResolveMetricName(metric)
+	metricName := m.resolveMetricName(metric)
 
 	defer func() {
 		if r := recover(); r != nil {
@@ -176,7 +161,7 @@ func (m *MetricStorage) CounterAdd(metric string, value float64, labels map[stri
 	defer func() {
 		if r := recover(); r != nil {
 			log.WithField("operator.component", "metricsStorage").
-				Errorf("Metric counter add %s %v with %v: %v", m.ResolveMetricName(metric), LabelNames(labels), labels, r)
+				Errorf("Metric counter add %s %v with %v: %v", m.resolveMetricName(metric), LabelNames(labels), labels, r)
 		}
 	}()
 	m.Counter(metric, labels).With(labels).Add(value)
@@ -196,7 +181,7 @@ func (m *MetricStorage) Counter(metric string, labels map[string]string) *promet
 
 // RegisterCounter registers a counter.
 func (m *MetricStorage) RegisterCounter(metric string, labels map[string]string) *prometheus.CounterVec {
-	metricName := m.ResolveMetricName(metric)
+	metricName := m.resolveMetricName(metric)
 
 	defer func() {
 		if r := recover(); r != nil {
@@ -235,7 +220,7 @@ func (m *MetricStorage) HistogramObserve(metric string, value float64, labels ma
 	defer func() {
 		if r := recover(); r != nil {
 			log.WithField("operator.component", "metricsStorage").
-				Errorf("Metric histogram observe %s %v with %v: %v", m.ResolveMetricName(metric), LabelNames(labels), labels, r)
+				Errorf("Metric histogram observe %s %v with %v: %v", m.resolveMetricName(metric), LabelNames(labels), labels, r)
 		}
 	}()
 	m.Histogram(metric, labels, buckets).With(labels).Observe(value)
@@ -252,7 +237,7 @@ func (m *MetricStorage) Histogram(metric string, labels map[string]string, bucke
 }
 
 func (m *MetricStorage) RegisterHistogram(metric string, labels map[string]string, buckets []float64) *prometheus.HistogramVec {
-	metricName := m.ResolveMetricName(metric)
+	metricName := m.resolveMetricName(metric)
 
 	defer func() {
 		if r := recover(); r != nil {
@@ -294,7 +279,7 @@ func (m *MetricStorage) RegisterHistogram(metric string, labels map[string]strin
 
 // Batch operations for metrics from hooks
 
-func (m *MetricStorage) SendBatchV0(ops []operation.MetricOperation, labels map[string]string) error {
+func (m *MetricStorage) sendBatchV0(ops []operation.MetricOperation, labels map[string]string) error {
 	if m == nil {
 		return nil
 	}
@@ -346,11 +331,11 @@ func (m *MetricStorage) SendBatch(ops []operation.MetricOperation, labels map[st
 
 	// Expire each group and apply new metric operations.
 	for group, ops := range groupedOps {
-		m.ApplyGroupOperations(group, ops, labels)
+		m.applyGroupOperations(group, ops, labels)
 	}
 
 	// Send non-grouped metrics.
-	err = m.SendBatchV0(nonGroupedOps, labels)
+	err = m.sendBatchV0(nonGroupedOps, labels)
 	if err != nil {
 		return err
 	}
@@ -384,8 +369,8 @@ func (m *MetricStorage) ApplyOperation(op operation.MetricOperation, commonLabel
 	}
 }
 
-// ApplyGroupOperations set metrics for group to a new state defined by ops.
-func (m *MetricStorage) ApplyGroupOperations(group string, ops []operation.MetricOperation, commonLabels map[string]string) {
+// applyGroupOperations set metrics for group to a new state defined by ops.
+func (m *MetricStorage) applyGroupOperations(group string, ops []operation.MetricOperation, commonLabels map[string]string) {
 	// Implicitly expire all metrics for group.
 	m.GroupedVault.ExpireGroupMetrics(group)
 
diff --git a/pkg/schedule_manager/schedule_manager.go b/pkg/schedule_manager/schedule_manager.go
index eef14ab..f0c7bd1 100644
--- a/pkg/schedule_manager/schedule_manager.go
+++ b/pkg/schedule_manager/schedule_manager.go
@@ -10,7 +10,6 @@ import (
 )
 
 type ScheduleManager interface {
-	WithContext(ctx context.Context)
 	Stop()
 	Start()
 	Add(entry ScheduleEntry)
@@ -33,8 +32,11 @@ type scheduleManager struct {
 
 var _ ScheduleManager = &scheduleManager{}
 
-var NewScheduleManager = func() *scheduleManager {
+func NewScheduleManager(ctx context.Context) *scheduleManager {
+	cctx, cancel := context.WithCancel(ctx)
 	sm := &scheduleManager{
+		ctx:        cctx,
+		cancel:     cancel,
 		ScheduleCh: make(chan string, 1),
 		cron:       cron.New(),
 		Entries:    make(map[string]CronEntry),
@@ -42,10 +44,6 @@ var NewScheduleManager = func() *scheduleManager {
 	return sm
 }
 
-func (sm *scheduleManager) WithContext(ctx context.Context) {
-	sm.ctx, sm.cancel = context.WithCancel(ctx)
-}
-
 func (sm *scheduleManager) Stop() {
 	if sm.cancel != nil {
 		sm.cancel()
diff --git a/pkg/shell-operator/bootstrap.go b/pkg/shell-operator/bootstrap.go
index b8ef9ad..38222f6 100644
--- a/pkg/shell-operator/bootstrap.go
+++ b/pkg/shell-operator/bootstrap.go
@@ -3,9 +3,6 @@ package shell_operator
 import (
 	"context"
 	"fmt"
-	"net/http"
-	"os"
-	"path/filepath"
 
 	log "github.com/sirupsen/logrus"
 
@@ -17,7 +14,7 @@ import (
 	"github.com/flant/shell-operator/pkg/kube_events_manager"
 	"github.com/flant/shell-operator/pkg/schedule_manager"
 	"github.com/flant/shell-operator/pkg/task/queue"
-	utils_file "github.com/flant/shell-operator/pkg/utils/file"
+	utils "github.com/flant/shell-operator/pkg/utils/file"
 	"github.com/flant/shell-operator/pkg/webhook/admission"
 	"github.com/flant/shell-operator/pkg/webhook/conversion"
 )
@@ -32,35 +29,34 @@ func Init() (*ShellOperator, error) {
 	log.Infof(app.AppStartMessage)
 	log.Debug(jq.FilterInfo())
 
-	hooksDir, err := RequireExistingDirectory(app.HooksDir)
+	hooksDir, err := utils.RequireExistingDirectory(app.HooksDir)
 	if err != nil {
 		log.Errorf("Fatal: hooks directory is required: %s", err)
 		return nil, err
 	}
 
-	tempDir, err := EnsureTempDirectory(app.TempDir)
+	tempDir, err := utils.EnsureTempDirectory(app.TempDir)
 	if err != nil {
 		log.Errorf("Fatal: temp directory: %s", err)
 		return nil, err
 	}
 
-	op := NewShellOperator()
-	op.WithContext(context.Background())
+	op := NewShellOperator(context.Background())
 
 	// Debug server.
-	debugServer, err := InitDefaultDebugServer()
+	debugServer, err := RunDefaultDebugServer(app.DebugUnixSocket, app.DebugHttpServerAddr)
 	if err != nil {
 		log.Errorf("Fatal: start Debug server: %s", err)
 		return nil, err
 	}
 
-	err = AssembleCommonOperator(op)
+	err = op.AssembleCommonOperator(app.ListenAddress, app.ListenPort)
 	if err != nil {
 		log.Errorf("Fatal: %s", err)
 		return nil, err
 	}
 
-	err = AssembleShellOperator(op, hooksDir, tempDir, debugServer, runtimeConfig)
+	err = op.assembleShellOperator(hooksDir, tempDir, debugServer, runtimeConfig)
 	if err != nil {
 		log.Errorf("Fatal: %s", err)
 		return nil, err
@@ -69,58 +65,15 @@ func Init() (*ShellOperator, error) {
 	return op, nil
 }
 
-func RequireExistingDirectory(inDir string) (dir string, err error) {
-	if inDir == "" {
-		return "", fmt.Errorf("path is required but not set")
-	}
-
-	dir, err = filepath.Abs(inDir)
-	if err != nil {
-		return "", fmt.Errorf("get absolute path: %v", err)
-	}
-	if exists, _ := utils_file.DirExists(dir); !exists {
-		return "", fmt.Errorf("path '%s' not exist", dir)
-	}
-
-	return dir, nil
-}
-
-func EnsureTempDirectory(inDir string) (string, error) {
-	// No path to temporary dir, use default temporary dir.
-	if inDir == "" {
-		tmpPath := app.AppName + "-*"
-		dir, err := os.MkdirTemp("", tmpPath)
-		if err != nil {
-			return "", fmt.Errorf("create tmp dir in '%s': %s", tmpPath, err)
-		}
-		return dir, nil
-	}
-
-	// Get absolute path for temporary directory and create if needed.
-	dir, err := filepath.Abs(inDir)
-	if err != nil {
-		return "", fmt.Errorf("get absolute path: %v", err)
-	}
-	if exists, _ := utils_file.DirExists(dir); !exists {
-		err := os.Mkdir(dir, os.FileMode(0o777))
-		if err != nil {
-			return "", fmt.Errorf("create tmp dir '%s': %s", dir, err)
-		}
-	}
-	return dir, nil
-}
-
 // AssembleCommonOperator instantiate common dependencies. These dependencies
 // may be used for shell-operator derivatives, like addon-operator.
-func AssembleCommonOperator(op *ShellOperator) (err error) {
-	err = StartHttpServer(app.ListenAddress, app.ListenPort, http.DefaultServeMux)
-	if err != nil {
-		return fmt.Errorf("start HTTP server: %s", err)
-	}
+// requires listenAddress, listenPort to run http server for operator APIs
+func (op *ShellOperator) AssembleCommonOperator(listenAddress, listenPort string) (err error) {
+	op.APIServer = newBaseHTTPServer(listenAddress, listenPort)
 
-	op.MetricStorage = DefaultMetricStorage(op.ctx)
+	op.MetricStorage = defaultMetricStorage(op.ctx)
 
-	op.HookMetricStorage, err = SetupHookMetricStorageAndServer(op.ctx)
+	op.setupHookMetricStorage()
 	if err != nil {
 		return fmt.Errorf("start HTTP server for hook metrics: %s", err)
 	}
@@ -130,23 +83,23 @@ func AssembleCommonOperator(op *ShellOperator) (err error) {
 	}
 
 	// 'main' Kubernetes client.
-	op.KubeClient, err = InitDefaultMainKubeClient(op.MetricStorage)
+	op.KubeClient, err = initDefaultMainKubeClient(op.MetricStorage)
 	if err != nil {
 		return err
 	}
 
 	// ObjectPatcher with a separate Kubernetes client.
-	op.ObjectPatcher, err = InitDefaultObjectPatcher(op.MetricStorage)
+	op.ObjectPatcher, err = initDefaultObjectPatcher(op.MetricStorage)
 	if err != nil {
 		return err
 	}
 
-	SetupEventManagers(op)
+	op.SetupEventManagers()
 
 	return nil
 }
 
-// AssembleShellOperator uses settings in app package to create all
+// assembleShellOperator uses settings in app package to create all
 // dependencies needed for the full-fledged ShellOperator.
 //
 // - check directories
@@ -158,32 +111,32 @@ func AssembleCommonOperator(op *ShellOperator) (err error) {
 //   - hook manager
 //   - kubernetes events manager
 //   - schedule manager
-func AssembleShellOperator(op *ShellOperator, hooksDir string, tempDir string, debugServer *debug.Server, runtimeConfig *config.Config) (err error) {
-	RegisterDefaultRoutes(op)
+func (op *ShellOperator) assembleShellOperator(hooksDir string, tempDir string, debugServer *debug.Server, runtimeConfig *config.Config) (err error) {
+	registerDefaultRoutes(op)
 
-	RegisterDebugQueueRoutes(debugServer, op)
-	RegisterDebugHookRoutes(debugServer, op)
-	RegisterDebugConfigRoutes(debugServer, runtimeConfig)
+	op.RegisterDebugQueueRoutes(debugServer)
+	op.RegisterDebugHookRoutes(debugServer)
+	op.RegisterDebugConfigRoutes(debugServer, runtimeConfig)
 
-	RegisterShellOperatorMetrics(op.MetricStorage)
+	registerShellOperatorMetrics(op.MetricStorage)
 
 	// Create webhookManagers with dependencies.
-	SetupHookManagers(op, hooksDir, tempDir)
+	op.setupHookManagers(hooksDir, tempDir)
 
 	// Search and configure all hooks.
-	err = op.InitHookManager()
+	err = op.initHookManager()
 	if err != nil {
 		return fmt.Errorf("initialize HookManager fail: %s", err)
 	}
 
 	// Load validation hooks.
-	err = op.InitValidatingWebhookManager()
+	err = op.initValidatingWebhookManager()
 	if err != nil {
 		return fmt.Errorf("initialize ValidatingWebhookManager fail: %s", err)
 	}
 
 	// Load conversion hooks.
-	err = op.InitConversionWebhookManager()
+	err = op.initConversionWebhookManager()
 	if err != nil {
 		return fmt.Errorf("initialize ConversionWebhookManager fail: %s", err)
 	}
@@ -192,35 +145,33 @@ func AssembleShellOperator(op *ShellOperator, hooksDir string, tempDir string, d
 }
 
 // SetupEventManagers instantiate queues and managers for schedule and Kubernetes events.
-func SetupEventManagers(op *ShellOperator) {
+// This function is also used in the addon-operator
+func (op *ShellOperator) SetupEventManagers() {
 	// Initialize the task queues set with the "main" queue.
 	op.TaskQueues = queue.NewTaskQueueSet()
 	op.TaskQueues.WithContext(op.ctx)
 	op.TaskQueues.WithMetricStorage(op.MetricStorage)
 
 	// Initialize schedule manager.
-	op.ScheduleManager = schedule_manager.NewScheduleManager()
-	op.ScheduleManager.WithContext(op.ctx)
+	op.ScheduleManager = schedule_manager.NewScheduleManager(op.ctx)
 
 	// Initialize kubernetes events manager.
-	op.KubeEventsManager = kube_events_manager.NewKubeEventsManager()
-	op.KubeEventsManager.WithKubeClient(op.KubeClient)
-	op.KubeEventsManager.WithContext(op.ctx)
+	op.KubeEventsManager = kube_events_manager.NewKubeEventsManager(op.ctx, op.KubeClient)
 	op.KubeEventsManager.WithMetricStorage(op.MetricStorage)
 
 	// Initialize events handler that emit tasks to run hooks
-	op.ManagerEventsHandler = NewManagerEventsHandler()
-	op.ManagerEventsHandler.WithContext(op.ctx)
-	op.ManagerEventsHandler.WithTaskQueueSet(op.TaskQueues)
-	op.ManagerEventsHandler.WithScheduleManager(op.ScheduleManager)
-	op.ManagerEventsHandler.WithKubeEventsManager(op.KubeEventsManager)
+	cfg := &managerEventsHandlerConfig{
+		tqs:  op.TaskQueues,
+		mgr:  op.KubeEventsManager,
+		smgr: op.ScheduleManager,
+	}
+	op.ManagerEventsHandler = newManagerEventsHandler(op.ctx, cfg)
 }
 
-// SetupHookManagers instantiates different hook managers.
-func SetupHookManagers(op *ShellOperator, hooksDir string, tempDir string) {
+// setupHookManagers instantiates different hook managers.
+func (op *ShellOperator) setupHookManagers(hooksDir string, tempDir string) {
 	// Initialize admission webhooks manager.
-	op.AdmissionWebhookManager = admission.NewWebhookManager()
-	op.AdmissionWebhookManager.WithKubeClient(op.KubeClient)
+	op.AdmissionWebhookManager = admission.NewWebhookManager(op.KubeClient)
 	op.AdmissionWebhookManager.Settings = app.ValidatingWebhookSettings
 	op.AdmissionWebhookManager.Namespace = app.Namespace
 
@@ -231,10 +182,13 @@ func SetupHookManagers(op *ShellOperator, hooksDir string, tempDir string) {
 	op.ConversionWebhookManager.Namespace = app.Namespace
 
 	// Initialize Hook manager.
-	op.HookManager = hook.NewHookManager()
-	op.HookManager.WithDirectories(hooksDir, tempDir)
-	op.HookManager.WithKubeEventManager(op.KubeEventsManager)
-	op.HookManager.WithScheduleManager(op.ScheduleManager)
-	op.HookManager.WithAdmissionWebhookManager(op.AdmissionWebhookManager)
-	op.HookManager.WithConversionWebhookManager(op.ConversionWebhookManager)
+	cfg := &hook.HookManagerConfig{
+		WorkingDir: hooksDir,
+		TempDir:    tempDir,
+		Kmgr:       op.KubeEventsManager,
+		Smgr:       op.ScheduleManager,
+		Wmgr:       op.AdmissionWebhookManager,
+		Cmgr:       op.ConversionWebhookManager,
+	}
+	op.HookManager = hook.NewHookManager(cfg)
 }
diff --git a/pkg/shell-operator/combine_binding_context.go b/pkg/shell-operator/combine_binding_context.go
index 95665d2..4924d22 100644
--- a/pkg/shell-operator/combine_binding_context.go
+++ b/pkg/shell-operator/combine_binding_context.go
@@ -16,7 +16,7 @@ type CombineResult struct {
 	MonitorIDs      []string
 }
 
-// CombineBindingContextForHook combines binding contexts from a sequence of task with similar
+// combineBindingContextForHook combines binding contexts from a sequence of task with similar
 // hook name and task type into array of binding context and delete excess tasks from queue.
 //
 // Also, sequences of binding contexts with similar group are compacted in one binding context.
@@ -24,7 +24,7 @@ type CombineResult struct {
 // If input task has no metadata, result will be nil.
 // Metadata should implement HookNameAccessor, BindingContextAccessor and MonitorIDAccessor interfaces.
 // DEV WARNING! Do not use HookMetadataAccessor here. Use only *Accessor interfaces because this method is used from addon-operator.
-func CombineBindingContextForHook(tqs *queue.TaskQueueSet, q *queue.TaskQueue, t task.Task, stopCombineFn func(tsk task.Task) bool) *CombineResult {
+func combineBindingContextForHook(tqs *queue.TaskQueueSet, q *queue.TaskQueue, t task.Task, stopCombineFn func(tsk task.Task) bool) *CombineResult {
 	if q == nil {
 		return nil
 	}
diff --git a/pkg/shell-operator/debug_server.go b/pkg/shell-operator/debug_server.go
index 7486c5b..82e879e 100644
--- a/pkg/shell-operator/debug_server.go
+++ b/pkg/shell-operator/debug_server.go
@@ -8,36 +8,34 @@ import (
 
 	"github.com/go-chi/chi/v5"
 
-	"github.com/flant/shell-operator/pkg/app"
 	"github.com/flant/shell-operator/pkg/config"
 	"github.com/flant/shell-operator/pkg/debug"
 	"github.com/flant/shell-operator/pkg/task/dump"
 )
 
-func DefaultDebugServer() *debug.Server {
-	dbgSrv := debug.NewServer("/debug", app.DebugUnixSocket, app.DebugHttpServerAddr)
+// RunDefaultDebugServer initialized and run default debug server on unix and http sockets
+// This method is also used in addon-operator
+func RunDefaultDebugServer(unixSocket, httpServerAddress string) (*debug.Server, error) {
+	dbgSrv := debug.NewServer("/debug", unixSocket, httpServerAddress)
 
-	return dbgSrv
-}
-
-func InitDefaultDebugServer() (*debug.Server, error) {
-	dbgSrv := DefaultDebugServer()
-	err := dbgSrv.Init()
-	if err != nil {
-		return nil, err
-	}
-	dbgSrv.Route("/", func(_ *http.Request) (interface{}, error) {
+	dbgSrv.RegisterHandler(http.MethodGet, "/", func(_ *http.Request) (interface{}, error) {
 		return "debug endpoint is alive", nil
 	})
-	return dbgSrv, nil
+
+	err := dbgSrv.Init()
+
+	return dbgSrv, err
 }
 
-func RegisterDebugQueueRoutes(dbgSrv *debug.Server, op *ShellOperator) {
-	dbgSrv.Route("/queue/main.{format:(json|yaml|text)}", func(_ *http.Request) (interface{}, error) {
-		return dump.TaskQueueMainToText(op.TaskQueues), nil
+// RegisterDebugQueueRoutes register routes for dumping main queue
+// this method is also used in addon-operator
+func (op *ShellOperator) RegisterDebugQueueRoutes(dbgSrv *debug.Server) {
+	dbgSrv.RegisterHandler(http.MethodGet, "/queue/main.{format:(json|yaml|text)}", func(req *http.Request) (interface{}, error) {
+		format := debug.FormatFromRequest(req)
+		return dump.TaskMainQueue(op.TaskQueues, format), nil
 	})
 
-	dbgSrv.Route("/queue/list.{format:(json|yaml|text)}", func(req *http.Request) (interface{}, error) {
+	dbgSrv.RegisterHandler(http.MethodGet, "/queue/list.{format:(json|yaml|text)}", func(req *http.Request) (interface{}, error) {
 		showEmptyStr := req.URL.Query().Get("showEmpty")
 		showEmpty, err := strconv.ParseBool(showEmptyStr)
 		if err != nil {
@@ -48,12 +46,13 @@ func RegisterDebugQueueRoutes(dbgSrv *debug.Server, op *ShellOperator) {
 	})
 }
 
-func RegisterDebugHookRoutes(dbgSrv *debug.Server, op *ShellOperator) {
-	dbgSrv.Route("/hook/list.{format:(json|yaml|text)}", func(_ *http.Request) (interface{}, error) {
+// RegisterDebugHookRoutes register routes for dumping queues
+func (op *ShellOperator) RegisterDebugHookRoutes(dbgSrv *debug.Server) {
+	dbgSrv.RegisterHandler(http.MethodGet, "/hook/list.{format:(json|yaml|text)}", func(_ *http.Request) (interface{}, error) {
 		return op.HookManager.GetHookNames(), nil
 	})
 
-	dbgSrv.Route("/hook/{name}/snapshots.{format:(json|yaml|text)}", func(r *http.Request) (interface{}, error) {
+	dbgSrv.RegisterHandler(http.MethodGet, "/hook/{name}/snapshots.{format:(json|yaml|text)}", func(r *http.Request) (interface{}, error) {
 		hookName := chi.URLParam(r, "name")
 		h := op.HookManager.GetHook(hookName)
 		return h.HookController.SnapshotsDump(), nil
@@ -61,8 +60,9 @@ func RegisterDebugHookRoutes(dbgSrv *debug.Server, op *ShellOperator) {
 }
 
 // RegisterDebugConfigRoutes registers routes to manage runtime configuration.
-func RegisterDebugConfigRoutes(dbgSrv *debug.Server, runtimeConfig *config.Config) {
-	dbgSrv.Route("/config/list.{format:(json|yaml|text)}", func(r *http.Request) (interface{}, error) {
+// This method is also used in addon-operator
+func (op *ShellOperator) RegisterDebugConfigRoutes(dbgSrv *debug.Server, runtimeConfig *config.Config) {
+	dbgSrv.RegisterHandler(http.MethodGet, "/config/list.{format:(json|yaml|text)}", func(r *http.Request) (interface{}, error) {
 		format := debug.FormatFromRequest(r)
 		if format == "text" {
 			return runtimeConfig.String(), nil
@@ -70,31 +70,35 @@ func RegisterDebugConfigRoutes(dbgSrv *debug.Server, runtimeConfig *config.Confi
 		return runtimeConfig.List(), nil
 	})
 
-	dbgSrv.RoutePOST("/config/set", func(r *http.Request) (interface{}, error) {
+	dbgSrv.RegisterHandler(http.MethodPost, "/config/set", func(r *http.Request) (interface{}, error) {
+		err := r.ParseForm()
+		if err != nil {
+			return nil, err
+		}
+
 		name := r.PostForm.Get("name")
 		if name == "" {
-			return nil, fmt.Errorf("'name' parameter is required")
+			return nil, &debug.BadRequestError{Msg: "'name' parameter is required"}
 		}
 		if !runtimeConfig.Has(name) {
-			return nil, fmt.Errorf("unknown runtime parameter '%s'", name)
+			return nil, &debug.BadRequestError{Msg: fmt.Sprintf("unknown runtime parameter %q", name)}
 		}
 
 		value := r.PostForm.Get("value")
 		if name == "" {
-			return nil, fmt.Errorf("'value' parameter is required")
+			return nil, &debug.BadRequestError{Msg: "'value' parameter is required"}
 		}
 
-		if err := runtimeConfig.IsValid(name, value); err != nil {
-			return nil, fmt.Errorf("'value' parameter is invalid: %w", err)
+		if err = runtimeConfig.IsValid(name, value); err != nil {
+			return nil, &debug.BadRequestError{Msg: fmt.Sprintf("'value' parameter is invalid: %s", err)}
 		}
 
 		var duration time.Duration
-		var err error
 		durationStr := r.PostForm.Get("duration")
 		if durationStr != "" {
 			duration, err = time.ParseDuration(durationStr)
 			if err != nil {
-				return nil, fmt.Errorf("parse duration: %v", err)
+				return nil, &debug.BadRequestError{Msg: fmt.Sprintf("parse duration %q failed: %s", durationStr, err)}
 			}
 		}
 		if duration == 0 {
@@ -102,6 +106,7 @@ func RegisterDebugConfigRoutes(dbgSrv *debug.Server, runtimeConfig *config.Confi
 		} else {
 			runtimeConfig.SetTemporarily(name, value, duration)
 		}
+
 		return nil, runtimeConfig.LastError(name)
 	})
 }
diff --git a/pkg/shell-operator/http_server.go b/pkg/shell-operator/http_server.go
index 1f039f5..486e265 100644
--- a/pkg/shell-operator/http_server.go
+++ b/pkg/shell-operator/http_server.go
@@ -1,39 +1,87 @@
 package shell_operator
 
 import (
+	"context"
 	"fmt"
-	"net"
 	"net/http"
-	"os"
+	"time"
 
+	"github.com/go-chi/chi/v5"
 	log "github.com/sirupsen/logrus"
 
 	"github.com/flant/shell-operator/pkg/app"
 )
 
-func StartHttpServer(ip string, port string, mux *http.ServeMux) error {
-	address := fmt.Sprintf("%s:%s", ip, port)
+type baseHTTPServer struct {
+	router chi.Router
 
-	// Check if port is available
-	listener, err := net.Listen("tcp", address)
-	if err != nil {
-		return fmt.Errorf("listen on '%s' fails: %v", address, err)
+	address string
+	port    string
+}
+
+// Start runs http server
+func (bhs *baseHTTPServer) Start(ctx context.Context) {
+	srv := &http.Server{
+		Addr:         bhs.address + ":" + bhs.port,
+		Handler:      bhs.router,
+		ReadTimeout:  30 * time.Second,
+		WriteTimeout: 30 * time.Second,
 	}
 
-	log.Infof("Listen on %s", address)
+	go func() {
+		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
+			log.Fatalf("base http server listen: %s\n", err)
+		}
+	}()
+	log.Infof("base http server started at %s:%s", bhs.address, bhs.port)
 
 	go func() {
-		if err := http.Serve(listener, mux); err != nil {
-			log.Errorf("Fatal: error starting HTTP server: %s", err)
-			os.Exit(1)
+		<-ctx.Done()
+		log.Info("base http server stopped")
+
+		cctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+		defer func() {
+			// extra handling here
+			cancel()
+		}()
+
+		if err := srv.Shutdown(cctx); err != nil {
+			log.Fatalf("base http server shutdown failed:%+v", err)
 		}
 	}()
+}
+
+// RegisterRoute register http.HandlerFunc
+func (bhs *baseHTTPServer) RegisterRoute(method, pattern string, h http.HandlerFunc) {
+	switch method {
+	case http.MethodGet:
+		bhs.router.Get(pattern, h)
+
+	case http.MethodPost:
+		bhs.router.Post(pattern, h)
+
+	case http.MethodPut:
+		bhs.router.Put(pattern, h)
+
+	case http.MethodDelete:
+		bhs.router.Delete(pattern, h)
+	}
+}
+
+func newBaseHTTPServer(address, port string) *baseHTTPServer {
+	router := chi.NewRouter()
+
+	srv := &baseHTTPServer{
+		router:  router,
+		address: address,
+		port:    port,
+	}
 
-	return nil
+	return srv
 }
 
-func RegisterDefaultRoutes(op *ShellOperator) {
-	http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
+func registerDefaultRoutes(op *ShellOperator) {
+	op.APIServer.RegisterRoute(http.MethodGet, "/", func(writer http.ResponseWriter, request *http.Request) {
 		_, _ = fmt.Fprintf(writer, `<html>
     <head><title>Shell operator</title></head>
     <body>
@@ -43,7 +91,7 @@ func RegisterDefaultRoutes(op *ShellOperator) {
     </html>`, app.ListenPort)
 	})
 
-	http.HandleFunc("/metrics", func(writer http.ResponseWriter, request *http.Request) {
+	op.APIServer.RegisterRoute(http.MethodGet, "/metrics", func(writer http.ResponseWriter, request *http.Request) {
 		if op.MetricStorage != nil {
 			op.MetricStorage.Handler().ServeHTTP(writer, request)
 		}
diff --git a/pkg/shell-operator/kube_client.go b/pkg/shell-operator/kube_client.go
index b49600c..3095cb9 100644
--- a/pkg/shell-operator/kube_client.go
+++ b/pkg/shell-operator/kube_client.go
@@ -7,36 +7,30 @@ import (
 	"github.com/flant/shell-operator/pkg/app"
 	"github.com/flant/shell-operator/pkg/kube/object_patch"
 	"github.com/flant/shell-operator/pkg/metric_storage"
+	utils "github.com/flant/shell-operator/pkg/utils/labels"
 )
 
 var (
-	DefaultMainKubeClientMetricLabels          = map[string]string{"component": "main"}
-	DefaultObjectPatcherKubeClientMetricLabels = map[string]string{"component": "object_patcher"}
+	defaultMainKubeClientMetricLabels          = map[string]string{"component": "main"}
+	defaultObjectPatcherKubeClientMetricLabels = map[string]string{"component": "object_patcher"}
 )
 
-func DefaultIfEmpty(m map[string]string, def map[string]string) map[string]string {
-	if len(m) == 0 {
-		return def
-	}
-	return m
-}
-
-// DefaultMainKubeClient creates a Kubernetes client for hooks. No timeout specified, because
+// defaultMainKubeClient creates a Kubernetes client for hooks. No timeout specified, because
 // timeout will reset connections for Watchers.
-func DefaultMainKubeClient(metricStorage *metric_storage.MetricStorage, metricLabels map[string]string) klient.Client {
+func defaultMainKubeClient(metricStorage *metric_storage.MetricStorage, metricLabels map[string]string) *klient.Client {
 	client := klient.New()
 	client.WithContextName(app.KubeContext)
 	client.WithConfigPath(app.KubeConfig)
 	client.WithRateLimiterSettings(app.KubeClientQps, app.KubeClientBurst)
 	client.WithMetricStorage(metricStorage)
-	client.WithMetricLabels(DefaultIfEmpty(metricLabels, DefaultMainKubeClientMetricLabels))
+	client.WithMetricLabels(utils.DefaultIfEmpty(metricLabels, defaultMainKubeClientMetricLabels))
 	return client
 }
 
-func InitDefaultMainKubeClient(metricStorage *metric_storage.MetricStorage) (klient.Client, error) {
+func initDefaultMainKubeClient(metricStorage *metric_storage.MetricStorage) (*klient.Client, error) {
 	//nolint:staticcheck
-	klient.RegisterKubernetesClientMetrics(metricStorage, DefaultMainKubeClientMetricLabels)
-	kubeClient := DefaultMainKubeClient(metricStorage, DefaultMainKubeClientMetricLabels)
+	klient.RegisterKubernetesClientMetrics(metricStorage, defaultMainKubeClientMetricLabels)
+	kubeClient := defaultMainKubeClient(metricStorage, defaultMainKubeClientMetricLabels)
 	err := kubeClient.Init()
 	if err != nil {
 		return nil, fmt.Errorf("initialize 'main' Kubernetes client: %s\n", err)
@@ -44,20 +38,20 @@ func InitDefaultMainKubeClient(metricStorage *metric_storage.MetricStorage) (kli
 	return kubeClient, nil
 }
 
-// DefaultObjectPatcherKubeClient initializes a Kubernetes client for ObjectPatcher. Timeout is specified here.
-func DefaultObjectPatcherKubeClient(metricStorage *metric_storage.MetricStorage, metricLabels map[string]string) klient.Client {
+// defaultObjectPatcherKubeClient initializes a Kubernetes client for ObjectPatcher. Timeout is specified here.
+func defaultObjectPatcherKubeClient(metricStorage *metric_storage.MetricStorage, metricLabels map[string]string) *klient.Client {
 	client := klient.New()
 	client.WithContextName(app.KubeContext)
 	client.WithConfigPath(app.KubeConfig)
 	client.WithRateLimiterSettings(app.ObjectPatcherKubeClientQps, app.ObjectPatcherKubeClientBurst)
 	client.WithMetricStorage(metricStorage)
-	client.WithMetricLabels(DefaultIfEmpty(metricLabels, DefaultObjectPatcherKubeClientMetricLabels))
+	client.WithMetricLabels(utils.DefaultIfEmpty(metricLabels, defaultObjectPatcherKubeClientMetricLabels))
 	client.WithTimeout(app.ObjectPatcherKubeClientTimeout)
 	return client
 }
 
-func InitDefaultObjectPatcher(metricStorage *metric_storage.MetricStorage) (*object_patch.ObjectPatcher, error) {
-	patcherKubeClient := DefaultObjectPatcherKubeClient(metricStorage, DefaultObjectPatcherKubeClientMetricLabels)
+func initDefaultObjectPatcher(metricStorage *metric_storage.MetricStorage) (*object_patch.ObjectPatcher, error) {
+	patcherKubeClient := defaultObjectPatcherKubeClient(metricStorage, defaultObjectPatcherKubeClientMetricLabels)
 	err := patcherKubeClient.Init()
 	if err != nil {
 		return nil, fmt.Errorf("initialize Kubernetes client for Object patcher: %s\n", err)
diff --git a/pkg/shell-operator/manager_events_handler.go b/pkg/shell-operator/manager_events_handler.go
index 44ff9b2..63e53ab 100644
--- a/pkg/shell-operator/manager_events_handler.go
+++ b/pkg/shell-operator/manager_events_handler.go
@@ -12,6 +12,12 @@ import (
 	"github.com/flant/shell-operator/pkg/task/queue"
 )
 
+type managerEventsHandlerConfig struct {
+	tqs  *queue.TaskQueueSet
+	mgr  kube_events_manager.KubeEventsManager
+	smgr schedule_manager.ScheduleManager
+}
+
 type ManagerEventsHandler struct {
 	ctx    context.Context
 	cancel context.CancelFunc
@@ -25,40 +31,34 @@ type ManagerEventsHandler struct {
 	taskQueues *queue.TaskQueueSet
 }
 
-func NewManagerEventsHandler() *ManagerEventsHandler {
-	return &ManagerEventsHandler{}
-}
-
-func (m *ManagerEventsHandler) WithTaskQueueSet(tqs *queue.TaskQueueSet) {
-	m.taskQueues = tqs
-}
-
-func (m *ManagerEventsHandler) WithKubeEventsManager(mgr kube_events_manager.KubeEventsManager) {
-	m.kubeEventsManager = mgr
+func newManagerEventsHandler(ctx context.Context, cfg *managerEventsHandlerConfig) *ManagerEventsHandler {
+	if ctx == nil {
+		ctx = context.Background()
+	}
+	cctx, cancel := context.WithCancel(ctx)
+
+	return &ManagerEventsHandler{
+		ctx:               cctx,
+		cancel:            cancel,
+		scheduleManager:   cfg.smgr,
+		kubeEventsManager: cfg.mgr,
+		taskQueues:        cfg.tqs,
+	}
 }
 
+// WithKubeEventHandler sets custom function for event handling.
+// This function is used inside addon-operator.
 func (m *ManagerEventsHandler) WithKubeEventHandler(fn func(kubeEvent KubeEvent) []task.Task) {
 	m.kubeEventCb = fn
 }
 
-func (m *ManagerEventsHandler) WithScheduleManager(mgr schedule_manager.ScheduleManager) {
-	m.scheduleManager = mgr
-}
-
+// WithScheduleEventHandler sets custom scheduler function.
+// This function is used inside addon-operator.
 func (m *ManagerEventsHandler) WithScheduleEventHandler(fn func(crontab string) []task.Task) {
 	m.scheduleCb = fn
 }
 
-func (m *ManagerEventsHandler) WithContext(ctx context.Context) {
-	m.ctx, m.cancel = context.WithCancel(ctx)
-}
-
-func (m *ManagerEventsHandler) Stop() {
-	if m.cancel != nil {
-		m.cancel()
-	}
-}
-
+// Start runs events handler. This function is used in addon-operator
 func (m *ManagerEventsHandler) Start() {
 	go func() {
 		for {
diff --git a/pkg/shell-operator/metrics_hooks.go b/pkg/shell-operator/metrics_hooks.go
index 42a62db..08bb752 100644
--- a/pkg/shell-operator/metrics_hooks.go
+++ b/pkg/shell-operator/metrics_hooks.go
@@ -1,38 +1,17 @@
 package shell_operator
 
 import (
-	"context"
 	"net/http"
 
 	"github.com/flant/shell-operator/pkg/app"
 	"github.com/flant/shell-operator/pkg/metric_storage"
 )
 
-// DefaultHookMetricStorage creates MetricStorage object
-// with new registry to scrape hook metrics on separate port.
-func DefaultHookMetricStorage(ctx context.Context) *metric_storage.MetricStorage {
-	metricStorage := metric_storage.NewMetricStorage()
-	metricStorage.WithContext(ctx)
-	metricStorage.WithPrefix(app.PrometheusMetricsPrefix)
-	metricStorage.WithNewRegistry()
-	metricStorage.Start()
-	return metricStorage
-}
+func (op *ShellOperator) setupHookMetricStorage() {
+	metricStorage := metric_storage.NewMetricStorage(op.ctx, app.PrometheusMetricsPrefix, true)
 
-func SetupHookMetricStorageAndServer(ctx context.Context) (*metric_storage.MetricStorage, error) {
-	if app.HookMetricsListenPort == "" || app.HookMetricsListenPort == app.ListenPort {
-		// No separate metric storage required.
-		return nil, nil
-	}
+	op.APIServer.RegisterRoute(http.MethodGet, "/metrics/hooks", metricStorage.Handler().ServeHTTP)
 	// create new metric storage for hooks
-	metricStorage := DefaultHookMetricStorage(ctx)
-	// Create new ServeMux, and serve on custom port.
-	mux := http.NewServeMux()
-	err := StartHttpServer(app.ListenAddress, app.HookMetricsListenPort, mux)
-	if err != nil {
-		return nil, err
-	}
 	// register scrape handler
-	mux.Handle("/metrics", metricStorage.Handler())
-	return metricStorage, nil
+	op.MetricStorage = metricStorage
 }
diff --git a/pkg/shell-operator/metrics_operator.go b/pkg/shell-operator/metrics_operator.go
index d410bd2..7c32c0c 100644
--- a/pkg/shell-operator/metrics_operator.go
+++ b/pkg/shell-operator/metrics_operator.go
@@ -7,16 +7,13 @@ import (
 	"github.com/flant/shell-operator/pkg/metric_storage"
 )
 
-func DefaultMetricStorage(ctx context.Context) *metric_storage.MetricStorage {
-	metricStorage := metric_storage.NewMetricStorage()
-	metricStorage.WithContext(ctx)
-	metricStorage.WithPrefix(app.PrometheusMetricsPrefix)
-	metricStorage.Start()
+func defaultMetricStorage(ctx context.Context) *metric_storage.MetricStorage {
+	metricStorage := metric_storage.NewMetricStorage(ctx, app.PrometheusMetricsPrefix, false)
 	return metricStorage
 }
 
-// RegisterShellOperatorMetrics register all metrics needed for the ShellOperator.
-func RegisterShellOperatorMetrics(metricStorage *metric_storage.MetricStorage) {
+// registerShellOperatorMetrics register all metrics needed for the ShellOperator.
+func registerShellOperatorMetrics(metricStorage *metric_storage.MetricStorage) {
 	RegisterCommonMetrics(metricStorage)
 	RegisterTaskQueueMetrics(metricStorage)
 	RegisterKubeEventsManagerMetrics(metricStorage, map[string]string{
@@ -24,13 +21,17 @@ func RegisterShellOperatorMetrics(metricStorage *metric_storage.MetricStorage) {
 		"binding": "",
 		"queue":   "",
 	})
-	RegisterHookMetrics(metricStorage)
+	registerHookMetrics(metricStorage)
 }
 
+// RegisterCommonMetrics register base metric
+// This function is used in the addon-operator
 func RegisterCommonMetrics(metricStorage *metric_storage.MetricStorage) {
 	metricStorage.RegisterCounter("{PREFIX}live_ticks", map[string]string{})
 }
 
+// RegisterTaskQueueMetrics
+// This function is used in the addon-operator
 func RegisterTaskQueueMetrics(metricStorage *metric_storage.MetricStorage) {
 	metricStorage.RegisterHistogram(
 		"{PREFIX}tasks_queue_action_duration_seconds",
@@ -50,7 +51,8 @@ func RegisterTaskQueueMetrics(metricStorage *metric_storage.MetricStorage) {
 	metricStorage.RegisterGauge("{PREFIX}tasks_queue_length", map[string]string{"queue": ""})
 }
 
-// metrics for kube_event_manager
+// RegisterKubeEventsManagerMetrics registers metrics for kube_event_manager
+// This function is used in the addon-operator
 func RegisterKubeEventsManagerMetrics(metricStorage *metric_storage.MetricStorage, labels map[string]string) {
 	// Count of objects in snapshot for one kubernets bindings.
 	metricStorage.RegisterGauge("{PREFIX}kube_snapshot_objects", labels)
@@ -84,7 +86,7 @@ func RegisterKubeEventsManagerMetrics(metricStorage *metric_storage.MetricStorag
 }
 
 // Shell-operator specific metrics for HookManager
-func RegisterHookMetrics(metricStorage *metric_storage.MetricStorage) {
+func registerHookMetrics(metricStorage *metric_storage.MetricStorage) {
 	// Metrics for enable kubernetes bindings.
 	metricStorage.RegisterGauge("{PREFIX}hook_enable_kubernetes_bindings_seconds", map[string]string{"hook": ""})
 	metricStorage.RegisterCounter("{PREFIX}hook_enable_kubernetes_bindings_errors_total", map[string]string{"hook": ""})
diff --git a/pkg/shell-operator/operator.go b/pkg/shell-operator/operator.go
index 30a86f2..d86ddb3 100644
--- a/pkg/shell-operator/operator.go
+++ b/pkg/shell-operator/operator.go
@@ -5,8 +5,8 @@ import (
 	"fmt"
 	"time"
 
+	"github.com/gofrs/uuid/v5"
 	log "github.com/sirupsen/logrus"
-	uuid "gopkg.in/satori/go.uuid.v1"
 
 	klient "github.com/flant/kube-client/client"
 	"github.com/flant/shell-operator/pkg/hook"
@@ -34,10 +34,13 @@ type ShellOperator struct {
 	ctx    context.Context
 	cancel context.CancelFunc
 
+	// APIServer common http server for liveness and metrics endpoints
+	APIServer *baseHTTPServer
+
 	MetricStorage *metric_storage.MetricStorage
 	// separate metric storage for hook metrics if separate listen port is configured
 	HookMetricStorage *metric_storage.MetricStorage
-	KubeClient        klient.Client
+	KubeClient        *klient.Client
 	ObjectPatcher     *object_patch.ObjectPatcher
 
 	ScheduleManager   schedule_manager.ScheduleManager
@@ -53,13 +56,38 @@ type ShellOperator struct {
 	ConversionWebhookManager *conversion.WebhookManager
 }
 
-func NewShellOperator() *ShellOperator {
-	return &ShellOperator{}
+func NewShellOperator(ctx context.Context) *ShellOperator {
+	if ctx == nil {
+		ctx = context.Background()
+	}
+	cctx, cancel := context.WithCancel(ctx)
+	return &ShellOperator{
+		ctx:    cctx,
+		cancel: cancel,
+	}
 }
 
-func (op *ShellOperator) WithContext(ctx context.Context) *ShellOperator {
-	op.ctx, op.cancel = context.WithCancel(ctx)
-	return op
+// Start run the operator
+func (op *ShellOperator) Start() {
+	log.Info("start shell-operator")
+
+	op.APIServer.Start(op.ctx)
+
+	// Create 'main' queue and add onStartup tasks and enable bindings tasks.
+	op.bootstrapMainQueue(op.TaskQueues)
+	// Start main task queue handler
+	op.TaskQueues.StartMain()
+	op.initAndStartHookQueues()
+
+	// Start emit "live" metrics
+	op.runMetrics()
+
+	// Managers are generating events. This go-routine handles all events and converts them into queued tasks.
+	// Start it before start all informers to catch all kubernetes events (#42)
+	op.ManagerEventsHandler.Start()
+
+	// Unlike KubeEventsManager, ScheduleManager has one go-routine.
+	op.ScheduleManager.Start()
 }
 
 func (op *ShellOperator) Stop() {
@@ -68,16 +96,8 @@ func (op *ShellOperator) Stop() {
 	}
 }
 
-func (op *ShellOperator) WithKubernetesClient(klient klient.Client) {
-	op.KubeClient = klient
-}
-
-func (op *ShellOperator) WithMetricStorage(metricStorage *metric_storage.MetricStorage) {
-	op.MetricStorage = metricStorage
-}
-
-// InitHookManager load hooks from HooksDir and defines event handlers that emit tasks.
-func (op *ShellOperator) InitHookManager() (err error) {
+// initHookManager load hooks from HooksDir and defines event handlers that emit tasks.
+func (op *ShellOperator) initHookManager() (err error) {
 	if op.HookManager == nil {
 		return
 	}
@@ -91,7 +111,7 @@ func (op *ShellOperator) InitHookManager() (err error) {
 	// Define event handlers for schedule event and kubernetes event.
 	op.ManagerEventsHandler.WithKubeEventHandler(func(kubeEvent KubeEvent) []task.Task {
 		logLabels := map[string]string{
-			"event.id": uuid.NewV4().String(),
+			"event.id": uuid.Must(uuid.NewV4()).String(),
 			"binding":  string(OnKubernetesEvent),
 		}
 		logEntry := log.WithFields(utils.LabelsToLogFields(logLabels))
@@ -120,7 +140,7 @@ func (op *ShellOperator) InitHookManager() (err error) {
 	})
 	op.ManagerEventsHandler.WithScheduleEventHandler(func(crontab string) []task.Task {
 		logLabels := map[string]string{
-			"event.id": uuid.NewV4().String(),
+			"event.id": uuid.Must(uuid.NewV4()).String(),
 			"binding":  string(Schedule),
 		}
 		logEntry := log.WithFields(utils.LabelsToLogFields(logLabels))
@@ -151,9 +171,9 @@ func (op *ShellOperator) InitHookManager() (err error) {
 	return nil
 }
 
-// InitValidatingWebhookManager adds kubernetesValidating hooks
+// initValidatingWebhookManager adds kubernetesValidating hooks
 // to a WebhookManager and set a validating event handler.
-func (op *ShellOperator) InitValidatingWebhookManager() (err error) {
+func (op *ShellOperator) initValidatingWebhookManager() (err error) {
 	if op.HookManager == nil || op.AdmissionWebhookManager == nil {
 		return
 	}
@@ -185,7 +205,7 @@ func (op *ShellOperator) InitValidatingWebhookManager() (err error) {
 	op.AdmissionWebhookManager.WithAdmissionEventHandler(func(event AdmissionEvent) (*AdmissionResponse, error) {
 		eventBindingType := op.HookManager.DetectAdmissionEventType(event)
 		logLabels := map[string]string{
-			"event.id": uuid.NewV4().String(),
+			"event.id": uuid.Must(uuid.NewV4()).String(),
 			"event":    string(eventBindingType),
 		}
 		logEntry := log.WithFields(utils.LabelsToLogFields(logLabels))
@@ -216,7 +236,7 @@ func (op *ShellOperator) InitValidatingWebhookManager() (err error) {
 			logEntry.Errorf("Possible bug!!! %d hooks found for '%s' event '%s' '%s'", len(tasks), string(KubernetesValidating), event.ConfigurationId, event.WebhookId)
 		}
 
-		res := op.TaskHandler(tasks[0])
+		res := op.taskHandler(tasks[0])
 
 		if res.Status == "Fail" {
 			return &AdmissionResponse{
@@ -241,8 +261,8 @@ func (op *ShellOperator) InitValidatingWebhookManager() (err error) {
 	return err
 }
 
-// InitConversionWebhookManager creates and starts a conversion webhook manager.
-func (op *ShellOperator) InitConversionWebhookManager() (err error) {
+// initConversionWebhookManager creates and starts a conversion webhook manager.
+func (op *ShellOperator) initConversionWebhookManager() (err error) {
 	if op.HookManager == nil || op.ConversionWebhookManager == nil {
 		return
 	}
@@ -254,7 +274,7 @@ func (op *ShellOperator) InitConversionWebhookManager() (err error) {
 	}
 
 	// This handler is called when Kubernetes requests a conversion.
-	op.ConversionWebhookManager.EventHandlerFn = op.ConversionEventHandler
+	op.ConversionWebhookManager.EventHandlerFn = op.conversionEventHandler
 
 	err = op.ConversionWebhookManager.Init()
 	if err != nil {
@@ -274,10 +294,10 @@ func (op *ShellOperator) InitConversionWebhookManager() (err error) {
 	return err
 }
 
-// ConversionEventHandler is called when Kubernetes requests a conversion.
-func (op *ShellOperator) ConversionEventHandler(event conversion.Event) (*conversion.Response, error) {
+// conversionEventHandler is called when Kubernetes requests a conversion.
+func (op *ShellOperator) conversionEventHandler(event conversion.Event) (*conversion.Response, error) {
 	logLabels := map[string]string{
-		"event.id": uuid.NewV4().String(),
+		"event.id": uuid.Must(uuid.NewV4()).String(),
 		"binding":  string(KubernetesConversion),
 	}
 	logEntry := log.WithFields(utils.LabelsToLogFields(logLabels))
@@ -322,7 +342,7 @@ func (op *ShellOperator) ConversionEventHandler(event conversion.Event) (*conver
 				logEntry.Errorf("Possible bug!!! %d hooks found for '%s' event for crd/%s", len(tasks), string(KubernetesValidating), event.CrdName)
 			}
 
-			res := op.TaskHandler(tasks[0])
+			res := op.taskHandler(tasks[0])
 
 			if res.Status == "Fail" {
 				return &conversion.Response{
@@ -368,39 +388,18 @@ func (op *ShellOperator) ConversionEventHandler(event conversion.Event) (*conver
 	}, nil
 }
 
-// Start
-func (op *ShellOperator) Start() {
-	log.Info("start shell-operator")
-
-	// Create 'main' queue and add onStartup tasks and enable bindings tasks.
-	op.BootstrapMainQueue(op.TaskQueues)
-	// Start main task queue handler
-	op.TaskQueues.StartMain()
-	op.InitAndStartHookQueues()
-
-	// Start emit "live" metrics
-	op.RunMetrics()
-
-	// Managers are generating events. This go-routine handles all events and converts them into queued tasks.
-	// Start it before start all informers to catch all kubernetes events (#42)
-	op.ManagerEventsHandler.Start()
-
-	// Unlike KubeEventsManager, ScheduleManager has one go-routine.
-	op.ScheduleManager.Start()
-}
-
-// TaskHandler
-func (op *ShellOperator) TaskHandler(t task.Task) queue.TaskResult {
+// taskHandler
+func (op *ShellOperator) taskHandler(t task.Task) queue.TaskResult {
 	logEntry := log.WithField("operator.component", "taskRunner")
 	hookMeta := HookMetadataAccessor(t)
 	var res queue.TaskResult
 
 	switch t.GetType() {
 	case HookRun:
-		res = op.TaskHandleHookRun(t)
+		res = op.taskHandleHookRun(t)
 
 	case EnableKubernetesBindings:
-		res = op.TaskHandleEnableKubernetesBindings(t)
+		res = op.taskHandleEnableKubernetesBindings(t)
 
 	case EnableScheduleBindings:
 		hookLogLabels := map[string]string{}
@@ -420,8 +419,8 @@ func (op *ShellOperator) TaskHandler(t task.Task) queue.TaskResult {
 	return res
 }
 
-// TaskHandleEnableKubernetesBindings creates task for each Kubernetes binding in the hook and queues them.
-func (op *ShellOperator) TaskHandleEnableKubernetesBindings(t task.Task) queue.TaskResult {
+// taskHandleEnableKubernetesBindings creates task for each Kubernetes binding in the hook and queues them.
+func (op *ShellOperator) taskHandleEnableKubernetesBindings(t task.Task) queue.TaskResult {
 	hookMeta := HookMetadataAccessor(t)
 
 	metricLabels := map[string]string{
@@ -444,7 +443,7 @@ func (op *ShellOperator) TaskHandleEnableKubernetesBindings(t task.Task) queue.T
 
 	taskHook := op.HookManager.GetHook(hookMeta.HookName)
 
-	hookRunTasks := []task.Task{}
+	hookRunTasks := make([]task.Task, 0)
 
 	// Run hook for each binding with Synchronization binding context. Ignore queue name here, execute in main queue.
 	err := taskHook.HookController.HandleEnableKubernetesBindings(func(info controller.BindingExecutionInfo) {
@@ -489,7 +488,7 @@ func (op *ShellOperator) TaskHandleEnableKubernetesBindings(t task.Task) queue.T
 }
 
 // TODO use Context to pass labels and a queue name
-func (op *ShellOperator) TaskHandleHookRun(t task.Task) queue.TaskResult {
+func (op *ShellOperator) taskHandleHookRun(t task.Task) queue.TaskResult {
 	hookMeta := HookMetadataAccessor(t)
 	taskHook := op.HookManager.GetHook(hookMeta.HookName)
 
@@ -545,7 +544,7 @@ func (op *ShellOperator) TaskHandleHookRun(t task.Task) queue.TaskResult {
 			}
 		}
 		if shouldCombine {
-			combineResult := CombineBindingContextForHook(op.TaskQueues, op.TaskQueues.GetByName(t.GetQueueName()), t, nil)
+			combineResult := combineBindingContextForHook(op.TaskQueues, op.TaskQueues.GetByName(t.GetQueueName()), t, nil)
 			if combineResult != nil {
 				hookMeta.BindingContext = combineResult.BindingContexts
 				// Extra monitor IDs can be returned if several Synchronization for Group are combined.
@@ -567,7 +566,7 @@ func (op *ShellOperator) TaskHandleHookRun(t task.Task) queue.TaskResult {
 		success := 0.0
 		errors := 0.0
 		allowed := 0.0
-		err = op.HandleRunHook(t, taskHook, hookMeta, taskLogEntry, hookLogLabels, metricLabels)
+		err = op.handleRunHook(t, taskHook, hookMeta, taskLogEntry, hookLogLabels, metricLabels)
 		if err != nil {
 			if hookMeta.AllowFailure {
 				allowed = 1.0
@@ -601,13 +600,24 @@ func (op *ShellOperator) TaskHandleHookRun(t task.Task) queue.TaskResult {
 	return res
 }
 
-func (op *ShellOperator) HandleRunHook(t task.Task, taskHook *hook.Hook, hookMeta HookMetadata, taskLogEntry *log.Entry, hookLogLabels map[string]string, metricLabels map[string]string) error {
+func (op *ShellOperator) handleRunHook(t task.Task, taskHook *hook.Hook, hookMeta HookMetadata, taskLogEntry *log.Entry, hookLogLabels map[string]string, metricLabels map[string]string) error {
 	for _, info := range taskHook.HookController.SnapshotsInfo() {
 		taskLogEntry.Debugf("snapshot info: %s", info)
 	}
 
 	result, err := taskHook.Run(hookMeta.BindingType, hookMeta.BindingContext, hookLogLabels)
 	if err != nil {
+		if result != nil && len(result.KubernetesPatchBytes) > 0 {
+			operations, patchStatusErr := object_patch.ParseOperations(result.KubernetesPatchBytes)
+			if patchStatusErr != nil {
+				return fmt.Errorf("%s: couldn't patch status: %s", err, patchStatusErr)
+			}
+
+			patchStatusErr = op.ObjectPatcher.ExecuteOperations(object_patch.GetPatchStatusOperationsOnHookError(operations))
+			if patchStatusErr != nil {
+				return fmt.Errorf("%s: couldn't patch status: %s", err, patchStatusErr)
+			}
+		}
 		return err
 	}
 
@@ -653,7 +663,7 @@ func (op *ShellOperator) HandleRunHook(t task.Task, taskHook *hook.Hook, hookMet
 	return nil
 }
 
-// CombineBindingContextForHook combines binding contexts from a sequence of task with similar
+// combineBindingContextForHook combines binding contexts from a sequence of task with similar
 // hook name and task type into array of binding context and delete excess tasks from queue.
 //
 // Also, sequences of binding contexts with similar group are compacted in one binding context.
@@ -764,14 +774,14 @@ func (op *ShellOperator) CombineBindingContextForHook(q *queue.TaskQueue, t task
 	return res
 }
 
-// BootstrapMainQueue adds tasks to run hooks with OnStartup bindings
+// bootstrapMainQueue adds tasks to run hooks with OnStartup bindings
 // and tasks to enable kubernetes bindings.
-func (op *ShellOperator) BootstrapMainQueue(tqs *queue.TaskQueueSet) {
+func (op *ShellOperator) bootstrapMainQueue(tqs *queue.TaskQueueSet) {
 	logEntry := log.WithField("operator.component", "initMainQueue")
 
 	// Prepopulate main queue with 'onStartup' tasks and 'enable kubernetes bindings' tasks.
 	tqs.WithMainName("main")
-	tqs.NewNamedQueue("main", op.TaskHandler)
+	tqs.NewNamedQueue("main", op.taskHandler)
 
 	mainQueue := tqs.GetMain()
 
@@ -827,14 +837,14 @@ func (op *ShellOperator) BootstrapMainQueue(tqs *queue.TaskQueueSet) {
 	}
 }
 
-// InitAndStartHookQueues create all queues defined in hooks
-func (op *ShellOperator) InitAndStartHookQueues() {
+// initAndStartHookQueues create all queues defined in hooks
+func (op *ShellOperator) initAndStartHookQueues() {
 	schHooks, _ := op.HookManager.GetHooksInOrder(Schedule)
 	for _, hookName := range schHooks {
 		h := op.HookManager.GetHook(hookName)
 		for _, hookBinding := range h.Config.Schedules {
 			if op.TaskQueues.GetByName(hookBinding.Queue) == nil {
-				op.TaskQueues.NewNamedQueue(hookBinding.Queue, op.TaskHandler)
+				op.TaskQueues.NewNamedQueue(hookBinding.Queue, op.taskHandler)
 				op.TaskQueues.GetByName(hookBinding.Queue).Start()
 			}
 		}
@@ -845,14 +855,14 @@ func (op *ShellOperator) InitAndStartHookQueues() {
 		h := op.HookManager.GetHook(hookName)
 		for _, hookBinding := range h.Config.OnKubernetesEvents {
 			if op.TaskQueues.GetByName(hookBinding.Queue) == nil {
-				op.TaskQueues.NewNamedQueue(hookBinding.Queue, op.TaskHandler)
+				op.TaskQueues.NewNamedQueue(hookBinding.Queue, op.taskHandler)
 				op.TaskQueues.GetByName(hookBinding.Queue).Start()
 			}
 		}
 	}
 }
 
-func (op *ShellOperator) RunMetrics() {
+func (op *ShellOperator) runMetrics() {
 	if op.MetricStorage == nil {
 		return
 	}
diff --git a/pkg/task/dump/dump.go b/pkg/task/dump/dump.go
index a3477ca..b5f9dd3 100644
--- a/pkg/task/dump/dump.go
+++ b/pkg/task/dump/dump.go
@@ -29,18 +29,39 @@ func (a asQueueNames) Less(i, j int) bool {
 	return p.Name < q.Name
 }
 
-// TaskQueueMainToText dumps only the 'main' queue.
-func TaskQueueMainToText(tqs *queue.TaskQueueSet) string {
-	var buf strings.Builder
+// TaskMainQueue dumps 'main' queue with the given
+func TaskMainQueue(tqs *queue.TaskQueueSet, format string) interface{} {
+	var dq dumpQueue
 
 	q := tqs.GetMain()
 	if q == nil {
-		buf.WriteString(fmt.Sprintf("Queue '%s' is not created\n", queue.MainQueueName))
+		dq.Name = queue.MainQueueName
+		dq.Status = "Queue is not created"
 	} else {
-		buf.WriteString(TaskQueueToText(q))
+		tasks := getTasksForQueue(q)
+		dq = dumpQueue{
+			Name:       q.Name,
+			TasksCount: q.Length(),
+			Status:     q.Status,
+			Tasks:      tasks,
+		}
 	}
 
-	return buf.String()
+	if format == "text" {
+		var buf strings.Builder
+		buf.WriteString(fmt.Sprintf("Queue '%s': length %d, status: '%s'\n", dq.Name, dq.TasksCount, dq.Status))
+		buf.WriteString("\n")
+
+		for _, ts := range dq.Tasks {
+			buf.WriteString(fmt.Sprintf("%2d. ", ts.Index))
+			buf.WriteString(ts.Description)
+			buf.WriteString("\n")
+		}
+
+		return buf.String()
+	}
+
+	return dq
 }
 
 // TaskQueues dumps all queues.
@@ -135,23 +156,6 @@ func pluralize(n int, zero, one, many string) string {
 	return fmt.Sprintf("%d %s", n, description)
 }
 
-// TaskQueueToText dumps all tasks in queue.
-func TaskQueueToText(q *queue.TaskQueue) string {
-	var buf strings.Builder
-	buf.WriteString(fmt.Sprintf("Queue '%s': length %d, status: '%s'\n", q.Name, q.Length(), q.Status))
-	buf.WriteString("\n")
-
-	index := 1
-	q.Iterate(func(task task.Task) {
-		buf.WriteString(fmt.Sprintf("%2d. ", index))
-		buf.WriteString(task.GetDescription())
-		buf.WriteString("\n")
-		index++
-	})
-
-	return buf.String()
-}
-
 func getTasksForQueue(q *queue.TaskQueue) []dumpTask {
 	tasks := make([]dumpTask, 0, q.Length())
 
@@ -176,15 +180,15 @@ type dumpTaskQueues struct {
 }
 
 type dumpQueue struct {
-	Name       string     `json:"name"`
-	TasksCount int        `json:"tasksCount"`
-	Status     string     `json:"status,omitempty"`
-	Tasks      []dumpTask `json:"tasks,omitempty"`
+	Name       string     `json:"name" yaml:"name"`
+	TasksCount int        `json:"tasksCount" yaml:"tasksCount"`
+	Status     string     `json:"status,omitempty" yaml:"status,omitempty"`
+	Tasks      []dumpTask `json:"tasks,omitempty" yaml:"tasks,omitempty"`
 }
 
 type dumpTask struct {
-	Index       int    `json:"index"`
-	Description string `json:"description"`
+	Index       int    `json:"index" yaml:"index"`
+	Description string `json:"description" yaml:"description"`
 }
 
 type dumpSummary struct {
diff --git a/pkg/task/task.go b/pkg/task/task.go
index b13ec96..7dd38ef 100644
--- a/pkg/task/task.go
+++ b/pkg/task/task.go
@@ -4,7 +4,7 @@ import (
 	"fmt"
 	"time"
 
-	uuid "gopkg.in/satori/go.uuid.v1"
+	uuid "github.com/gofrs/uuid/v5"
 
 	utils "github.com/flant/shell-operator/pkg/utils/labels"
 )
@@ -46,7 +46,7 @@ type BaseTask struct {
 }
 
 func NewTask(taskType TaskType) *BaseTask {
-	taskId := uuid.NewV4().String()
+	taskId := uuid.Must(uuid.NewV4()).String()
 	return &BaseTask{
 		Id:           taskId,
 		FailureCount: 0,
diff --git a/pkg/utils/file/dir.go b/pkg/utils/file/dir.go
new file mode 100644
index 0000000..19ee95f
--- /dev/null
+++ b/pkg/utils/file/dir.go
@@ -0,0 +1,59 @@
+package utils
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+
+	"github.com/flant/shell-operator/pkg/app"
+)
+
+func RequireExistingDirectory(inDir string) (dir string, err error) {
+	if inDir == "" {
+		return "", fmt.Errorf("path is required but not set")
+	}
+
+	dir, err = filepath.Abs(inDir)
+	if err != nil {
+		return "", fmt.Errorf("get absolute path: %v", err)
+	}
+	if exists, _ := DirExists(dir); !exists {
+		return "", fmt.Errorf("path '%s' not exist", dir)
+	}
+
+	return dir, nil
+}
+
+func EnsureTempDirectory(inDir string) (string, error) {
+	// No path to temporary dir, use default temporary dir.
+	if inDir == "" {
+		tmpPath := app.AppName + "-*"
+		dir, err := os.MkdirTemp("", tmpPath)
+		if err != nil {
+			return "", fmt.Errorf("create tmp dir in '%s': %s", tmpPath, err)
+		}
+		return dir, nil
+	}
+
+	// Get absolute path for temporary directory and create if needed.
+	dir, err := filepath.Abs(inDir)
+	if err != nil {
+		return "", fmt.Errorf("get absolute path: %v", err)
+	}
+	if exists, _ := DirExists(dir); !exists {
+		err := os.Mkdir(dir, os.FileMode(0o777))
+		if err != nil {
+			return "", fmt.Errorf("create tmp dir '%s': %s", dir, err)
+		}
+	}
+	return dir, nil
+}
+
+func DirExists(path string) (bool, error) {
+	fileInfo, err := os.Stat(path)
+	if err != nil && os.IsNotExist(err) {
+		return false, nil
+	}
+
+	return fileInfo.IsDir(), nil
+}
diff --git a/pkg/utils/file/file.go b/pkg/utils/file/file.go
index d33307d..92e063b 100644
--- a/pkg/utils/file/file.go
+++ b/pkg/utils/file/file.go
@@ -20,15 +20,6 @@ func FileExists(path string) (bool, error) {
 	return true, nil
 }
 
-func DirExists(path string) (bool, error) {
-	fileInfo, err := os.Stat(path)
-	if err != nil && os.IsNotExist(err) {
-		return false, nil
-	}
-
-	return fileInfo.IsDir(), nil
-}
-
 func IsFileExecutable(f os.FileInfo) bool {
 	return f.Mode()&0o111 != 0
 }
diff --git a/pkg/utils/labels/labels.go b/pkg/utils/labels/labels.go
index 1eff1ab..c8eb4ed 100644
--- a/pkg/utils/labels/labels.go
+++ b/pkg/utils/labels/labels.go
@@ -46,3 +46,10 @@ func LabelValues(labels map[string]string, labelNames []string) []string {
 	}
 	return values
 }
+
+func DefaultIfEmpty(m map[string]string, def map[string]string) map[string]string {
+	if len(m) == 0 {
+		return def
+	}
+	return m
+}
diff --git a/pkg/webhook/admission/manager.go b/pkg/webhook/admission/manager.go
index b2395e7..c593da1 100644
--- a/pkg/webhook/admission/manager.go
+++ b/pkg/webhook/admission/manager.go
@@ -20,7 +20,7 @@ const DefaultConfigurationId = "hooks"
 //   - Call AddWebhook for every binding in hooks
 //   - Start() to run server and create ValidatingWebhookConfiguration/MutatingWebhookConfiguration
 type WebhookManager struct {
-	KubeClient klient.Client
+	KubeClient *klient.Client
 
 	Settings  *WebhookSettings
 	Namespace string
@@ -33,17 +33,14 @@ type WebhookManager struct {
 	Handler             *WebhookHandler
 }
 
-func NewWebhookManager() *WebhookManager {
+func NewWebhookManager(kubeClient *klient.Client) *WebhookManager {
 	return &WebhookManager{
 		ValidatingResources: make(map[string]*ValidatingWebhookResource),
 		MutatingResources:   make(map[string]*MutatingWebhookResource),
+		KubeClient:          kubeClient,
 	}
 }
 
-func (m *WebhookManager) WithKubeClient(kubeClient klient.Client) {
-	m.KubeClient = kubeClient
-}
-
 func (m *WebhookManager) WithAdmissionEventHandler(handler AdmissionEventHandlerFn) {
 	if m.Handler == nil {
 		m.Handler = &WebhookHandler{
diff --git a/pkg/webhook/admission/resource.go b/pkg/webhook/admission/resource.go
index ae41b23..5932d6e 100644
--- a/pkg/webhook/admission/resource.go
+++ b/pkg/webhook/admission/resource.go
@@ -12,7 +12,7 @@ import (
 )
 
 type WebhookResourceOptions struct {
-	KubeClient        klient.Client
+	KubeClient        *klient.Client
 	Namespace         string
 	ConfigurationName string
 	ServiceName       string
diff --git a/pkg/webhook/conversion/crd_client_config.go b/pkg/webhook/conversion/crd_client_config.go
index 48e8338..aaa0dd9 100644
--- a/pkg/webhook/conversion/crd_client_config.go
+++ b/pkg/webhook/conversion/crd_client_config.go
@@ -13,7 +13,7 @@ import (
 
 // A clientConfig for a particular CRD.
 type CrdClientConfig struct {
-	KubeClient  klient.Client
+	KubeClient  *klient.Client
 	CrdName     string
 	Namespace   string
 	ServiceName string
diff --git a/pkg/webhook/conversion/manager.go b/pkg/webhook/conversion/manager.go
index d11fe5e..2bcc6f4 100644
--- a/pkg/webhook/conversion/manager.go
+++ b/pkg/webhook/conversion/manager.go
@@ -24,7 +24,7 @@ type EventHandlerFn func(event Event) (*Response, error)
 //   - Start server loop.
 //   - Update clientConfig in each registered CRD.
 type WebhookManager struct {
-	KubeClient klient.Client
+	KubeClient *klient.Client
 
 	EventHandlerFn EventHandlerFn
 	Settings       *WebhookSettings
diff --git a/pkg/webhook/validating/validation/rule.go b/pkg/webhook/validating/validation/rule.go
index b38c50d..e4de526 100644
--- a/pkg/webhook/validating/validation/rule.go
+++ b/pkg/webhook/validating/validation/rule.go
@@ -32,9 +32,9 @@ func validateResources(resources []string, fldPath *field.Path) field.ErrorList
 	}
 
 	// */x
-	resourcesWithWildcardSubresoures := sets.String{}
+	resourcesWithWildcardSubresoures := sets.Set[string]{}
 	// x/*
-	subResourcesWithWildcardResource := sets.String{}
+	subResourcesWithWildcardResource := sets.Set[string]{}
 	// */*
 	hasDoubleWildcard := false
 	// *
diff --git a/pkg/webhook/validating/validation/validation.go b/pkg/webhook/validating/validation/validation.go
index 355a15b..9975477 100644
--- a/pkg/webhook/validating/validation/validation.go
+++ b/pkg/webhook/validating/validation/validation.go
@@ -66,22 +66,13 @@ func ValidateValidatingWebhook(hook *v1.ValidatingWebhook, fldPath *field.Path)
 	}
 
 	if hook.NamespaceSelector != nil {
-		allErrors = AppendFieldList(allErrors, metav1validation.ValidateLabelSelector(hook.NamespaceSelector, fldPath.Child("namespaceSelector")))
+		allErrors = AppendFieldList(allErrors, metav1validation.ValidateLabelSelector(hook.NamespaceSelector, metav1validation.LabelSelectorValidationOptions{}, fldPath.Child("namespaceSelector")))
 	}
 
 	if hook.ObjectSelector != nil {
-		allErrors = AppendFieldList(allErrors, metav1validation.ValidateLabelSelector(hook.ObjectSelector, fldPath.Child("objectSelector")))
+		allErrors = AppendFieldList(allErrors, metav1validation.ValidateLabelSelector(hook.ObjectSelector, metav1validation.LabelSelectorValidationOptions{}, fldPath.Child("objectSelector")))
 	}
 
-	// cc := hook.ClientConfig
-	// switch {
-	// case (cc.URL == nil) == (cc.Service == nil):
-	//	allErrors = multierror.Append(allErrors, field.Required(fldPath.Child("clientConfig"), "exactly one of url or service is required"))
-	// case cc.URL != nil:
-	//	allErrors = multierror.Append(allErrors, webhook.ValidateWebhookURL(fldPath.Child("clientConfig").Child("url"), *cc.URL, true)...)
-	// case cc.Service != nil:
-	//	allErrors = multierror.Append(allErrors, webhook.ValidateWebhookService(fldPath.Child("clientConfig").Child("service"), cc.Service.Name, cc.Service.Namespace, cc.Service.Path, cc.Service.Port)...)
-	//}
 	return allErrors
 }
 


Test patch:
diff --git a/.github/workflows/tests-labeled.yaml b/.github/workflows/tests-labeled.yaml
index f34b146..01e5b84 100644
--- a/.github/workflows/tests-labeled.yaml
+++ b/.github/workflows/tests-labeled.yaml
@@ -46,21 +46,21 @@ jobs:
       fail-fast: true
       matrix:
         include:
-        - k8s_version: "1.19"
-          kind_node_image: "kindest/node:v1.19.16"
-          cluster_name: "kube-1-19"
-        - k8s_version: "1.20"
-          kind_node_image: "kindest/node:v1.20.15"
-          cluster_name: "kube-1-20"
         - k8s_version: "1.23"
-          kind_node_image: "kindest/node:v1.23.13"
+          kind_node_image: "kindest/node:v1.23.17"
           cluster_name: "kube-1-23"
         - k8s_version: "1.24"
-          kind_node_image: "kindest/node:v1.24.7"
+          kind_node_image: "kindest/node:v1.24.15"
           cluster_name: "kube-1-24"
         - k8s_version: "1.25"
-          kind_node_image: "kindest/node:v1.25.2"
+          kind_node_image: "kindest/node:v1.25.11"
           cluster_name: "kube-1-25"
+        - k8s_version: "1.26"
+          kind_node_image: "kindest/node:v1.26.6"
+          cluster_name: "kube-1-26"
+        - k8s_version: "1.27"
+          kind_node_image: "kindest/node:v1.27.3"
+          cluster_name: "kube-1-27"
     runs-on: ubuntu-latest
     steps:
       - name: Set up Go 1.20
@@ -101,7 +101,7 @@ jobs:
       - name: Start kind cluster
         uses: engineerd/setup-kind@v0.5.0
         with:
-          version: "v0.17.0"
+          version: "v0.20.0"
           image: ${{ matrix.kind_node_image }}
           name: ${{ matrix.cluster_name }}
 
diff --git a/pkg/hook/controller/hook_controller_test.go b/pkg/hook/controller/hook_controller_test.go
index d6baee6..782aa29 100644
--- a/pkg/hook/controller/hook_controller_test.go
+++ b/pkg/hook/controller/hook_controller_test.go
@@ -19,9 +19,7 @@ func Test_UpdateSnapshots(t *testing.T) {
 	g := NewWithT(t)
 
 	fc := fake.NewFakeCluster(fake.ClusterVersionV121)
-	mgr := kube_events_manager.NewKubeEventsManager()
-	mgr.WithContext(context.Background())
-	mgr.WithKubeClient(fc.Client)
+	mgr := kube_events_manager.NewKubeEventsManager(context.Background(), fc.Client)
 
 	testHookConfig := `
 configVersion: v1
diff --git a/pkg/hook/hook_manager_test.go b/pkg/hook/hook_manager_test.go
index ed2e8a7..0067eed 100644
--- a/pkg/hook/hook_manager_test.go
+++ b/pkg/hook/hook_manager_test.go
@@ -16,18 +16,23 @@ import (
 )
 
 func newHookManager(t *testing.T, testdataDir string) *hookManager {
-	hm := NewHookManager()
-
 	hooksDir, _ := filepath.Abs(testdataDir)
-	hm.WithDirectories(hooksDir, t.TempDir())
 
 	conversionManager := conversion.NewWebhookManager()
 	conversionManager.Settings = app.ConversionWebhookSettings
-	hm.WithConversionWebhookManager(conversionManager)
 
-	admissionManager := admission.NewWebhookManager()
+	admissionManager := admission.NewWebhookManager(nil)
 	admissionManager.Settings = app.ValidatingWebhookSettings
-	hm.WithAdmissionWebhookManager(admissionManager)
+
+	cfg := &HookManagerConfig{
+		WorkingDir: hooksDir,
+		TempDir:    t.TempDir(),
+		Kmgr:       nil,
+		Smgr:       nil,
+		Wmgr:       admissionManager,
+		Cmgr:       conversionManager,
+	}
+	hm := NewHookManager(cfg)
 
 	return hm
 }
diff --git a/pkg/hook/task_metadata/task_metadata_test.go b/pkg/hook/task_metadata/task_metadata_test.go
index 620be30..ce3dd0e 100644
--- a/pkg/hook/task_metadata/task_metadata_test.go
+++ b/pkg/hook/task_metadata/task_metadata_test.go
@@ -1,6 +1,8 @@
 package task_metadata
 
 import (
+	"fmt"
+	"strings"
 	"testing"
 
 	. "github.com/onsi/gomega"
@@ -8,7 +10,6 @@ import (
 	. "github.com/flant/shell-operator/pkg/hook/binding_context"
 	. "github.com/flant/shell-operator/pkg/hook/types"
 	"github.com/flant/shell-operator/pkg/task"
-	"github.com/flant/shell-operator/pkg/task/dump"
 	"github.com/flant/shell-operator/pkg/task/queue"
 )
 
@@ -70,7 +71,7 @@ func Test_HookMetadata_QueueDump_Task_Description(t *testing.T) {
 		WithLogLabels(logLabels).
 		WithQueueName("main"))
 
-	queueDump := dump.TaskQueueToText(q)
+	queueDump := taskQueueToText(q)
 
 	g.Expect(queueDump).Should(ContainSubstring("hook1.sh"), "Queue dump should reveal a hook name.")
 	g.Expect(queueDump).Should(ContainSubstring("EnableKubernetesBindings"), "Queue dump should reveal EnableKubernetesBindings.")
@@ -78,3 +79,19 @@ func Test_HookMetadata_QueueDump_Task_Description(t *testing.T) {
 	g.Expect(queueDump).Should(ContainSubstring(":schedule:"), "Queue dump should show schedule binding.")
 	g.Expect(queueDump).Should(ContainSubstring("group=monitor_pods"), "Queue dump should show group name.")
 }
+
+func taskQueueToText(q *queue.TaskQueue) string {
+	var buf strings.Builder
+	buf.WriteString(fmt.Sprintf("Queue '%s': length %d, status: '%s'\n", q.Name, q.Length(), q.Status))
+	buf.WriteString("\n")
+
+	index := 1
+	q.Iterate(func(task task.Task) {
+		buf.WriteString(fmt.Sprintf("%2d. ", index))
+		buf.WriteString(task.GetDescription())
+		buf.WriteString("\n")
+		index++
+	})
+
+	return buf.String()
+}
diff --git a/pkg/kube_events_manager/filter_test.go b/pkg/kube_events_manager/filter_test.go
index 635a0fb..a641e4f 100644
--- a/pkg/kube_events_manager/filter_test.go
+++ b/pkg/kube_events_manager/filter_test.go
@@ -11,7 +11,7 @@ import (
 func TestApplyFilter(t *testing.T) {
 	t.Run("filter func with error", func(t *testing.T) {
 		uns := &unstructured.Unstructured{Object: map[string]interface{}{"foo": "bar"}}
-		_, err := ApplyFilter("", filterFuncWithError, uns)
+		_, err := applyFilter("", filterFuncWithError, uns)
 		assert.EqualError(t, err, "filterFn (github.com/flant/shell-operator/pkg/kube_events_manager.filterFuncWithError) contains an error: invalid character 'a' looking for beginning of value")
 	})
 }
diff --git a/pkg/kube_events_manager/kube_events_manager_test.go b/pkg/kube_events_manager/kube_events_manager_test.go
index 6c392cc..6e4efd8 100644
--- a/pkg/kube_events_manager/kube_events_manager_test.go
+++ b/pkg/kube_events_manager/kube_events_manager_test.go
@@ -49,9 +49,7 @@ func Test_MainKubeEventsManager_Run(t *testing.T) {
 		},
 	}
 
-	mgr := NewKubeEventsManager()
-	mgr.WithContext(context.Background())
-	mgr.WithKubeClient(kubeClient)
+	mgr := NewKubeEventsManager(context.Background(), kubeClient)
 
 	// monitor with 3 namespaces and 4 object names
 	monitor := &MonitorConfig{
@@ -139,9 +137,7 @@ func Test_MainKubeEventsManager_HandleEvents(t *testing.T) {
 	_, _ = dynClient.Resource(podGvr).Namespace("default").Create(context.TODO(), obj, metav1.CreateOptions{}, []string{}...)
 
 	// Init() replacement
-	mgr := NewKubeEventsManager()
-	mgr.WithKubeClient(kubeClient)
-	mgr.WithContext(ctx)
+	mgr := NewKubeEventsManager(ctx, kubeClient)
 	mgr.KubeEventCh = make(chan KubeEvent, 10)
 
 	// monitor with 3 namespaces and 4 object names and all event types
@@ -317,8 +313,7 @@ func Test_FakeClient_CatchUpdates(t *testing.T) {
 	_, _ = dynClient.Resource(podGvr).Namespace("default").Create(context.TODO(), obj, metav1.CreateOptions{}, []string{}...)
 
 	//// Init() replacement
-	mgr := NewKubeEventsManager()
-	mgr.WithContext(ctx)
+	mgr := NewKubeEventsManager(ctx, nil)
 
 	// monitor with 3 namespaces and 4 object names and all event types
 	monitor := &MonitorConfig{
diff --git a/pkg/kube_events_manager/monitor_test.go b/pkg/kube_events_manager/monitor_test.go
index d8bccc9..1059256 100644
--- a/pkg/kube_events_manager/monitor_test.go
+++ b/pkg/kube_events_manager/monitor_test.go
@@ -34,15 +34,9 @@ func Test_Monitor_should_handle_dynamic_ns_events(t *testing.T) {
 			},
 		},
 	}
-
-	mon := NewMonitor()
-	mon.WithContext(context.TODO())
-	mon.WithKubeClient(fc.Client)
-	mon.WithConfig(monitorCfg)
-
-	// Catch resource IDs from monitor events.
 	objsFromEvents := make([]string, 0)
-	mon.WithKubeEventCb(func(ev KubeEvent) {
+
+	mon := NewMonitor(context.Background(), fc.Client, nil, monitorCfg, func(ev KubeEvent) {
 		objsFromEvents = append(objsFromEvents, snapshotResourceIDs(ev.Objects)...)
 	})
 
@@ -60,7 +54,7 @@ func Test_Monitor_should_handle_dynamic_ns_events(t *testing.T) {
 	createNsWithLabels(fc, "test-ns-1", map[string]string{"test-label": ""})
 
 	// Wait until informers appears.
-	g.Eventually(mon.(*monitor).VaryingInformers, "5s", "10ms").
+	g.Eventually(mon.VaryingInformers, "5s", "10ms").
 		Should(HaveKey("test-ns-1"), "Should create informer for new namespace")
 
 	createCM(fc, "test-ns-1", testCM("cm-1"))
@@ -84,7 +78,7 @@ func Test_Monitor_should_handle_dynamic_ns_events(t *testing.T) {
 		Should(SatisfyAll(
 			ContainElement("test-ns-1/ConfigMap/cm-2"),
 			ContainElement("test-ns-1/ConfigMap/cm-3"),
-		), "Should fire cached KubeEvents after EnableKubeEventCb")
+		), "Should fire cached KubeEvents after enableKubeEventCb")
 
 	g.Expect(snapshotResourceIDs(mon.Snapshot())).
 		Should(SatisfyAll(
@@ -98,7 +92,7 @@ func Test_Monitor_should_handle_dynamic_ns_events(t *testing.T) {
 	createNsWithLabels(fc, "test-ns-2", map[string]string{"test-label": ""})
 
 	// Monitor should create new configmap informer for new namespace.
-	g.Eventually(mon.(*monitor).VaryingInformers, "5s", "10ms").
+	g.Eventually(mon.VaryingInformers, "5s", "10ms").
 		Should(HaveKey("test-ns-2"), "Should create informer for ns/test-ns-2")
 
 	// Create new ConfigMap after Synchronization.
@@ -117,7 +111,7 @@ func Test_Monitor_should_handle_dynamic_ns_events(t *testing.T) {
 	createNsWithLabels(fc, "test-ns-non-matched", map[string]string{"non-matched-label": ""})
 
 	// Monitor should create new configmap informer for new namespace.
-	g.Eventually(mon.(*monitor).VaryingInformers, "5s", "10ms").
+	g.Eventually(mon.VaryingInformers, "5s", "10ms").
 		ShouldNot(HaveKey("test-ns-non-matched"), "Should not create informer for non-mathed Namespace")
 }
 
diff --git a/pkg/kube_events_manager/util_test.go b/pkg/kube_events_manager/util_test.go
index a416de1..0356126 100644
--- a/pkg/kube_events_manager/util_test.go
+++ b/pkg/kube_events_manager/util_test.go
@@ -8,7 +8,7 @@ import (
 func Test_RandomizedResyncPeriod(t *testing.T) {
 	t.SkipNow()
 	for i := 0; i < 10; i++ {
-		p := RandomizedResyncPeriod()
+		p := randomizedResyncPeriod()
 		fmt.Printf("%02d. %s\n", i, p.String())
 	}
 }
diff --git a/pkg/schedule_manager/schedule_manager_test.go b/pkg/schedule_manager/schedule_manager_test.go
index 66692e9..bb5de61 100644
--- a/pkg/schedule_manager/schedule_manager_test.go
+++ b/pkg/schedule_manager/schedule_manager_test.go
@@ -1,13 +1,14 @@
 package schedule_manager
 
 import (
+	"context"
 	"testing"
 
 	"github.com/flant/shell-operator/pkg/schedule_manager/types"
 )
 
 func Test_ScheduleManager_Add(t *testing.T) {
-	sm := NewScheduleManager()
+	sm := NewScheduleManager(context.Background())
 
 	expectations := []struct {
 		testName string
diff --git a/pkg/shell-operator/combine_binding_context_test.go b/pkg/shell-operator/combine_binding_context_test.go
index 9afdbf4..b87d69b 100644
--- a/pkg/shell-operator/combine_binding_context_test.go
+++ b/pkg/shell-operator/combine_binding_context_test.go
@@ -98,7 +98,7 @@ func Test_CombineBindingContext_MultipleHooks(t *testing.T) {
 	}
 	g.Expect(TaskQueues.GetByName("test_multiple_hooks").Length()).Should(Equal(len(tasks)))
 
-	combineResult := CombineBindingContextForHook(TaskQueues, TaskQueues.GetByName("test_multiple_hooks"), tasks[0], nil)
+	combineResult := combineBindingContextForHook(TaskQueues, TaskQueues.GetByName("test_multiple_hooks"), tasks[0], nil)
 
 	// Should combine binding contexts from 4 tasks.
 	g.Expect(combineResult).ShouldNot(BeNil())
@@ -158,7 +158,7 @@ func Test_CombineBindingContext_Nil_On_NoCombine(t *testing.T) {
 	}
 	g.Expect(TaskQueues.GetByName("test_no_combine").Length()).Should(Equal(len(tasks)))
 
-	combineResult := CombineBindingContextForHook(TaskQueues, TaskQueues.GetByName("test_no_combine"), tasks[0], nil)
+	combineResult := combineBindingContextForHook(TaskQueues, TaskQueues.GetByName("test_no_combine"), tasks[0], nil)
 	// Should return nil if no combine
 	g.Expect(combineResult).Should(BeNil())
 	// Should not delete tasks
@@ -257,7 +257,7 @@ func Test_CombineBindingContext_Group_Compaction(t *testing.T) {
 	}
 	g.Expect(TaskQueues.GetByName("test_multiple_hooks").Length()).Should(Equal(len(tasks)))
 
-	combineResult := CombineBindingContextForHook(TaskQueues, TaskQueues.GetByName("test_multiple_hooks"), tasks[0], nil)
+	combineResult := combineBindingContextForHook(TaskQueues, TaskQueues.GetByName("test_multiple_hooks"), tasks[0], nil)
 	// Should compact 4 tasks into 4 binding context and combine 3 binding contexts into one.
 	g.Expect(combineResult).ShouldNot(BeNil())
 	g.Expect(combineResult.BindingContexts).Should(HaveLen(2))
@@ -406,7 +406,7 @@ func Test_CombineBindingContext_Group_Type(t *testing.T) {
 	}
 	g.Expect(TaskQueues.GetByName("test_multiple_hooks").Length()).Should(Equal(len(tasks)))
 
-	combineResult := CombineBindingContextForHook(TaskQueues, TaskQueues.GetByName("test_multiple_hooks"), tasks[0], nil)
+	combineResult := combineBindingContextForHook(TaskQueues, TaskQueues.GetByName("test_multiple_hooks"), tasks[0], nil)
 	// Should leave 3 tasks in queue.
 	g.Expect(combineResult).ShouldNot(BeNil())
 	g.Expect(TaskQueues.GetByName("test_multiple_hooks").Length()).Should(Equal(3))
diff --git a/pkg/shell-operator/operator_test.go b/pkg/shell-operator/operator_test.go
index 35fa97c..71d711c 100644
--- a/pkg/shell-operator/operator_test.go
+++ b/pkg/shell-operator/operator_test.go
@@ -9,23 +9,23 @@ import (
 	. "github.com/flant/shell-operator/pkg/hook/task_metadata"
 	. "github.com/flant/shell-operator/pkg/hook/types"
 	"github.com/flant/shell-operator/pkg/task"
+	utils "github.com/flant/shell-operator/pkg/utils/file"
 )
 
 func Test_Operator_startup_tasks(t *testing.T) {
 	g := NewWithT(t)
 
-	hooksDir, err := RequireExistingDirectory("testdata/startup_tasks/hooks")
+	hooksDir, err := utils.RequireExistingDirectory("testdata/startup_tasks/hooks")
 	g.Expect(err).ShouldNot(HaveOccurred())
 
-	op := NewShellOperator()
-	op.WithContext(context.Background())
-	SetupEventManagers(op)
-	SetupHookManagers(op, hooksDir, "")
+	op := NewShellOperator(context.Background())
+	op.SetupEventManagers()
+	op.setupHookManagers(hooksDir, "")
 
-	err = op.InitHookManager()
+	err = op.initHookManager()
 	g.Expect(err).ShouldNot(HaveOccurred())
 
-	op.BootstrapMainQueue(op.TaskQueues)
+	op.bootstrapMainQueue(op.TaskQueues)
 
 	expectTasks := []struct {
 		taskType    task.TaskType
diff --git a/pkg/task/queue/task_queue_test.go b/pkg/task/queue/task_queue_test.go
index 1869fb9..7f967dc 100644
--- a/pkg/task/queue/task_queue_test.go
+++ b/pkg/task/queue/task_queue_test.go
@@ -120,16 +120,16 @@ func Test_ExponentialBackoff(t *testing.T) {
 
 	q.Start()
 
-	// Expect TaskHandler returns Success result.
+	// Expect taskHandler returns Success result.
 	g.Eventually(queueStopCh, "5s", "20ms").Should(BeClosed(), "Should handle first task in queue successfully")
 
-	// Expect TaskHandler called 'fails' times.
+	// Expect taskHandler called 'fails' times.
 	g.Expect(Task.GetFailureCount()).Should(Equal(fails), "task should fail %d times.", fails)
 
 	prev := failureCounts[0]
 	for i := 1; i < len(failureCounts); i++ {
 		cur := failureCounts[i]
-		g.Expect(cur > prev).Should(BeTrue(), "TaskHandler should receive task with growing FailureCount. Got %d after %d", cur, prev)
+		g.Expect(cur > prev).Should(BeTrue(), "taskHandler should receive task with growing FailureCount. Got %d after %d", cur, prev)
 	}
 
 	// Expect mean delay is greater than mocked delay.
@@ -208,7 +208,7 @@ func Test_CancelDelay(t *testing.T) {
 	// Start handling 'erroneous' task.
 	q.Start()
 
-	// Expect TaskHandler returns Success result.
+	// Expect taskHandler returns Success result.
 	g.Eventually(delayStartsCh, "5s", "20ms").Should(BeClosed(), "Should handle failed task and starts a delay")
 
 	// Add healing task and cancel delay in parallel.
diff --git a/pkg/webhook/admission/manager_test.go b/pkg/webhook/admission/manager_test.go
index 8d55a06..7a6147f 100644
--- a/pkg/webhook/admission/manager_test.go
+++ b/pkg/webhook/admission/manager_test.go
@@ -7,7 +7,7 @@ import (
 )
 
 func Test_Manager_AddWebhook(t *testing.T) {
-	m := NewWebhookManager()
+	m := NewWebhookManager(nil)
 	m.Namespace = "default"
 	vs := &WebhookSettings{}
 	vs.ConfigurationName = "webhook-configuration"
diff --git a/test/hook/context/context_combiner.go b/test/hook/context/context_combiner.go
index 5257e9c..a9bfc35 100644
--- a/test/hook/context/context_combiner.go
+++ b/test/hook/context/context_combiner.go
@@ -19,7 +19,7 @@ const TestTaskType task.TaskType = "TestTask"
 // TestQueueName is a name of the queue created by ContextCombiner.
 const TestQueueName string = "test-queue"
 
-// ContextCombiner is used to bring logic behind the CombineBindingContextForHook method
+// ContextCombiner is used to bring logic behind the combineBindingContextForHook method
 // into tests. This method requires a ShellOperator instance with at least one queue
 // with tasks.
 type ContextCombiner struct {
diff --git a/test/hook/context/generator.go b/test/hook/context/generator.go
index 7093180..7c5e8ed 100644
--- a/test/hook/context/generator.go
+++ b/test/hook/context/generator.go
@@ -59,14 +59,11 @@ func NewBindingContextController(config string, version ...fake.ClusterVersion)
 		fakeCluster: fc,
 	}
 
-	b.KubeEventsManager = kubeeventsmanager.NewKubeEventsManager()
-	b.KubeEventsManager.WithContext(ctx)
-	b.KubeEventsManager.WithKubeClient(b.fakeCluster.Client)
+	b.KubeEventsManager = kubeeventsmanager.NewKubeEventsManager(ctx, b.fakeCluster.Client)
 	// Re-create factory to drop informers created using different b.fakeCluster.Client.
 	kubeeventsmanager.DefaultFactoryStore = kubeeventsmanager.NewFactoryStore()
 
-	b.ScheduleManager = schedulemanager.NewScheduleManager()
-	b.ScheduleManager.WithContext(ctx)
+	b.ScheduleManager = schedulemanager.NewScheduleManager(ctx)
 
 	b.Controller = NewStateController(fc, b.KubeEventsManager)
 
diff --git a/test/integration/kube_event_manager/kube_event_manager_test.go b/test/integration/kube_event_manager/kube_event_manager_test.go
index bda2455..532ddd5 100644
--- a/test/integration/kube_event_manager/kube_event_manager_test.go
+++ b/test/integration/kube_event_manager/kube_event_manager_test.go
@@ -26,9 +26,7 @@ var _ = Describe("Binding 'kubernetes' with kind 'Pod' should emit KubeEvent obj
 	var KubeEventsManager kube_events_manager.KubeEventsManager
 
 	BeforeEach(func() {
-		KubeEventsManager = kube_events_manager.NewKubeEventsManager()
-		KubeEventsManager.WithContext(context.Background())
-		KubeEventsManager.WithKubeClient(KubeClient)
+		KubeEventsManager = kube_events_manager.NewKubeEventsManager(context.Background(), KubeClient)
 	})
 
 	Context("with configVersion: v1", func() {
diff --git a/test/integration/kubeclient/object_patch_test.go b/test/integration/kubeclient/object_patch_test.go
index 788dac7..2218231 100644
--- a/test/integration/kubeclient/object_patch_test.go
+++ b/test/integration/kubeclient/object_patch_test.go
@@ -7,9 +7,9 @@ import (
 	"context"
 	"encoding/json"
 
+	uuid "github.com/gofrs/uuid/v5"
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
-	uuid "gopkg.in/satori/go.uuid.v1"
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -208,7 +208,7 @@ func ensureNamespace(name string) error {
 	return ObjectPatcher.ExecuteOperation(object_patch.NewCreateOperation(unstructuredNS, object_patch.UpdateIfExists()))
 }
 
-func ensureTestObject(namespace string, obj interface{}) error {
+func ensureTestObject(_ string, obj interface{}) error {
 	unstructuredObj, err := generateUnstructured(obj)
 	if err != nil {
 		panic(err)
@@ -233,5 +233,5 @@ func generateUnstructured(obj interface{}) (*unstructured.Unstructured, error) {
 }
 
 func randomSuffix() string {
-	return uuid.NewV4().String()[0:8]
+	return uuid.Must(uuid.NewV4()).String()[0:8]
 }
diff --git a/test/integration/suite/run.go b/test/integration/suite/run.go
index afb1f98..316eec6 100644
--- a/test/integration/suite/run.go
+++ b/test/integration/suite/run.go
@@ -17,7 +17,7 @@ import (
 var (
 	ClusterName   string
 	ContextName   string
-	KubeClient    klient.Client
+	KubeClient    *klient.Client
 	ObjectPatcher *object_patch.ObjectPatcher
 )