[
  {
    "path": ".github/workflows/create_git_release.yaml",
    "content": "on:\n  push:\n    tags:\n      - 'kubetunnel-cli-*' # Push events to matching v*, i.e. v1.0, v20.15.10\n\nname: Create Release\n\njobs:\n  create-release:\n    name: Create Git Release\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v2\n      - uses: ncipollo/release-action@v1.11.1\n        with:\n          token: ${{ secrets.GITHUB_TOKEN }}\n          name: ${{ secrets.GITHUB_REF_NAME }}\n  releases-matrix:\n    needs: [create-release]\n    name: Create Go Binary\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        os: [darwin-amd64,darwin-arm64,windows-amd64,linux-amd64]\n    steps:\n      - uses: actions/checkout@v3\n      - uses: wangyoucao577/go-release-action@v1.32\n        with:\n          github_token: ${{ secrets.GITHUB_TOKEN }}\n          build_command: make ${{ matrix.os }}-cli\n          binary_name: kubetunnel\n          asset_name: kubetunnel-${{ secrets.GITHUB_REF_NAME }}-${{ matrix.os }}\n          release_tag: ${{ secrets.GITHUB_REF_NAME }}\n#   homebrew-releaser:\n#     runs-on: ubuntu-latest\n#     needs: [releases-matrix]\n#     name: homebrew-releaser\n#     steps:\n#       - name: Release my project to my Homebrew tap\n#         uses: Justintime50/homebrew-releaser@v1\n#         with:\n#           # The name of the homebrew tap to publish your formula to as it appears on GitHub.\n#           # Required - strings.\n#           homebrew_owner: we-dcode\n#           homebrew_tap: homebrew-tap\n\n#           # The name of the folder in your homebrew tap where formula will be committed to.\n#           # Default is shown - string.\n#           formula_folder: formula\n\n#           # The GitHub Token (saved as a repo secret) that has `repo` permissions for the homebrew tap you want to release to.\n#           # Required - string.\n#           github_token: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}\n\n#           # Git author info used to commit to the homebrew tap.\n#           # Defaults are shown - strings.\n#           commit_owner: homebrew-releaser\n#           commit_email: homebrew-releaser@example.com\n\n#           # Custom dependencies in case other formulas are needed to build the current one.\n#           # Optional - multiline string.\n#           #          depends_on: |\n#           #            \"bash\" => :build\n#           #            \"gcc\"\n\n#           # Custom install command for your formula.\n#           # Required - string.\n#           install: 'bin.install \"kubetunnel\"'\n\n#           # Adds URL and checksum targets for different OS and architecture pairs. Using this option assumes \n#           # a tar archive exists on your GitHub repo with the following URL pattern (this cannot be customized):\n#           # https://github.com/{GITHUB_OWNER}/{REPO_NAME}/releases/download/{TAG}/{REPO_NAME}-{VERSION}-{OPERATING_SYSTEM}-{ARCHITECTURE}.tar.gz'\n#           # Darwin AMD pre-existing path example: https://github.com/justintime50/myrepo/releases/download/v1.2.0/myrepo-1.2.0-darwin-amd64.tar.gz\n#           # Linux ARM pre-existing path example: https://github.com/justintime50/myrepo/releases/download/v1.2.0/myrepo-1.2.0-linux-arm64.tar.gz\n#           # Optional - booleans.\n\n#           target_darwin_amd64: true\n#           target_darwin_arm64: true\n#           target_linux_amd64: true\n\n\n#           # Update your homebrew tap's README with a table of all projects in the tap.\n#           # This is done by pulling the information from all your formula.rb files - eg:\n#           #\n#           # | Project                                    | Description  | Install                  |\n#           # | ------------------------------------------ | ------------ | ------------------------ |\n#           # | [formula_1](https://github.com/user/repo1) | helpful text | `brew install formula_1` |\n#           # | [formula_2](https://github.com/user/repo2) | helpful text | `brew install formula_2` |\n#           # | [formula_3](https://github.com/user/repo3) | helpful text | `brew install formula_3` |\n#           #\n#           # Simply place the following in your README or wrap your project in these comment tags:\n#           # <!-- project_table_start -->\n#           # TABLE HERE\n#           # <!--project_table_end -->\n#           #\n#           # Finally, mark `update_readme_table` as `true` in your GitHub Action config and we'll do the work of building a custom table for you.\n#           # Default is `false` - boolean.\n#           update_readme_table: false\n\n#           # Skips committing the generated formula to a homebrew tap (useful for local testing).\n#           # Default is shown - boolean.\n#           skip_commit: false\n\n#           # Logs debugging info to console.\n#           # Default is shown - boolean.\n#           debug: true\n"
  },
  {
    "path": ".github/workflows/create_helm_release.yaml",
    "content": "name: Release Charts\n\non:\n  push:\n    branches:\n      - main\n\njobs:\n  release:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v2\n        with:\n          fetch-depth: 0\n\n      - name: Configure Git\n        run: |\n          git config user.name \"$GITHUB_ACTOR\"\n          git config user.email \"$GITHUB_ACTOR@users.noreply.github.com\"\n\n      - name: Install Helm\n        uses: azure/setup-helm@v1\n        with:\n          version: v3.4.0\n\n      - name: Prepare GPG key\n        run: |\n          gpg_dir=.cr-gpg\n          mkdir \"$gpg_dir\"\n\n          keyring=\"$gpg_dir/secring.gpg\"\n          base64 -d <<< \"$GPG_KEYRING_BASE64\" > \"$keyring\"\n\n          passphrase_file=\"$gpg_dir/passphrase\"\n          echo \"$GPG_PASSPHRASE\" > \"$passphrase_file\"\n\n          echo \"CR_PASSPHRASE_FILE=$passphrase_file\" >> \"$GITHUB_ENV\"\n          echo \"CR_KEYRING=$keyring\" >> \"$GITHUB_ENV\"\n        env:\n          GPG_KEYRING_BASE64: \"${{ secrets.GPG_KEYRING_BASE64 }}\"\n          GPG_PASSPHRASE: \"${{ secrets.GPG_PASSPHRASE }}\"\n\n      - name: Run chart-releaser\n        uses: helm/chart-releaser-action@v1.4.1\n        with:\n          charts_dir: charts\n          config: ci/cr.yaml\n        env:\n          CR_TOKEN: \"${{ secrets.GITHUB_TOKEN }}\"\n"
  },
  {
    "path": ".github/workflows/lint-test.yaml",
    "content": "name: Lint and Test Charts\n\non: pull_request\n\njobs:\n  lint-test:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v2\n        with:\n          fetch-depth: 0\n\n      - name: Set up Helm\n        uses: azure/setup-helm@v1\n        with:\n          version: v3.4.0\n\n      - name: Set up Python\n        uses: actions/setup-python@v2\n        with:\n          python-version: 3.7\n\n      - name: Set up chart-testing\n        uses: unguiculus/chart-testing-action@master\n        with:\n          version: v3.3.0\n\n      - name: Run chart-testing (list-changed)\n        id: list-changed\n        run: |\n          changed=$(ct list-changed --config ci/ct.yaml)\n          if [[ -n \"$changed\" ]]; then\n            echo \"::set-output name=changed::true\"\n          fi\n\n      - name: Run chart-testing (lint)\n        run: ct lint --debug --config ct.yaml\n\n      # Note: No need to check helm charts in a kind cluster,\n      #       they aren't supposed to work without configuration from client\n      #\n      #      - name: Create kind cluster\n      #        uses: helm/kind-action@v1.0.0\n      #        if: steps.list-changed.outputs.changed == 'true'\n\n      # - name: Run chart-testing (install)\n      #   run: ct install --config ct.yaml\n"
  },
  {
    "path": ".gitignore",
    "content": "# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\n\n# Test binary, built with `go test -c`\n*.test\n\n# Output of the go coverage tool, specifically when used with LiteIDE\n*.out\n\n# Dependency directories (remove the comment below to include it)\n# vendor/\n\n.idea\nbuild\n.DS_Store\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Community Code of Conduct\n\nkube-tunnel follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).\n"
  },
  {
    "path": "Dockerfile",
    "content": "\nFROM golang:1.18-bullseye as build-env\n\nCOPY ./ /go/src/github.com/dcode/kubetunnel/\n\nWORKDIR /go/src/github.com/dcode/kubetunnel\n\n# install all dependencies\n#RUN go get ./...\nRUN go mod tidy\nRUN GOOS=linux GOARCH=amd64 go build -o /kubetunnel cmd/server/kubetunnel-server.go\n\n## Deploy\nFROM gcr.io/distroless/base-debian10\n\nWORKDIR /\n\nCOPY --from=build-env /kubetunnel /kubetunnel\n\nEXPOSE 8080\n\nUSER nonroot:nonroot\n\n# Put back once we have an application\nCMD [\"/kubetunnel\"]\n\n"
  },
  {
    "path": "Dockerfile.operator",
    "content": "# Build the manager binary\nFROM golang:1.18 as builder\n\nWORKDIR /workspace\n# Copy the Go Modules manifests\nCOPY go.mod go.mod\nCOPY go.sum go.sum\n# cache deps before building and copying source so that we don't need to re-download as much\n# and so that source changes don't invalidate our downloaded layer\nRUN go mod download\n\n# Copy the go source\nCOPY cmd/operator/main.go main.go\n# COPY pkg/operator/api api/\nCOPY pkg pkg/\n# COPY controllers controllers/\n\n# Build\nRUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o manager main.go\n\nFROM registry.access.redhat.com/ubi8/ubi-minimal:8.4\n\nENV HOME=/opt/helm \\\n    USER_NAME=helm \\\n    USER_UID=1001\n\nRUN echo \"${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin\" >> /etc/passwd\n\n# Copy necessary files with the right permissions\nCOPY --chown=${USER_UID}:0 pkg/operator/watches.yaml ${HOME}/watches.yaml\nCOPY --chown=${USER_UID}:0 pkg/operator/helm-charts  ${HOME}/helm-charts\n\n# Copy manager binary\nCOPY --from=builder /workspace/manager .\n\nUSER ${USER_UID}\n\nWORKDIR ${HOME}\n\nENTRYPOINT [\"/manager\"]\n"
  },
  {
    "path": "LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright The Helm Owners\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "Makefile",
    "content": "# Output File Location\nROOT_DIR=$(shell git rev-parse --show-toplevel)\nDIR=$(ROOT_DIR)/build\nBINARY=kubetunnel\n$(shell mkdir -p ${DIR})\n\nAPP_VERSION=\"0.3.0\" # TODO: get this one from env var\nOPERATOR_VERSION=\"0.0.16\"\nKUBETUNNEL_VERSION=\"1.1.4\"\n# Go build flags\nLDFLAGS=-ldflags \"-X main.Version=${APP_VERSION} -X main.OperatorVersion=${OPERATOR_VERSION}\"\n\ndefault-cli:\n\tgo build ${LDFLAGS} -o ${DIR}/${BINARY} ${ROOT_DIR}/cmd/cli\n\n# Compile CLI - Windows x64\nwindows-amd64-cli:\n\tmkdir -p ${DIR}/windows\n\tGOOS=windows GOARCH=amd64 go build ${LDFLAGS} -o ${BINARY} ${ROOT_DIR}/cmd/cli\n\n# Compile CLI - Linux x64\nlinux-amd64-cli:\n\tmkdir -p ${DIR}/linux\n\tGOOS=linux GOARCH=amd64 go build ${LDFLAGS} -o ${BINARY} ${ROOT_DIR}/cmd/cli\n\n# Compile CLI - Darwin arm x64\ndarwin-arm64-cli:\n\tmkdir -p ${DIR}/mac\n\tGOOS=darwin GOARCH=arm64 go build ${LDFLAGS} -o ${BINARY} ${ROOT_DIR}/cmd/cli\n\n# Compile CLI - Darwin amd x64\ndarwin-amd64-cli:\n\tmkdir -p ${DIR}/mac\n\tGOOS=darwin GOARCH=amd64 go build ${LDFLAGS} -o ${BINARY} ${ROOT_DIR}/cmd/cli\n\nall-cli: darwin-cli linux-cli windows-cli\n\nbuild_kubetunnel_server:\n\tdocker build -t dcodetech/kubetunnel:${KUBETUNNEL_VERSION} . && docker push dcodetech/kubetunnel:${KUBETUNNEL_VERSION}\n\t#sed -i 's/KUBETUNNEL_SERVER_VERSION/${KUBETUNNEL_VERSION}/g' ${ROOT_DIR}/pkg/operator/helm-charts/templates\n\nbuild_operator:\n\tdocker build -t dcodetech/kubetunnel-operator:${OPERATOR_VERSION} -f Dockerfile.operator . && docker push dcodetech/kubetunnel-operator:${OPERATOR_VERSION}\n#\tsed -i 's/KUBETUNNEL_OPERATOR_VERSION/${OPERATOR_VERSION}/g' ${ROOT_DIR}/charts/kubetunnel-operator/Chart.yaml\n#\tsed -i 's/KUBETUNNEL_OPERATOR_VERSION/${OPERATOR_VERSION}/g' ${ROOT_DIR}/charts/kubetunnel-operator/templates/operator.yaml\n\n\n\n\nclean:\n\trm -rf ${DIR}*\n"
  },
  {
    "path": "Makefile.operator",
    "content": "# VERSION defines the project version for the bundle.\n# Update this value when you upgrade the version of your project.\n# To re-generate a bundle for another specific version without changing the standard setup, you can:\n# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2)\n# - use environment variables to overwrite this value (e.g export VERSION=0.0.2)\nVERSION ?= 0.0.10\n\n# CHANNELS define the bundle channels used in the bundle.\n# Add a new line here if you would like to change its default config. (E.g CHANNELS = \"candidate,fast,stable\")\n# To re-generate a bundle for other specific channels without changing the standard setup, you can:\n# - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=candidate,fast,stable)\n# - use environment variables to overwrite this value (e.g export CHANNELS=\"candidate,fast,stable\")\nifneq ($(origin CHANNELS), undefined)\nBUNDLE_CHANNELS := --channels=$(CHANNELS)\nendif\n\n# DEFAULT_CHANNEL defines the default channel used in the bundle.\n# Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = \"stable\")\n# To re-generate a bundle for any other default channel without changing the default setup, you can:\n# - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable)\n# - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL=\"stable\")\nifneq ($(origin DEFAULT_CHANNEL), undefined)\nBUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL)\nendif\nBUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL)\n\n# IMAGE_TAG_BASE defines the docker.io namespace and part of the image name for remote images.\n# This variable is used to construct full image tags for bundle and catalog images.\n#\n# For example, running 'make bundle-build bundle-push catalog-build catalog-push' will build and push both\n# dcode.tech/operator-bundle:$VERSION and dcode.tech/operator-catalog:$VERSION.\nIMAGE_TAG_BASE ?= dcodetech/kubetunnel-operator\n\n# BUNDLE_IMG defines the image:tag used for the bundle.\n# You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=<some-registry>/<project-name-bundle>:<tag>)\nBUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION)\n\n# BUNDLE_GEN_FLAGS are the flags passed to the operator-sdk generate bundle command\nBUNDLE_GEN_FLAGS ?= -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)\n\n# USE_IMAGE_DIGESTS defines if images are resolved via tags or digests\n# You can enable this value if you would like to use SHA Based Digests\n# To enable set flag to true\nUSE_IMAGE_DIGESTS ?= false\nifeq ($(USE_IMAGE_DIGESTS), true)\n\tBUNDLE_GEN_FLAGS += --use-image-digests\nendif\n\n# Image URL to use all building/pushing image targets\nIMG ?= $(IMAGE_TAG_BASE):$(VERSION)\n# Produce CRDs that work back to Kubernetes 1.11 (no version conversion)\nCRD_OPTIONS ?= \"crd:trivialVersions=true,preserveUnknownFields=false\"\n# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.\nENVTEST_K8S_VERSION = 1.24\n\n# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)\nifeq (,$(shell go env GOBIN))\nGOBIN=$(shell go env GOPATH)/bin\nelse\nGOBIN=$(shell go env GOBIN)\nendif\n\n# Setting SHELL to bash allows bash commands to be executed by recipes.\n# This is a requirement for 'setup-envtest.sh' in the test target.\n# Options are set to exit when a recipe line exits non-zero or a piped command fails.\nSHELL = /usr/bin/env bash -o pipefail\n.SHELLFLAGS = -ec\n\n\n##@ General\n\n# The help target prints out all targets with their descriptions organized\n# beneath their categories. The categories are represented by '##@' and the\n# target descriptions by '##'. The awk commands is responsible for reading the\n# entire set of makefiles included in this invocation, looking for lines of the\n# file as xyz: ## something, and then pretty-format the target and help. Then,\n# if there's a line with ##@ something, that gets pretty-printed as a category.\n# More info on the usage of ANSI control characters for terminal formatting:\n# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters\n# More info on the awk command:\n# http://linuxcommand.org/lc3_adv_awk.php\n\nhelp: ## Display this help.\n\t@awk 'BEGIN {FS = \":.*##\"; printf \"\\nUsage:\\n  make \\033[36m<target>\\033[0m\\n\"} /^[a-zA-Z_0-9-]+:.*?##/ { printf \"  \\033[36m%-15s\\033[0m %s\\n\", $$1, $$2 } /^##@/ { printf \"\\n\\033[1m%s\\033[0m\\n\", substr($$0, 5) } ' $(MAKEFILE_LIST)\n\n##@ Build\n\nrun: helm-operator ## Run against the configured Kubernetes cluster in ~/.kube/config\n\t$(HELM_OPERATOR) run\n\ndocker-build: ## Build docker image with the manager.\n\tdocker build -t ${IMG} -f Dockerfile.operator .\n\ndocker-push: ## Push docker image with the manager.\n\tdocker push ${IMG}\n\n##@ Development\n\nmanifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.\n\t$(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths=\"./...\" output:crd:artifacts:config=config/crd/bases\n\ngenerate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.\n\t$(CONTROLLER_GEN) object:headerFile=\"\" paths=\"./...\"\n\nfmt: ## Run go fmt against code.\n\tgo fmt ./...\n\nvet: ## Run go vet against code.\n\tgo vet ./...\n\ntest: manifests generate fmt vet envtest ## Run tests.\n\tKUBEBUILDER_ASSETS=\"$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)\" go test ./... -coverprofile cover.out\n\n##@ Deployment\n\ninstall: kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.\n\t$(KUSTOMIZE) build config/crd | kubectl apply -f -\n\nuninstall: kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config.\n\t$(KUSTOMIZE) build config/crd | kubectl delete -f -\n\ndeploy: kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.\n\tcd pkg/operator/config/manager && $(KUSTOMIZE) edit set image controller=${IMG}\n\t$(KUSTOMIZE) build pkg/operator/config/default | kubectl apply -f -\n\nundeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config.\n\t$(KUSTOMIZE) build pkg/operator/config/default | kubectl delete -f -\n\nOS := $(shell uname -s | tr '[:upper:]' '[:lower:]')\nARCH := $(shell uname -m | sed 's/x86_64/amd64/')\n\nCONTROLLER_GEN = $(shell pwd)/bin/controller-gen\ncontroller-gen: ## Download controller-gen locally if necessary.\n\t$(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.6.1)\n\nKUSTOMIZE = $(shell pwd)/bin/kustomize\nkustomize: ## Download kustomize locally if necessary.\n\t$(call go-get-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v4@v4.5.2)\n\nENVTEST = $(shell pwd)/bin/setup-envtest\nenvtest: ## Download envtest-setup locally if necessary.\n\t$(call go-get-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@latest)\n\n# go-get-tool will 'go get' any package $2 and install it to $1.\nPROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))\ndefine go-get-tool\n@[ -f $(1) ] || { \\\nset -e ;\\\nTMP_DIR=$$(mktemp -d) ;\\\ncd $$TMP_DIR ;\\\ngo mod init tmp ;\\\necho \"Downloading $(2)\" ;\\\nGOBIN=$(PROJECT_DIR)/bin go get $(2) && GOBIN=$(PROJECT_DIR)/bin go install $(2) ;\\\nrm -rf $$TMP_DIR ;\\\n}\nendef\n\n.PHONY: helm-operator\nHELM_OPERATOR = $(shell pwd)/bin/helm-operator\nhelm-operator: ## Download helm-operator locally if necessary, preferring the $(pwd)/bin path over global if both exist.\nifeq (,$(wildcard $(HELM_OPERATOR)))\nifeq (,$(shell which helm-operator 2>/dev/null))\n\t@{ \\\n\tset -e ;\\\n\tmkdir -p $(dir $(HELM_OPERATOR)) ;\\\n\tcurl -sSLo $(HELM_OPERATOR) https://github.com/operator-framework/operator-sdk/releases/download/v1.9.0/helm-operator_$(OS)_$(ARCH) ;\\\n\tchmod +x $(HELM_OPERATOR) ;\\\n\t}\nelse\nHELM_OPERATOR = $(shell which helm-operator)\nendif\nendif\n\n\n.PHONY: bundle\nbundle: kustomize ## Generate bundle manifests and metadata, then validate generated files.\n\tcd pkg/operator && operator-sdk generate kustomize manifests -q\n\tcd pkg/operator/config/manager && $(KUSTOMIZE) edit set image controller=$(IMG)\n\tcd pkg/operator && $(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)\n\tcd pkg/operator && operator-sdk bundle validate ./bundle\n\n.PHONY: bundle-build\nbundle-build: ## Build the bundle image.\n\tdocker build -f bundle.Dockerfile -t $(BUNDLE_IMG) .\n\n.PHONY: bundle-push\nbundle-push: ## Push the bundle image.\n\t$(MAKE) docker-push IMG=$(BUNDLE_IMG)\n\n.PHONY: opm\nOPM = ./bin/opm\nopm: ## Download opm locally if necessary.\nifeq (,$(wildcard $(OPM)))\nifeq (,$(shell which opm 2>/dev/null))\n\t@{ \\\n\tset -e ;\\\n\tmkdir -p $(dir $(OPM)) ;\\\n\tcurl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.23.0/$(OS)-$(ARCH)-opm ;\\\n\tchmod +x $(OPM) ;\\\n\t}\nelse\nOPM = $(shell which opm)\nendif\nendif\n\n# A comma-separated list of bundle images (e.g. make catalog-build BUNDLE_IMGS=example.com/operator-bundle:v0.1.0,example.com/operator-bundle:v0.2.0).\n# These images MUST exist in a registry and be pull-able.\nBUNDLE_IMGS ?= $(BUNDLE_IMG)\n\n# The image tag given to the resulting catalog image (e.g. make catalog-build CATALOG_IMG=example.com/operator-catalog:v0.2.0).\nCATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION)\n\n# Set CATALOG_BASE_IMG to an existing catalog image tag to add $BUNDLE_IMGS to that image.\nifneq ($(origin CATALOG_BASE_IMG), undefined)\nFROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG)\nendif\n\n# Build a catalog image by adding bundle images to an empty catalog using the operator package manager tool, 'opm'.\n# This recipe invokes 'opm' in 'semver' bundle add mode. For more information on add modes, see:\n# https://github.com/operator-framework/community-operators/blob/7f1438c/docs/packaging-operator.md#updating-your-existing-operator\n.PHONY: catalog-build\ncatalog-build: opm ## Build a catalog image.\n\t$(OPM) index add --container-tool docker --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT)\n\n# Push the catalog image.\n.PHONY: catalog-push\ncatalog-push: ## Push a catalog image.\n\t$(MAKE) docker-push IMG=$(CATALOG_IMG)\n"
  },
  {
    "path": "README.md",
    "content": "\n\n<p align=\"center\" styles=\"background-color: white\">\n<img src=\"./assets/logo.svg\" width=\"300\"><br>\n  by <a href=\"https://dcode.tech\">Dcode.tech</a>\n</p>\n\n\n\n# KubeTunnel: Develop locally while being connected to Kubernetes.\n\n<img src=\"./assets/teaser.gif\" width=\"1000\">\n\nWebsite: [https://www.dcode.tech/](https://www.dcode.tech)  \nSlack: [Discuss](https://we-dcode.slack.com/archives/C047WAUR41M)\n\n**With KubeTunnel:**\n\n* You run one service locally using your favorite IDE\n* You run the rest of your microservices in Kubernetes, not limited to resources and compute power.\n\n**This gives developers:**\n\n* A fast local dev loop, with no waiting for a container build / push / deploy\n* Ability to use their favorite local tools (IDE, debugger, etc.)\n* Ability to run large-scale applications that can't run locally\n\n---\n\n## How It Works\n1. You select a **Kubernetes service** and a **local process**.\n2. Kubetunnel launches a pod on your namespace, and **changes the service** to move all traffic to this pod. This pod forwards all traffic to your local proccess through a secured tunnel.\n3. The CLI then forwards all your Kubernetes services in your namespace to localhost. \n\nThis creates a two way connection between your local process and the cluster meaning:\n\n* All other pods now connect to your local process instead of the original pod in the cluster.\n* You are able to connect to other services in the namespace from your local process.\n\nImportant: This tool is meant to be used only on development environments as all services will connect to you instead of the cluster.\n\nYou can read more about it [here](docs/Architecture.md).\n<p align=\"center\">\n<img src=\"./assets/architecture.png\" width=\"700\"><br>\n</p>\n\n---\n## Installation\n\n\nKubetunnel CLI can be installed through multiple channels.\n\n### Linux/Mac\n\nThere are 2 methods to install the CLI on Linux/Mac.\n\n1. Install Kubetunnel CLI from [Kubetunnel tap](https://github.com/kubetunnel/homebrew-tap) with [Homebrew](https://brew.sh) by running:\n\n```bash\nbrew tap we-dcode/tap\nbrew install kubetunnel\n```\n\n2. Download the KubeTunnel CLI with the latest binary in our [releases page](https://github.com/we-dcode/kubetunnel/releases/latest). \n\n### Windows\n\nDownload the latest CLI binary in our [releases page](https://github.com/we-dcode/kubetunnel/releases/latest)\n\n\n# Getting started with Kubetunnel CLI\n\nThings to consider before you start:\n\n* For this quickstart guide, your Kubernetes cluster is assumed to be already up and running. Before you proceed with the KubeTunnel installation, make sure you check the supported versions.\n* Make sure your user has `cluster-admin` permissions for the initial installation of the operator component. For the tunnels themselves, this is not needed.\n* The operator needs network access to each tunnel. If your namespaces deny ingress and egress traffic, please create NetworkPolicies to enable traffic between them as explained [here](docs/Network.md).\n* You will need local administrator privileges to create each tunnel as the KubeTunnel client modifies the local hosts file to include the cluster services.\n\nOnce you installed the KubeTunnel CLI, you can verify it's working by running:\n\n```bash\nkubetunnel --help\n```\n\nFor each of the following commands, you can run --help for more options.\n\n### 1. Installing the Operator\n\nTo install the operator and CRDs **using the CLI**, run the following command:\n\n```bash\nkubetunnel install \n```\n\nTo install the operator **using a helm chart**, run the following commands:\n\n```bash\nhelm repo add we-dcode https://we-dcode.github.io/kubetunnel\nhelm install we-dcode/kubetunnel-operator <release name>\n\n```\n\nAt this point, the KubeTunnel Kubernetes Operator is successfully installed. Once the KubeTunnel Operator pod is running, you are able to start tunneling processes to your cluster. \n\n### 2. Creating a tunnel\n\nFor each Kubernetes service you want to tunnel, run the following command:\n\n```bash\n  sudo -E kubetunnel create-tunnel -p '8080:80' svc_name\n```\n\nThis command waits for the local port to be available with the process you want to tunnel.  When the local process is up, it is tunneled to the cluster and the application service is switched to forward traffic to it.  If your local process becomes unavailable, the service is switched back to the original pod.\n\n##  Autocomplete with Kubetunnel CLI\n\nKubeTunnel supports completion for multiple shells.  \nFor autocomplete for your shell run the following command:\n\n```bash\nkubetunnel completion --help\n```\n\n# Known Limitations\n\n* The current KubeTunnel version can only tunnel a single service per workstation. In the future, we will add support for multiple services.\n\n##  Troubleshooting\n\n**Q**: I'm not able to create a tunnel. What's going on?  \n\n**A**: Check the following things before creating a tunnel:\n1. You are able to connect to the cluster from your workstation. \n2. You have run the `kubetunnel install` command. \n3. You can check the logs of the operator pod:    \n   a. Run the command `kubectl get pods -n <operator namespace>`   \n   b. Observe the state of the pod. Is it running or in some kind of error?  \n   c. Run `kubectl logs <operator pod name> -c manager`. Do you see any errors?  \n4. The kubetunnel pods need to be able to connect to the operator pod. Are NetworkPolicies enabled on your cluster? If so, have you created them as seen [here](./docs/Network.md)\n5. Check the logs of the kubetunnel pod itself. Has it been created? Does it have some kind of error?\n\n**Q**: I'm not able to install the operator. What's going on?  \n\n**A**: Check the following things before creating a tunnel:\n1. You are able to connect to the cluster from your workstation. \n2. Installing the operator includes installing ClusterRoles, ClusterRoleBindings and CustomResourceDefinitions. Do you have the sufficient privileges to create these resources?\n3. Are you using the latest version of the CLI? If not, try upgrading your version.\n\n\n## Cleanup\n\nTo uninstall resources for a specific tunnel, find the specific tunnel you wish to delete and run the following commands:\n\n```bash\nkubectl get kubetunnel -n <requested namespace> \n\n# Search for the tunnel you wish to delete\nkubectl delete kubetunnel <name>\n```\n\nTo uninstall the operator itself, run the following command after deleting all kubetunnel resources:\n\n```bash\n\nhelm ls -n <operator-namespace>\nhelm uninstall <release-name> -n <operator-namespace>\n```\n\n\n# Getting support\n\nIf you need support using KubeTunnel CLI, please [join our Slack channel](https://join.slack.com/t/we-dcode/shared_invite/zt-1kfg6u0d2-hICXM19FWTEP~PCWoyBZww).\n\nPlease leave issues for any error or bug that you encounter.\n\n# Contributing\n\nIf you are an external contributor, before working on any contributions, please first [contact us](https://dcode.tech) to discuss the issue or feature request with us.\n\n---\n\nMade with 💙 by Dcode.tech\n"
  },
  {
    "path": "charts/kubetunnel-operator/Chart.yaml",
    "content": "apiVersion: v2\nname: kubetunnel-operator\ndescription: A Helm chart for Kubernetes\n\n# A chart can be either an 'application' or a 'library' chart.\n#\n# Application charts are a collection of templates that can be packaged into versioned archives\n# to be deployed.\n#\n# Library charts provide useful utilities or functions for the chart developer. They're included as\n# a dependency of application charts to inject those utilities and functions into the rendering\n# pipeline. Library charts do not define any templates and therefore cannot be deployed.\ntype: application\n\n# This is the chart version. This version number should be incremented each time you make changes\n# to the chart and its templates, including the app version.\n# Versions are expected to follow Semantic Versioning (https://semver.org/)\nversion: 0.0.16\n\n# This is the version number of the application being deployed. This version number should be\n# incremented each time you make changes to the application. Versions are not expected to\n# follow Semantic Versioning. They should reflect the version the application is using.\n# It is recommended to use it with quotes.\nappVersion: \"1.16.0\"\nmaintainers:\n  - name: Eliran Wolf\n    email: eliran@dcode.tech\n  - name: Maor Davidov\n    email: maor@dcode.tech\n  - name: tamirshaul\n    email: tshaul@gmail.com\n"
  },
  {
    "path": "charts/kubetunnel-operator/crds/crd.yaml",
    "content": "---\napiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  name: kubetunnels.application.dcode.tech\nspec:\n  group: application.dcode.tech\n  names:\n    kind: Kubetunnel\n    listKind: KubetunnelList\n    plural: kubetunnels\n    singular: kubetunnel\n  scope: Namespaced\n  versions:\n  - additionalPrinterColumns:\n    - jsonPath: .spec.isConnected\n      name: Is Connected\n      type: boolean\n    - jsonPath: .spec.client\n      name: Client\n      type: string\n    name: v1\n    schema:\n      openAPIV3Schema:\n        description: Kubetunnel is the Schema for the kubetunnels API\n        properties:\n          apiVersion:\n            description: 'APIVersion defines the versioned schema of this representation\n              of an object. Servers should convert recognized schemas to the latest\n              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'\n            type: string\n          client:\n            default: none\n            description: Client defines name of client\n            type: string\n            x-kubernetes-preserve-unknown-fields: true\n          isConnected:\n            default: false\n            description: Connected defines if connected to client\n            type: boolean\n            x-kubernetes-preserve-unknown-fields: true\n          kind:\n            description: 'Kind is a string value representing the REST resource this\n              object represents. Servers may infer this from the endpoint the client\n              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'\n            type: string\n          metadata:\n            type: object\n          spec:\n            description: Spec defines the desired state of Kubetunnel\n            type: object\n            x-kubernetes-preserve-unknown-fields: true\n          status:\n            description: Status defines the observed state of Kubetunnel\n            type: object\n            x-kubernetes-preserve-unknown-fields: true\n        type: object\n    served: true\n    storage: true\n    subresources:\n      status: {}\n\n"
  },
  {
    "path": "charts/kubetunnel-operator/templates/clusterrole.metrics.yaml",
    "content": "---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: operator-metrics-reader\nrules:\n- nonResourceURLs:\n  - /metrics\n  verbs:\n  - get\n\n"
  },
  {
    "path": "charts/kubetunnel-operator/templates/clusterrole.proxy.yaml",
    "content": "---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: operator-proxy-role\nrules:\n- apiGroups:\n  - authentication.k8s.io\n  resources:\n  - tokenreviews\n  verbs:\n  - create\n- apiGroups:\n  - authorization.k8s.io\n  resources:\n  - subjectaccessreviews\n  verbs:\n  - create\n\n"
  },
  {
    "path": "charts/kubetunnel-operator/templates/clusterrole.yaml",
    "content": "---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: operator-manager-role\nrules:\n- apiGroups:\n  - \"\"\n  resources:\n  - namespaces\n  - roles\n  verbs:\n  - get\n- apiGroups:\n  - \"\"\n  - rbac.authorization.k8s.io\n  - roles.rbac.authorization.k8s.io\n  - authorization.k8s.io\n  resources:\n  - secrets\n  - configmaps\n  - rolebindings\n  - roles\n  verbs:\n  - '*'\n- apiGroups:\n  - \"\"\n  resources:\n  - events\n  verbs:\n  - create\n- apiGroups:\n  - application.dcode.tech\n  resources:\n  - kubetunnels\n  - kubetunnels/status\n  - kubetunnels/finalizers\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - \"\"\n  resources:\n  - serviceaccounts\n  - services\n  - roles\n  verbs:\n  - '*'\n- apiGroups:\n  - apps\n  resources:\n  - deployments\n  verbs:\n  - '*'\n\n"
  },
  {
    "path": "charts/kubetunnel-operator/templates/cm.yaml",
    "content": "---\napiVersion: v1\ndata:\n  controller_manager_config.yaml: |\n    apiVersion: controller-runtime.sigs.k8s.io/v1alpha1\n    kind: ControllerManagerConfig\n    health:\n      healthProbeBindAddress: :8081\n    metrics:\n      bindAddress: 127.0.0.1:8080\n    webhook:\n      port: 9443\n    leaderElection:\n      leaderElect: true\n      resourceName: 5dbd2493.dcode.tech\n    # leaderElectionReleaseOnCancel defines if the leader should step down volume\n    # when the Manager ends. This requires the binary to immediately end when the\n    # Manager is stopped, otherwise, this setting is unsafe. Setting this significantly\n    # speeds up voluntary leader transitions as the new leader don't have to wait\n    # LeaseDuration time first.\n    # In the default scaffold provided, the program ends immediately after\n    # the manager stops, so would be fine to enable this option. However,\n    # if you are doing or is intended to do any operation such as perform cleanups\n    # after the manager stops then its usage might be unsafe.\n    # leaderElectionReleaseOnCancel: true\nkind: ConfigMap\nmetadata:\n  name: operator-manager-config\n\n"
  },
  {
    "path": "charts/kubetunnel-operator/templates/crb.yaml",
    "content": "---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: operator-manager-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: operator-manager-role\nsubjects:\n- kind: ServiceAccount\n  name: operator-controller-manager\n  namespace: {{ .Release.Namespace }}\n\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: operator-proxy-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: operator-proxy-role\nsubjects:\n- kind: ServiceAccount\n  name: operator-controller-manager\n  namespace: {{ .Release.Namespace }}\n\n"
  },
  {
    "path": "charts/kubetunnel-operator/templates/operator.yaml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    we-dcode-app: kubetunnel-operator\n  name: operator-controller-manager-metrics-service\nspec:\n  ports:\n  - name: https\n    port: 8443\n    protocol: TCP\n    targetPort: https\n  selector:\n    we-dcode-app: kubetunnel-operator\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    app.kubernetes.io/instance: kube-tunnel-operator\n  name: operator-kube-tunnel-operator\nspec:\n  internalTrafficPolicy: Cluster\n  ipFamilies:\n  - IPv4\n  ipFamilyPolicy: SingleStack\n  ports:\n  - name: http\n    port: 80\n    targetPort: http\n  selector:\n    we-dcode-app: kubetunnel-operator\n  type: ClusterIP\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    we-dcode-app: kubetunnel-operator\n  name: kubetunnel-operator\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      we-dcode-app: kubetunnel-operator\n  template:\n    metadata:\n      annotations:\n        kubectl.kubernetes.io/default-container: manager\n      labels:\n        we-dcode-app: kubetunnel-operator\n    spec:\n      containers:\n      - args:\n        - --secure-listen-address=0.0.0.0:8443\n        - --upstream=http://127.0.0.1:8080/\n        - --logtostderr=true\n        - --v=0\n        image: gcr.io/kubebuilder/kube-rbac-proxy:v0.13.0\n        name: kube-rbac-proxy\n        ports:\n        - containerPort: 8443\n          name: https\n          protocol: TCP\n        resources:\n          limits:\n            cpu: 500m\n            memory: 128Mi\n          requests:\n            cpu: 5m\n            memory: 64Mi\n        securityContext:\n          allowPrivilegeEscalation: false\n          capabilities:\n            drop:\n            - ALL\n      - args:\n        - --health-probe-bind-address=:8081\n        - --metrics-bind-address=127.0.0.1:8080\n        - --leader-elect\n        - --leader-election-id=operator\n        env:\n        - name: SERVICE_PORT\n          value: {{ .Values.service.port | quote }}\n        - name: SERVICE_NAME\n          value: {{ .Values.service.name }}\n        - name: POD_NAMESPACE\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.namespace\n        image: dcodetech/kubetunnel-operator:0.0.14\n        livenessProbe:\n          httpGet:\n            path: /healthz\n            port: 8081\n          initialDelaySeconds: 15\n          periodSeconds: 20\n        name: manager\n        ports:\n        - containerPort: 8083\n          name: http\n          protocol: TCP\n        readinessProbe:\n          httpGet:\n            path: /readyz\n            port: 8081\n          initialDelaySeconds: 5\n          periodSeconds: 10\n        resources:\n          limits:\n            cpu: 500m\n            memory: 512Mi\n          requests:\n            cpu: 500m\n            memory: 512Mi\n        securityContext:\n          allowPrivilegeEscalation: false\n          capabilities:\n            drop:\n            - ALL\n      securityContext:\n        runAsNonRoot: true\n      serviceAccountName: operator-controller-manager\n      terminationGracePeriodSeconds: 10\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    app.kubernetes.io/instance: kube-tunnel-operator\n  name: {{ .Values.service.name }}\nspec:\n  internalTrafficPolicy: Cluster\n  ipFamilies:\n  - IPv4\n  ipFamilyPolicy: SingleStack\n  ports:\n  - name: http\n    port: {{ .Values.service.port }}\n    targetPort: http\n  selector:\n    we-dcode-app: kubetunnel-operator\n  type: ClusterIP\n"
  },
  {
    "path": "charts/kubetunnel-operator/templates/rb.yaml",
    "content": "---\napiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  name: operator-leader-election-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: Role\n  name: operator-leader-election-role\nsubjects:\n- kind: ServiceAccount\n  name: operator-controller-manager\n  namespace: {{ .Release.Namespace }}\n\n"
  },
  {
    "path": "charts/kubetunnel-operator/templates/role.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n  name: operator-leader-election-role\nrules:\n- apiGroups:\n  - \"\"\n  resources:\n  - configmaps\n  verbs:\n  - get\n  - list\n  - watch\n  - create\n  - update\n  - patch\n  - delete\n- apiGroups:\n  - coordination.k8s.io\n  resources:\n  - leases\n  verbs:\n  - get\n  - list\n  - watch\n  - create\n  - update\n  - patch\n  - delete\n- apiGroups:\n  - \"\"\n  resources:\n  - events\n  verbs:\n  - create\n  - patch\n\n"
  },
  {
    "path": "charts/kubetunnel-operator/templates/serviceaccount.yaml",
    "content": "---\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: operator-controller-manager\n"
  },
  {
    "path": "charts/kubetunnel-operator/values.yaml",
    "content": "service:\n  name: \"kube-tunnel-operator\"\n  port: 80\n"
  },
  {
    "path": "ci/cr.yaml",
    "content": "sign: false\nkey: cr-test-key\n"
  },
  {
    "path": "ci/ct.yaml",
    "content": "# See https://github.com/helm/chart-testing#configuration\nremote: origin\nchart-dirs:\n  - charts\nchart-repos:\n  - bitnami=https://charts.bitnami.com/bitnami\nhelm-extra-args: --timeout 600s\ntarget-branch: main\nvalidate-maintainers: false\n"
  },
  {
    "path": "cmd/cli/cmds/completion.go",
    "content": "package cmds\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/spf13/cobra\"\n\n\tcmdutil \"k8s.io/kubectl/pkg/cmd/util\"\n\t\"k8s.io/kubectl/pkg/util/i18n\"\n\t\"k8s.io/kubectl/pkg/util/templates\"\n)\n\nconst defaultBoilerPlate = `\n# Copyright 2016 The Kubernetes Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n`\n\nvar (\n\tcompletionLong = templates.LongDesc(i18n.T(`\n\t\tOutput shell completion code for the specified shell (bash, zsh, fish, or powershell).\n\t\tThe shell code must be evaluated to provide interactive\n\t\tcompletion of kubetunnel commands.  This can be done by sourcing it from\n\t\tthe .bash_profile.\n\n\t\tDetailed instructions on how to do this are available here:\n\n        for macOS:\n        https://kubernetes.io/docs/tasks/tools/install-kubectl-macos/#enable-shell-autocompletion\n\n        for linux:\n        https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/#enable-shell-autocompletion\n\n        for windows:\n        https://kubernetes.io/docs/tasks/tools/install-kubectl-windows/#enable-shell-autocompletion\n\n\t\tNote for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2.`))\n\n\tcompletionExample = templates.Examples(i18n.T(`\n\t\t# Installing bash completion on macOS using homebrew\n\t\t## If running Bash 3.2 included with macOS\n\t\t    brew install bash-completion\n\t\t## or, if running Bash 4.1+\n\t\t    brew install bash-completion@2\n\t\t## If kubetunnel is installed via homebrew, this should start working immediately\n\t\t## If you've installed via other means, you may need add the completion to your completion directory\n\t\t    kubetunnel completion bash > $(brew --prefix)/etc/bash_completion.d/kubetunnel\n\n\n\t\t# Installing bash completion on Linux\n\t\t## If bash-completion is not installed on Linux, install the 'bash-completion' package\n\t\t## via your distribution's package manager.\n\t\t## Load the kubetunnel completion code for bash into the current shell\n\t\t    source <(kubetunnel completion bash)\n\t\t## Write bash completion code to a file and source it from .bash_profile\n\t\t    kubetunnel completion bash > ~/.kube/completion.bash.inc\n\t\t    printf \"\n\t\t      # kubetunnel shell completion\n\t\t      source '$HOME/.kube/completion.bash.inc'\n\t\t      \" >> $HOME/.bash_profile\n\t\t    source $HOME/.bash_profile\n\n\t\t# Load the kubetunnel completion code for zsh[1] into the current shell\n\t\t    source <(kubetunnel completion zsh)\n\t\t# Set the kubetunnel completion code for zsh[1] to autoload on startup\n\t\t    kubetunnel completion zsh > \"${fpath[1]}/_kubetunnel\"\n\n\n\t\t# Load the kubetunnel completion code for fish[2] into the current shell\n\t\t    kubetunnel completion fish | source\n\t\t# To load completions for each session, execute once: \n\t\t    kubetunnel completion fish > ~/.config/fish/completions/kubetunnel.fish\n\n\t\t# Load the kubetunnel completion code for powershell into the current shell\n\t\t    kubetunnel completion powershell | Out-String | Invoke-Expression\n\t\t# Set kubetunnel completion code for powershell to run on startup\n\t\t## Save completion code to a script and execute in the profile\n\t\t    kubetunnel completion powershell > $HOME\\.kube\\completion.ps1\n\t\t    Add-Content $PROFILE \"$HOME\\.kube\\completion.ps1\"\n\t\t## Execute completion code in the profile\n\t\t    Add-Content $PROFILE \"if (Get-Command kubetunnel -ErrorAction SilentlyContinue) {\n\t\t        kubetunnel completion powershell | Out-String | Invoke-Expression\n\t\t    }\"\n\t\t## Add completion code directly to the $PROFILE script\n\t\t    kubetunnel completion powershell >> $PROFILE`))\n)\n\nvar (\n\tcompletionShells = map[string]func(out io.Writer, boilerPlate string, cmd *cobra.Command) error{\n\t\t\"bash\":       runCompletionBash,\n\t\t\"zsh\":        runCompletionZsh,\n\t\t\"fish\":       runCompletionFish,\n\t\t\"powershell\": runCompletionPwsh,\n\t}\n)\n\n// NewCmdCompletion creates the `completion` command\nfunc NewCmdCompletion(out io.Writer, boilerPlate string) *cobra.Command {\n\tvar shells []string\n\tfor s := range completionShells {\n\t\tshells = append(shells, s)\n\t}\n\n\tcmd := &cobra.Command{\n\t\tUse:                   \"completion SHELL\",\n\t\tDisableFlagsInUseLine: true,\n\t\tShort:                 i18n.T(\"Output shell completion code for the specified shell (bash, zsh, fish or powershell)\"),\n\t\tLong:                  completionLong,\n\t\tExample:               completionExample,\n\t\tRun: func(cmd *cobra.Command, args []string) {\n\t\t\tcmdutil.CheckErr(RunCompletion(out, boilerPlate, cmd, args))\n\t\t},\n\t\tValidArgs: shells,\n\t}\n\n\treturn cmd\n}\n\n// RunCompletion checks given arguments and executes command\nfunc RunCompletion(out io.Writer, boilerPlate string, cmd *cobra.Command, args []string) error {\n\tif len(args) == 0 {\n\t\treturn cmdutil.UsageErrorf(cmd, \"Shell not specified.\")\n\t}\n\tif len(args) > 1 {\n\t\treturn cmdutil.UsageErrorf(cmd, \"Too many arguments. Expected only the shell type.\")\n\t}\n\trun, found := completionShells[args[0]]\n\tif !found {\n\t\treturn cmdutil.UsageErrorf(cmd, \"Unsupported shell type %q.\", args[0])\n\t}\n\n\treturn run(out, boilerPlate, cmd.Parent())\n}\n\nfunc runCompletionBash(out io.Writer, boilerPlate string, kubectl *cobra.Command) error {\n\tif len(boilerPlate) == 0 {\n\t\tboilerPlate = defaultBoilerPlate\n\t}\n\tif _, err := out.Write([]byte(boilerPlate)); err != nil {\n\t\treturn err\n\t}\n\n\treturn kubectl.GenBashCompletion(out)\n}\n\nfunc runCompletionZsh(out io.Writer, boilerPlate string, kubectl *cobra.Command) error {\n\tzshHead := fmt.Sprintf(\"#compdef %[1]s\\ncompdef _%[1]s %[1]s\\n\", kubectl.Name())\n\tout.Write([]byte(zshHead))\n\n\tif len(boilerPlate) == 0 {\n\t\tboilerPlate = defaultBoilerPlate\n\t}\n\tif _, err := out.Write([]byte(boilerPlate)); err != nil {\n\t\treturn err\n\t}\n\n\treturn kubectl.GenZshCompletion(out)\n}\n\nfunc runCompletionFish(out io.Writer, boilerPlate string, kubectl *cobra.Command) error {\n\tif len(boilerPlate) == 0 {\n\t\tboilerPlate = defaultBoilerPlate\n\t}\n\tif _, err := out.Write([]byte(boilerPlate)); err != nil {\n\t\treturn err\n\t}\n\n\treturn kubectl.GenFishCompletion(out, true)\n}\n\nfunc runCompletionPwsh(out io.Writer, boilerPlate string, kubectl *cobra.Command) error {\n\tif len(boilerPlate) == 0 {\n\t\tboilerPlate = defaultBoilerPlate\n\t}\n\n\tif _, err := out.Write([]byte(boilerPlate)); err != nil {\n\t\treturn err\n\t}\n\n\treturn kubectl.GenPowerShellCompletionWithDesc(out)\n}\n"
  },
  {
    "path": "cmd/cli/kubetunnel.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"github.com/spf13/cobra\"\n\t\"github.com/we-dcode/kube-tunnel/cmd/cli/cmds\"\n\t\"github.com/we-dcode/kube-tunnel/pkg\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/constants\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/utils/logutil\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"regexp\"\n\n\tlog \"github.com/sirupsen/logrus\"\n)\n\nvar globalUsage = ``\nvar Version = \"0.0.0\"\nvar OperatorVersion = \"0.0.0\"\n\nfunc init() {\n\t// quiet version\n\targs := os.Args[1:]\n\tif len(args) == 2 && args[0] == \"version\" && args[1] == \"quiet\" {\n\t\tfmt.Println(Version)\n\t\tos.Exit(0)\n\t}\n\n\tlog.SetOutput(&logutil.LogOutputSplitter{})\n\tif len(args) > 0 && args[0] == \"completion\" {\n\t\tlog.SetOutput(ioutil.Discard)\n\t}\n}\n\nfunc main() {\n\n\tlog.SetLevel(log.InfoLevel)\n\tlog.SetFormatter(&log.TextFormatter{\n\t\tFullTimestamp:   true,\n\t\tForceColors:     true,\n\t\tTimestampFormat: \"15:04:05\",\n\t})\n\n\t//log.Print(\"\")\n\t//log.Print(\"https://github.com/we-dcode/kube-tunnel\")\n\t//log.Print(\"https://dcode.tech\")\n\t//log.Print(\"\")\n\n\tcmd := NewRootCmd()\n\n\tif err := cmd.Execute(); err != nil {\n\t\tos.Exit(1)\n\t}\n}\n\nfunc NewRootCmd() *cobra.Command {\n\trootCmd := &cobra.Command{\n\t\tUse:   constants.KubetunnelSlug,\n\t\tShort: \"Duplex interaction with K8s cluster.\",\n\t\tLong:  \"\\\"Deploy\\\" local service to running Kubernetes cluster and allow duplex interaction.\",\n\t}\n\n\trootCmd.AddCommand(NewInstallKubeTunnelCmd())\n\trootCmd.AddCommand(NewCreateTunnelCmd())\n\trootCmd.AddCommand(NewVersionCmd())\n\trootCmd.AddCommand(cmds.NewCmdCompletion(os.Stdout, \"\"))\n\t//rootCmd.SetHelpCommand()\n\n\treturn rootCmd\n}\n\nfunc NewVersionCmd() *cobra.Command {\n\tversionCmd := &cobra.Command{\n\t\tUse:   \"version\",\n\t\tShort: fmt.Sprintf(\"Print the version of %s\", constants.KubetunnelSlug),\n\t\tLong:  ``,\n\t\tRun: func(cmd *cobra.Command, args []string) {\n\t\t\tfmt.Printf(\"%s version: %s\\nhttps://github.com/we-dcode/kube-tunnel\\n\", constants.KubetunnelSlug, Version)\n\t\t},\n\t}\n\n\treturn versionCmd\n}\n\nfunc NewInstallKubeTunnelCmd() *cobra.Command {\n\n\tvar kubeConfig, namespace, kubetunnelVersion string\n\n\tsvcCmd := &cobra.Command{\n\t\tUse:   \"install\",\n\t\tShort: \"Install kubetunnel operator to k8s cluster.\",\n\t\tExample: fmt.Sprintf(\"  %s install --help\\n\", constants.KubetunnelSlug) +\n\t\t\tfmt.Sprintf(\"  %s install\\n\", constants.KubetunnelSlug) +\n\t\t\tfmt.Sprintf(\"  %s install -c kubeconfig/path\\n\", constants.KubetunnelSlug) +\n\t\t\tfmt.Sprintf(\"  %s install -c kubeconfig/path --operator-version %s\\n\", constants.KubetunnelSlug, OperatorVersion),\n\n\t\t// TODO: Consider change to RunE and modify all panic to return error\n\t\tRun: func(cmd *cobra.Command, args []string) {\n\n\t\t\tkubeTunnel := pkg.MustNewKubeTunnel(kubeConfig, namespace, false)\n\n\t\t\tkubeTunnel.Install(kubetunnelVersion)\n\t\t},\n\t}\n\n\tsvcCmd.Flags().StringVarP(&kubeConfig, \"kubeconfig\", \"c\", \"\", \"absolute path to a kubectl config file.\")\n\tsvcCmd.Flags().StringVar(&kubetunnelVersion, \"operator-version\", OperatorVersion, fmt.Sprintf(\"%s's Operator chart version.\", constants.KubeTunnelKind))\n\tsvcCmd.Flags().StringVarP(&namespace, \"namespace\", \"n\", constants.KubetunnelSlug, \"operator's namespace\")\n\n\treturn svcCmd\n}\n\nfunc NewCreateTunnelCmd() *cobra.Command {\n\n\tvar kubeConfig, kubetunnelVersion, localIp, namespace, port string\n\n\tsvcCmd := &cobra.Command{\n\t\tUse:   \"create-tunnel\",\n\t\tShort: \"Duplex interaction with K8s cluster.\",\n\t\tArgs:  cobra.ExactArgs(1),\n\t\tExample: fmt.Sprintf(\"  sudo -E %s create-tunnel --help\\n\", constants.KubetunnelSlug) +\n\t\t\tfmt.Sprintf(\"  sudo -E %s create-tunnel -p '8080:80' svc_name\\n\", constants.KubetunnelSlug) +\n\t\t\tfmt.Sprintf(\"  sudo -E %s create-tunnel -c kubeconfig/path -p '8080:80' svc_name\\n\", constants.KubetunnelSlug) +\n\t\t\tfmt.Sprintf(\"  sudo -E %s create-tunnel -c kubeconfig/path -n namespace -p '8080:80' svc_name\\n\", constants.KubetunnelSlug),\n\t\t//ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {\n\t\t//\n\t\t//\tlog.SetLevel(log.PanicLevel)\n\t\t//\n\t\t//\tk := kube.MustNew(kubeConfig, namespace)\n\t\t//\n\t\t//\tserviceNames, _ := k.ListServiceNamesWithoutKubeTunnel()\n\t\t//\n\t\t//\treturn serviceNames, cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveNoFileComp\n\t\t//},\n\t\t// TODO: Consider change to RunE and modify all panic to return error\n\t\tRun: func(cmd *cobra.Command, args []string) {\n\n\t\t\t// TODO: Validate kubetunnel is installed and return error if not\n\n\t\t\tportForwardRegex := regexp.MustCompile(`^(?P<local>[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]):(?P<remote>[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$`)\n\n\t\t\tif portForwardRegex.MatchString(port) == false {\n\n\t\t\t\tlog.Panicf(\"port: '%s' is invalid. expected format example: '8080:80'\", port)\n\t\t\t}\n\n\t\t\tmatches := portForwardRegex.FindStringSubmatch(port)\n\t\t\tlocalIndex := portForwardRegex.SubexpIndex(\"local\")\n\t\t\tremoteIndex := portForwardRegex.SubexpIndex(\"remote\")\n\n\t\t\tkubeTunnel := pkg.MustNewKubeTunnel(kubeConfig, namespace, true)\n\n\t\t\tkubeTunnel.CreateTunnel(pkg.KubeTunnelConf{\n\t\t\t\tServiceName: args[0],\n\t\t\t\tKubeTunnelPortMap: map[string]string{\n\t\t\t\t\tmatches[localIndex]: matches[remoteIndex],\n\t\t\t\t},\n\t\t\t\tLocalIP: localIp,\n\t\t\t})\n\n\t\t},\n\t}\n\n\tsvcCmd.Flags().StringVarP(&kubeConfig, \"kubeconfig\", \"c\", \"\", \"absolute path to a kubectl config file.\")\n\tsvcCmd.Flags().StringVar(&kubetunnelVersion, \"operator-version\", Version, fmt.Sprintf(\"%s's Operator chart version.\", constants.KubeTunnelKind))\n\tsvcCmd.Flags().StringVar(&localIp, \"local-ip\", \"127.0.0.1\", \"local service binding ip, usually localhost.\")\n\n\tsvcCmd.Flags().StringVarP(&namespace, \"namespace\", \"n\", \"\", \"specify namespace, default: taken from kubeconfig's context.\")\n\n\t// TODO: Change port to []string and allow multi -p ...\n\tsvcCmd.Flags().StringVarP(&port, \"port\", \"p\", \"\", \"localPort:remotePort (example: 8080:80).\")\n\tsvcCmd.MarkFlagRequired(\"port\")\n\n\treturn svcCmd\n}\n"
  },
  {
    "path": "cmd/operator/main.go",
    "content": "/*\nCopyright 2022.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage main\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"github.com/gin-gonic/gin\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/clients/kube\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/constants\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\t\"os\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/operator-framework/helm-operator-plugins/pkg/annotation\"\n\t\"github.com/operator-framework/helm-operator-plugins/pkg/reconciler\"\n\t\"github.com/operator-framework/helm-operator-plugins/pkg/watches\"\n\tctrlruntime \"k8s.io/apimachinery/pkg/runtime\"\n\tutilruntime \"k8s.io/apimachinery/pkg/util/runtime\"\n\tclientgoscheme \"k8s.io/client-go/kubernetes/scheme\"\n\t_ \"k8s.io/client-go/plugin/pkg/client/auth\"\n\tctrl \"sigs.k8s.io/controller-runtime\"\n\t\"sigs.k8s.io/controller-runtime/pkg/healthz\"\n\t\"sigs.k8s.io/controller-runtime/pkg/log/zap\"\n\t//+kubebuilder:scaffold:imports\n)\n\nvar (\n\tscheme                         = ctrlruntime.NewScheme()\n\tsetupLog                       = ctrl.Log.WithName(\"setup\")\n\tdefaultMaxConcurrentReconciles = runtime.NumCPU()\n\tdefaultReconcilePeriod         = time.Minute\n)\n\ntype ServiceReq struct {\n\tName        string\n\tNamespace   string\n\tClient      string\n\tIsConnected string\n}\n\nfunc init() {\n\tutilruntime.Must(clientgoscheme.AddToScheme(scheme))\n\n\t//+kubebuilder:scaffold:scheme\n}\n\nfunc main() {\n\tvar (\n\t\tmetricsAddr          string\n\t\tleaderElectionID     string\n\t\twatchesPath          string\n\t\tprobeAddr            string\n\t\tenableLeaderElection bool\n\t)\n\n\tsetupLog.Info(\"Starting Gin server..\")\n\tgo startGin()\n\n\t// #### Manager pod configuration\n\n\tflag.StringVar(&metricsAddr, \"metrics-bind-address\", \":8080\", \"The address the metric endpoint binds to.\")\n\tflag.StringVar(&probeAddr, \"health-probe-bind-address\", \":8081\", \"The address the probe endpoint binds to.\")\n\tflag.StringVar(&watchesPath, \"watches-file\", \"watches.yaml\", \"path to watches file\")\n\tflag.StringVar(&leaderElectionID, \"leader-election-id\", \"5dbd2493.dcode.tech\", \"provide leader election\")\n\tflag.BoolVar(&enableLeaderElection, \"leader-elect\", false,\n\t\t\"Enable leader election for controller manager. \"+\n\t\t\t\"Enabling this will ensure there is only one active controller manager.\")\n\topts := zap.Options{\n\t\tDevelopment: true,\n\t}\n\topts.BindFlags(flag.CommandLine)\n\tflag.Parse()\n\n\tctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))\n\n\tmgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{\n\t\tScheme:                 scheme,\n\t\tMetricsBindAddress:     metricsAddr,\n\t\tPort:                   9443,\n\t\tHealthProbeBindAddress: probeAddr,\n\t\tLeaderElection:         enableLeaderElection,\n\t\tLeaderElectionID:       leaderElectionID,\n\t})\n\tif err != nil {\n\t\tsetupLog.Error(err, \"unable to start manager\")\n\t\tos.Exit(1)\n\t}\n\n\t//+kubebuilder:scaffold:builder\n\n\tif err := mgr.AddHealthzCheck(\"healthz\", healthz.Ping); err != nil {\n\t\tsetupLog.Error(err, \"unable to set up health check\")\n\t\tos.Exit(1)\n\t}\n\tif err := mgr.AddReadyzCheck(\"readyz\", healthz.Ping); err != nil {\n\t\tsetupLog.Error(err, \"unable to set up ready check\")\n\t\tos.Exit(1)\n\t}\n\n\tws, err := watches.Load(watchesPath)\n\tif err != nil {\n\t\tsetupLog.Error(err, \"Failed to create new manager factories\")\n\t\tos.Exit(1)\n\t}\n\n\tfor _, w := range ws {\n\t\t// Register controller with the factory\n\t\treconcilePeriod := defaultReconcilePeriod\n\t\tif w.ReconcilePeriod != nil {\n\t\t\treconcilePeriod = w.ReconcilePeriod.Duration\n\t\t}\n\n\t\tmaxConcurrentReconciles := defaultMaxConcurrentReconciles\n\t\tif w.MaxConcurrentReconciles != nil {\n\t\t\tmaxConcurrentReconciles = *w.MaxConcurrentReconciles\n\t\t}\n\n\t\t// Setup manager with Helm API\n\n\t\tw.OverrideValues = map[string]string{}\n\t\tw.OverrideValues[\"operator.namespace\"] = getEnvVar(\"POD_NAMESPACE\")\n\t\tw.OverrideValues[\"operator.service.port\"] = getEnvVar(\"SERVICE_PORT\")\n\t\tw.OverrideValues[\"operator.service.name\"] = getEnvVar(\"SERVICE_NAME\")\n\t\tfmt.Printf(\"Values: %+v\", w.OverrideValues)\n\n\t\tr, err := reconciler.New(\n\t\t\treconciler.WithChart(*w.Chart),\n\t\t\treconciler.WithGroupVersionKind(w.GroupVersionKind),\n\t\t\treconciler.WithOverrideValues(w.OverrideValues),\n\t\t\treconciler.SkipDependentWatches(w.WatchDependentResources != nil && !*w.WatchDependentResources),\n\t\t\treconciler.WithMaxConcurrentReconciles(maxConcurrentReconciles),\n\t\t\treconciler.WithReconcilePeriod(reconcilePeriod),\n\t\t\treconciler.WithInstallAnnotations(annotation.DefaultInstallAnnotations...),\n\t\t\treconciler.WithUpgradeAnnotations(annotation.DefaultUpgradeAnnotations...),\n\t\t\treconciler.WithUninstallAnnotations(annotation.DefaultUninstallAnnotations...),\n\t\t)\n\t\tif err != nil {\n\t\t\tsetupLog.Error(err, \"unable to create helm reconciler\", \"controller\", \"Helm\")\n\t\t\tos.Exit(1)\n\t\t}\n\n\t\t// The SetupWithManager method is called when the operator starts.\n\t\t// It serves to tell the operator framework what types our PodReconciler\n\t\t// needs to watch. To use the same Pod type used by Kubernetes internally,\n\t\t// we need to import some of its code. All of the Kubernetes source code is\n\t\t// open source, so you can import any part you like in your own Go code. You can\n\t\t// find a complete list of available packages in the Kubernetes source code or here\n\t\t// on pkg.go.dev. To use pods, we need the k8s.io/api/core/v1 package.\n\t\tif err := r.SetupWithManager(mgr); err != nil {\n\n\t\t\tsetupLog.Error(err, \"unable to create controller\", \"controller\", \"Helm\")\n\t\t\tos.Exit(1)\n\t\t}\n\t\tsetupLog.Info(\"configured watch\", \"gvk\", w.GroupVersionKind, \"chartPath\", w.ChartPath, \"maxConcurrentReconciles\", maxConcurrentReconciles, \"reconcilePeriod\", reconcilePeriod)\n\t}\n\n\tsetupLog.Info(\"starting manager\")\n\tif err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {\n\t\tsetupLog.Error(err, \"problem running manager\")\n\t\tos.Exit(1)\n\t}\n}\n\nfunc startGin() {\n\tsetupLog.Info(\"Inside Gin function..\")\n\trouter := gin.Default()\n\trouter.POST(\"/service\", serviceHandler)\n\n\trouter.Run(\"0.0.0.0:8083\")\n\tsetupLog.Info(\"Started Gin Server on port 8083..\")\n}\n\nfunc serviceHandler(c *gin.Context) {\n\tvar req ServiceReq\n\tc.BindJSON(&req)\n\tc.JSON(200, req)\n\n\tkube := connectToKubernetes(req.Namespace) // TODO: change this one\n\tisConnected, err := strconv.ParseBool(req.IsConnected)\n\tif err != nil {\n\t\tfmt.Errorf(err.Error())\n\t}\n\terror := patchServiceWithLabel(kube, req.Name, isConnected)\n\tif error != nil {\n\t\tfmt.Errorf(\"error %v\", err)\n\t} else {\n\t\tfmt.Print(\"No error!\")\n\t}\n\n}\n\nfunc connectToKubernetes(namespace string) *kube.Kube {\n\n\tkubeClient := kube.MustNew(\"\", namespace)\n\n\terr := kubeClient.ConnectivityCheck()\n\tif err != nil {\n\t\tfmt.Printf(err.Error())\n\t}\n\n\treturn kubeClient\n}\n\nfunc patchServiceWithLabel(k *kube.Kube, serviceName string, connected bool) error {\n\n\tsvcContext, err := k.GetServiceContext(serviceName)\n\tif err != nil {\n\t\tlog.Errorf(\"fail to get service: '%s' context, error: %s\", serviceName, err.Error())\n\t}\n\n\tclientSet := k.InnerKubeClient\n\tlog.Debugf(k.Namespace)\n\tctx := context.TODO()\n\n\t//slugPrefix := fmt.Sprintf(\"%s-\", constants.KubetunnelSlug)\n\n\t// TODO: Check if service needs to be updated...\n\n\tif connected == false {\n\n\t\tlog.Debugf(\"removing true from %v\\n\", serviceName)\n\t\tvar payload []kube.PatchOperation\n\n\t\tif _, exists := svcContext.LabelSelector[constants.KubetunnelSlug]; exists == false {\n\t\t\treturn nil\n\t\t}\n\n\t\tpayload = append(payload, kube.PatchOperation{\n\n\t\t\tOp:    \"remove\",\n\t\t\tPath:  fmt.Sprintf(\"/spec/selector/%s\", constants.KubetunnelSlug),\n\t\t\tValue: serviceName,\n\t\t})\n\t\t//\n\t\t//for key, valueWithSlug := range svcContext.LabelSelector {\n\t\t//\n\t\t//\tif strings.EqualFold(key, constants.KubetunnelSlug) {\n\t\t//\t\tcontinue\n\t\t//\t}\n\t\t//\n\t\t//\tslugAlreadyRemoved := strings.Contains(valueWithSlug, constants.KubetunnelSlug) == false\n\t\t//\tif slugAlreadyRemoved {\n\t\t//\t\tcontinue\n\t\t//\t}\n\t\t//\n\t\t//\tvalueWithoutSlug := strings.Replace(valueWithSlug, slugPrefix, \"\", 1)\n\t\t//\n\t\t//\tpayload = append(payload, kube.PatchOperation{\n\t\t//\n\t\t//\t\tOp:    \"replace\",\n\t\t//\t\tPath:  fmt.Sprintf(\"/spec/selector/%s\", strings.ReplaceAll(key, \"/\", \"~1\")),\n\t\t//\t\tValue: valueWithoutSlug,\n\t\t//\t})\n\t\t//}\n\n\t\tif len(payload) > 0 {\n\t\t\tpayloadBytes, _ := json.Marshal(payload)\n\t\t\t_, err := clientSet.\n\t\t\t\tCoreV1().\n\t\t\t\tServices(k.Namespace).\n\t\t\t\tPatch(ctx, serviceName, types.JSONPatchType, payloadBytes, metav1.PatchOptions{})\n\t\t\treturn err\n\t\t}\n\n\t} else {\n\t\tlog.Debugf(\"adding true to %v\\n\", serviceName)\n\n\t\tvar payload []kube.PatchOperation\n\n\t\tif _, exists := svcContext.LabelSelector[constants.KubetunnelSlug]; exists {\n\t\t\treturn nil\n\t\t}\n\n\t\tpayload = append(payload, kube.PatchOperation{\n\n\t\t\tOp:    \"replace\",\n\t\t\tPath:  fmt.Sprintf(\"/spec/selector/%s\", constants.KubetunnelSlug),\n\t\t\tValue: serviceName,\n\t\t})\n\n\t\t//for key, valueWithoutSlug := range svcContext.LabelSelector {\n\t\t//\n\t\t//\tif strings.EqualFold(key, constants.KubetunnelSlug) {\n\t\t//\t\tcontinue\n\t\t//\t}\n\t\t//\n\t\t//\talreadyContainSlug := strings.Contains(valueWithoutSlug, constants.KubetunnelSlug)\n\t\t//\n\t\t//\tif alreadyContainSlug {\n\t\t//\t\tcontinue\n\t\t//\t}\n\t\t//\n\t\t//\tvalueWithSlug := fmt.Sprintf(\"%s%s\", slugPrefix, valueWithoutSlug)\n\t\t//\n\t\t//\tpayload = append(payload, kube.PatchOperation{\n\t\t//\n\t\t//\t\tOp:    \"replace\",\n\t\t//\t\tPath:  fmt.Sprintf(\"/spec/selector/%s\", strings.ReplaceAll(key, \"/\", \"~1\")),\n\t\t//\t\tValue: valueWithSlug,\n\t\t//\t})\n\t\t//}\n\t\tif len(payload) > 0 {\n\t\t\tpayloadBytes, _ := json.Marshal(payload)\n\t\t\t_, err := clientSet.\n\t\t\t\tCoreV1().\n\t\t\t\tServices(k.Namespace).\n\t\t\t\tPatch(ctx, serviceName, types.JSONPatchType, payloadBytes, metav1.PatchOptions{})\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n\n}\n\nfunc getEnvVar(variable string) string {\n\tenvVar, ok := os.LookupEnv(variable)\n\tif !ok {\n\t\tfmt.Errorf(\"%v is not a present env variable\", variable)\n\t}\n\treturn envVar\n}\n"
  },
  {
    "path": "cmd/operator/main_test.go",
    "content": "package main\n\nimport (\n\t\"gotest.tools/v3/assert\"\n\t\"testing\"\n)\n\nfunc TestPatchServiceWithLabel(t *testing.T) {\n\n\tkube := connectToKubernetes(\"kubetunnel\") // TODO: change this one\n\n\terr := patchServiceWithLabel(kube, \"nginx\", false)\n\n\tassert.NilError(t, err)\n}\n"
  },
  {
    "path": "cmd/server/kubetunnel-server.go",
    "content": "package main\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/robfig/cron/v3\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/utils/logutil\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/utils/tcputil\"\n\t_ \"k8s.io/client-go/plugin/pkg/client/auth\"\n\t\"net/http\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n)\n\nvar (\n\tkubeContext = \"\"\n\n\tisConnected = false\n\n\thostname = \"127.0.0.1\"\n)\n\nfunc main() {\n\n\tlog.SetLevel(log.DebugLevel)\n\tlog.SetFormatter(&log.TextFormatter{\n\t\tFullTimestamp:   true,\n\t\tForceColors:     true,\n\t\tTimestampFormat: \"15:04:05\",\n\t})\n\tlog.SetOutput(&logutil.LogOutputSplitter{})\n\tlog.Print(\"\")\n\tlog.Print(\"https://github.com/we-dcode/kube-tunnel\")\n\tlog.Print(\"https://we.dcode.tech\")\n\tlog.Print(\"\")\n\n\tstartJob()\n\tstartGin()\n\n}\n\nfunc startJob() {\n\tjob := cron.New()\n\tjob.AddFunc(\"@every 1s\", func() {\n\t\tportChecker()\n\t})\n\tjob.Start()\n}\n\nfunc startGin() {\n\trouter := gin.Default()\n\trouter.GET(\"/health\", healthHandler)\n\n\trouter.Run(\"0.0.0.0:8080\")\n}\n\nfunc portChecker() {\n\n\tlog.Debugf(\"Starting portChecker.. \")\n\n\tportArr := strings.Split(getEnvVar(\"PORTS\"), \",\")\n\tserviceName := getEnvVar(\"SERVICE_NAME\")\n\tpodNamespace := getEnvVar(\"POD_NAMESPACE\")\n\toperatorSvcName := getEnvVar(\"OPERATOR_SVC_NAME\")\n\toperatorNamespace := getEnvVar(\"OPERATOR_NAMESPACE\")\n\toperatorPort := getEnvVar(\"OPERATOR_PORT\")\n\n\tlog.Debugf(\"ports are %v\", portArr)\n\n\tfor _, port := range portArr {\n\t\tif tcputil.IsAvailable(hostname, port) == false {\n\t\t\tlog.Debugf(\"port %v is unavailable on host\", port)\n\n\t\t\tif isConnected != false {\n\t\t\t\terror := patchService(\n\t\t\t\t\tpodNamespace, serviceName, false, operatorSvcName,\n\t\t\t\t\toperatorNamespace, operatorPort)\n\t\t\t\tif error != nil {\n\t\t\t\t\tlog.Debugf(\"error %v\", error)\n\t\t\t\t} else {\n\t\t\t\t\tisConnected = false\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn\n\t\t}\n\t}\n\n\t//  patch\n\tlog.Debugf(\"labeling service %v to %v\\n\", serviceName, true)\n\tif isConnected != true {\n\t\terror := patchService(\n\t\t\tpodNamespace, serviceName,\n\t\t\ttrue, operatorSvcName,\n\t\t\toperatorNamespace, operatorPort)\n\t\tif error != nil {\n\t\t\tlog.Debugf(\"error %v\", error)\n\t\t} else {\n\t\t\tisConnected = true\n\t\t}\n\t}\n\n}\n\nfunc healthHandler(c *gin.Context) {\n\tif isConnected {\n\t\tc.IndentedJSON(http.StatusOK, isConnected)\n\t} else {\n\t\tc.IndentedJSON(http.StatusServiceUnavailable, isConnected)\n\n\t}\n}\n\nfunc patchService(namespace string, serviceName string, isConnected bool, operatorSvcName string, operatorNamespace string, operatorSvcPort string) error {\n\tvalues := map[string]string{\"Namespace\": namespace,\n\t\t\"Name\":        serviceName,\n\t\t\"IsConnected\": strconv.FormatBool(isConnected)}\n\tjsonData, err := json.Marshal(values)\n\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tresp, err := http.Post(fmt.Sprintf(\n\t\t\"http://%s.%s.svc.cluster.local:%s/service\", operatorSvcName, operatorNamespace, operatorSvcPort),\n\t\t\"application/json\",\n\t\tbytes.NewBuffer(jsonData))\n\tif err != nil {\n\t\treturn err\n\t}\n\tlog.Printf(\"Response: %s\", resp)\n\treturn nil\n\n}\nfunc getEnvVar(variable string) string {\n\tenvVar, ok := os.LookupEnv(variable)\n\tif !ok {\n\t\tlog.Errorf(\"%v is not a present env variable\", variable)\n\t}\n\treturn envVar\n}\n"
  },
  {
    "path": "docs/Architecture.md",
    "content": "# KubeTunnel Architecture\n\nKubeTunnel uses a Kubernetes Operator, KubeTunnel CustomResources and a local CLI to forward traffic to and from your local workstation and the cluster. \n\nThe **operator** pod is composed of two different components:\n\n1. A manager component that handles the KubeTunnel Custom Resources and deployments. \n2. A REST API that handles requests from the KubeTunnel deployments to patch the application services. This API will change the application service's labelSelectors to move traffic to the original application or to the tunnel depending on the connection of the tunnel to your station. This ensures that if your local process is down or that the KubeTunnel CRD still exists in the cluster but you aren't using KubeTunnel currently the service returns to forward traffic to the original application pod.\n\nEach **KubeTunnel server** is composed of a deployment with the following components:\n\n1. An FRP Server container that includes configuration from the KubeTunnel CLI.\n2. A KubeTunnel Go server that checks that the FRP Server is connected to your local process. If it is connected, it sends a request to the operator to change the Kubernetes service's labelSelector to it, and if not, it sends the request to change the labelSelector back to the original pod.\n\nThe **KubeTunnel CLI** achieves the two way connection by doing the following:\n\nFrom you to the cluster:\n1. Forwards all the cluster services to your local station and modifies your `hosts` file.\n\n\nFrom the cluster to you:\n1. Creates a KubeTunnel CR which includes the tunnel from the local process to the cluster.\n2. Changes the application's service labelSelectors to point to this tunnel, \"stealing\" the traffic from the Kubernetes deployment and moving it to your process.\n\n## Architecture Diagram\n\n<p align=\"center\">\n<img src=\"../assets/Architecture-extended.png\" width=\"800\"><br>\n</p>\n\n"
  },
  {
    "path": "docs/Network.md",
    "content": "# KubeTunnel Networking\n\nKubeTunnel uses 3 main components to manage tunnels in your Kubernetes Cluster.\n1. The CLI installed locally.\n2. The KubeTunnel deployment that is deployed in your application's namespace.\n3. The KubeTunnel Operator deployed in it's own namespace.\n\nThe KubeTunnel deployments need access to the Operator to tell it if they are connected or disconencted to your local process. This happens through HTTP requests to the operator's REST API. This means:\n1. There needs to be Egress network open from the tunnel pods to the operator pod and namespace.\n2. There needs to be Ingress network open to the operator pod from the tunnel pods and namespaces.\n\n## Example NetworkPolicies\n\n```yaml\n\n# Egress policy - deployed on each application namespace \napiVersion: networking.k8s.io/v1\nkind: NetworkPolicy\nmetadata:\n  name: kubetunnel-np\n  namespace: <Application namespace>\nspec:\n  podSelector:\n    matchLabels:\n      we-dcode-app: kubetunnel\n  policyTypes:\n    - Egress\n  egress:\n    - to:\n      - namespaceSelector:\n          matchLabels:\n            kubernetes.io/metadata.name: <operator namespace>\n      ports:\n        - protocol: TCP\n          port: 80\n        - protocol: TCP\n          port: 8083\n---\n\n# Ingress Policy - Deployed in operator namespace\napiVersion: networking.k8s.io/v1\nkind: NetworkPolicy\nmetadata:\n  name: kubetunnel-operator-np\n  namespace: <operator namespace>\nspec:\n  podSelector:\n    matchLabels:\n      we-dcode-app: kubetunnel-operator\n  policyTypes:\n    - Ingress\n  ingress:\n  - from:\n    - namespaceSelector:\n        matchLabels:\n          kubernetes.io/metadata.name: <application namespace>\n  - from:\n    - namespaceSelector:\n        matchLabels:\n          kubernetes.io/metadata.name: <application namespace 2>\n  - from:\n    - namespaceSelector:\n        matchLabels:\n          kubernetes.io/metadata.name: <application namespace 3>\n    ports:\n      - protocol: TCP\n        port: 80\n      - protocol: TCP\n        port: 8083\n\n```\n## Architecture Diagram\n\n<p align=\"center\">\n<img src=\"../assets/Architecture-extended.png\" width=\"800\"><br>\n</p>\n\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/we-dcode/kube-tunnel\n\ngo 1.18\n\nrequire (\n\tgithub.com/BurntSushi/toml v1.0.0\n\tgithub.com/ahmetb/go-linq/v3 v3.2.0\n\tgithub.com/fatedier/frp v0.44.0\n\tgithub.com/gin-gonic/gin v1.8.1\n\tgithub.com/maordavidov/go-k8s-portforward v0.0.0-20221009144733-274c2bdf14a1\n\tgithub.com/mittwald/go-helm-client v0.11.3\n\tgithub.com/operator-framework/helm-operator-plugins v0.0.11\n\tgithub.com/robfig/cron/v3 v3.0.1\n\tgithub.com/sirupsen/logrus v1.8.1\n\tgithub.com/spf13/cobra v1.4.0\n\tgithub.com/stretchr/testify v1.8.0\n\tgithub.com/txn2/kubefwd v1.22.3\n\tgithub.com/txn2/txeh v1.3.0\n\tgotest.tools/v3 v3.0.3\n\thelm.sh/helm/v3 v3.9.1\n\tk8s.io/api v0.25.2\n\tk8s.io/apimachinery v0.25.2\n\tk8s.io/client-go v0.25.2\n\tk8s.io/kubectl v0.24.2\n\tsigs.k8s.io/controller-runtime v0.13.0\n)\n\nrequire (\n\tcloud.google.com/go v0.99.0 // indirect\n\tgithub.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect\n\tgithub.com/Azure/go-autorest v14.2.0+incompatible // indirect\n\tgithub.com/Azure/go-autorest/autorest v0.11.27 // indirect\n\tgithub.com/Azure/go-autorest/autorest/adal v0.9.20 // indirect\n\tgithub.com/Azure/go-autorest/autorest/date v0.3.0 // indirect\n\tgithub.com/Azure/go-autorest/logger v0.2.1 // indirect\n\tgithub.com/Azure/go-autorest/tracing v0.6.0 // indirect\n\tgithub.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c // indirect\n\tgithub.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd // indirect\n\tgithub.com/Masterminds/goutils v1.1.1 // indirect\n\tgithub.com/Masterminds/semver/v3 v3.1.1 // indirect\n\tgithub.com/Masterminds/sprig/v3 v3.2.2 // indirect\n\tgithub.com/Masterminds/squirrel v1.5.3 // indirect\n\tgithub.com/PuerkitoBio/purell v1.1.1 // indirect\n\tgithub.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect\n\tgithub.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 // indirect\n\tgithub.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect\n\tgithub.com/beorn7/perks v1.0.1 // indirect\n\tgithub.com/bep/debounce v1.2.0 // indirect\n\tgithub.com/cespare/xxhash/v2 v2.1.2 // indirect\n\tgithub.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect\n\tgithub.com/containerd/containerd v1.6.6 // indirect\n\tgithub.com/coreos/go-oidc v2.2.1+incompatible // indirect\n\tgithub.com/cyphar/filepath-securejoin v0.2.3 // indirect\n\tgithub.com/davecgh/go-spew v1.1.1 // indirect\n\tgithub.com/docker/cli v20.10.17+incompatible // indirect\n\tgithub.com/docker/distribution v2.8.1+incompatible // indirect\n\tgithub.com/docker/docker v20.10.17+incompatible // indirect\n\tgithub.com/docker/docker-credential-helpers v0.6.4 // indirect\n\tgithub.com/docker/go-connections v0.4.0 // indirect\n\tgithub.com/docker/go-metrics v0.0.1 // indirect\n\tgithub.com/docker/go-units v0.4.0 // indirect\n\tgithub.com/emicklei/go-restful/v3 v3.8.0 // indirect\n\tgithub.com/evanphx/json-patch v4.12.0+incompatible // indirect\n\tgithub.com/evanphx/json-patch/v5 v5.6.0 // indirect\n\tgithub.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect\n\tgithub.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb // indirect\n\tgithub.com/fatedier/golib v0.1.1-0.20220321042308-c306138b83ac // indirect\n\tgithub.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible // indirect\n\tgithub.com/fatih/color v1.13.0 // indirect\n\tgithub.com/fsnotify/fsnotify v1.5.4 // indirect\n\tgithub.com/gin-contrib/sse v0.1.0 // indirect\n\tgithub.com/go-errors/errors v1.0.1 // indirect\n\tgithub.com/go-gorp/gorp/v3 v3.0.2 // indirect\n\tgithub.com/go-logr/logr v1.2.3 // indirect\n\tgithub.com/go-logr/zapr v1.2.3 // indirect\n\tgithub.com/go-openapi/jsonpointer v0.19.5 // indirect\n\tgithub.com/go-openapi/jsonreference v0.19.5 // indirect\n\tgithub.com/go-openapi/swag v0.19.14 // indirect\n\tgithub.com/go-playground/locales v0.14.0 // indirect\n\tgithub.com/go-playground/universal-translator v0.18.0 // indirect\n\tgithub.com/go-playground/validator/v10 v10.10.0 // indirect\n\tgithub.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect\n\tgithub.com/gobwas/glob v0.2.3 // indirect\n\tgithub.com/goccy/go-json v0.9.7 // indirect\n\tgithub.com/gogo/protobuf v1.3.2 // indirect\n\tgithub.com/golang-jwt/jwt/v4 v4.2.0 // indirect\n\tgithub.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect\n\tgithub.com/golang/protobuf v1.5.2 // indirect\n\tgithub.com/golang/snappy v0.0.3 // indirect\n\tgithub.com/google/btree v1.0.1 // indirect\n\tgithub.com/google/gnostic v0.6.9 // indirect\n\tgithub.com/google/go-cmp v0.5.8 // indirect\n\tgithub.com/google/gofuzz v1.2.0 // indirect\n\tgithub.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect\n\tgithub.com/google/uuid v1.2.0 // indirect\n\tgithub.com/gorilla/mux v1.8.0 // indirect\n\tgithub.com/gosuri/uitable v0.0.4 // indirect\n\tgithub.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect\n\tgithub.com/hashicorp/yamux v0.0.0-20210707203944-259a57b3608c // indirect\n\tgithub.com/huandu/xstrings v1.3.2 // indirect\n\tgithub.com/imdario/mergo v0.3.12 // indirect\n\tgithub.com/inconshreveable/mousetrap v1.0.0 // indirect\n\tgithub.com/jmoiron/sqlx v1.3.5 // indirect\n\tgithub.com/josharian/intern v1.0.0 // indirect\n\tgithub.com/json-iterator/go v1.1.12 // indirect\n\tgithub.com/klauspost/compress v1.13.6 // indirect\n\tgithub.com/klauspost/cpuid/v2 v2.0.6 // indirect\n\tgithub.com/klauspost/reedsolomon v1.9.15 // indirect\n\tgithub.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect\n\tgithub.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect\n\tgithub.com/leodido/go-urn v1.2.1 // indirect\n\tgithub.com/lib/pq v1.10.6 // indirect\n\tgithub.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect\n\tgithub.com/mailru/easyjson v0.7.6 // indirect\n\tgithub.com/mattn/go-colorable v0.1.12 // indirect\n\tgithub.com/mattn/go-isatty v0.0.14 // indirect\n\tgithub.com/mattn/go-runewidth v0.0.9 // indirect\n\tgithub.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect\n\tgithub.com/mitchellh/copystructure v1.2.0 // indirect\n\tgithub.com/mitchellh/go-wordwrap v1.0.0 // indirect\n\tgithub.com/mitchellh/reflectwalk v1.0.2 // indirect\n\tgithub.com/moby/locker v1.0.1 // indirect\n\tgithub.com/moby/spdystream v0.2.0 // indirect\n\tgithub.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect\n\tgithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect\n\tgithub.com/modern-go/reflect2 v1.0.2 // indirect\n\tgithub.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect\n\tgithub.com/morikuni/aec v1.0.0 // indirect\n\tgithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect\n\tgithub.com/opencontainers/go-digest v1.0.0 // indirect\n\tgithub.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect\n\tgithub.com/operator-framework/operator-lib v0.11.0 // indirect\n\tgithub.com/pelletier/go-toml/v2 v2.0.1 // indirect\n\tgithub.com/peterbourgon/diskv v2.0.1+incompatible // indirect\n\tgithub.com/pires/go-proxyproto v0.6.2 // indirect\n\tgithub.com/pkg/errors v0.9.1 // indirect\n\tgithub.com/pmezard/go-difflib v1.0.0 // indirect\n\tgithub.com/pquerna/cachecontrol v0.1.0 // indirect\n\tgithub.com/prometheus/client_golang v1.12.2 // indirect\n\tgithub.com/prometheus/client_model v0.2.0 // indirect\n\tgithub.com/prometheus/common v0.32.1 // indirect\n\tgithub.com/prometheus/procfs v0.7.3 // indirect\n\tgithub.com/rubenv/sql-migrate v1.1.1 // indirect\n\tgithub.com/russross/blackfriday v1.5.2 // indirect\n\tgithub.com/sergi/go-diff v1.1.0 // indirect\n\tgithub.com/shopspring/decimal v1.2.0 // indirect\n\tgithub.com/spf13/cast v1.4.1 // indirect\n\tgithub.com/spf13/pflag v1.0.5 // indirect\n\tgithub.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect\n\tgithub.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect\n\tgithub.com/tjfoc/gmsm v1.4.1 // indirect\n\tgithub.com/ugorji/go/codec v1.2.7 // indirect\n\tgithub.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect\n\tgithub.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect\n\tgithub.com/xeipuuv/gojsonschema v1.2.0 // indirect\n\tgithub.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect\n\tgo.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect\n\tgo.uber.org/atomic v1.7.0 // indirect\n\tgo.uber.org/multierr v1.6.0 // indirect\n\tgo.uber.org/zap v1.21.0 // indirect\n\tgolang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect\n\tgolang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect\n\tgolang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect\n\tgolang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect\n\tgolang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect\n\tgolang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect\n\tgolang.org/x/text v0.3.7 // indirect\n\tgolang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect\n\tgomodules.xyz/jsonpatch/v2 v2.2.0 // indirect\n\tgoogle.golang.org/appengine v1.6.7 // indirect\n\tgoogle.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect\n\tgoogle.golang.org/grpc v1.47.0 // indirect\n\tgoogle.golang.org/protobuf v1.28.0 // indirect\n\tgopkg.in/inf.v0 v0.9.1 // indirect\n\tgopkg.in/ini.v1 v1.62.0 // indirect\n\tgopkg.in/square/go-jose.v2 v2.5.1 // indirect\n\tgopkg.in/yaml.v2 v2.4.0 // indirect\n\tgopkg.in/yaml.v3 v3.0.1 // indirect\n\tk8s.io/apiextensions-apiserver v0.25.0 // indirect\n\tk8s.io/apiserver v0.25.0 // indirect\n\tk8s.io/cli-runtime v0.24.3 // indirect\n\tk8s.io/component-base v0.25.0 // indirect\n\tk8s.io/klog/v2 v2.70.1 // indirect\n\tk8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect\n\tk8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect\n\toras.land/oras-go v1.2.0 // indirect\n\tsigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect\n\tsigs.k8s.io/kustomize/api v0.11.4 // indirect\n\tsigs.k8s.io/kustomize/kyaml v0.13.6 // indirect\n\tsigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect\n\tsigs.k8s.io/yaml v1.3.0 // indirect\n)\n\nreplace github.com/justinbarrick/go-k8s-portforward => github.com/maordavidov/go-k8s-portforward v0.0.0-20221009141743-ba4487f63bcc\n"
  },
  {
    "path": "go.sum",
    "content": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=\ncloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=\ncloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=\ncloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=\ncloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=\ncloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=\ncloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=\ncloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=\ncloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=\ncloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=\ncloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=\ncloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=\ncloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=\ncloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=\ncloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=\ncloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=\ncloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=\ncloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=\ncloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=\ncloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=\ncloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=\ncloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=\ncloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=\ncloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=\ncloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=\ncloud.google.com/go v0.99.0 h1:y/cM2iqGgGi5D5DQZl6D9STN/3dR/Vx5Mp8s752oJTY=\ncloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=\ncloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=\ncloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=\ncloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=\ncloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=\ncloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=\ncloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=\ncloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=\ncloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=\ncloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=\ncloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=\ncloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=\ncloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=\ncloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=\ncloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=\ncloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=\ncloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=\ncloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=\ncloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=\ndmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=\ngithub.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=\ngithub.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=\ngithub.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=\ngithub.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=\ngithub.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw=\ngithub.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=\ngithub.com/Azure/go-autorest/autorest v0.11.27 h1:F3R3q42aWytozkV8ihzcgMO4OA4cuqr3bNlsEuF6//A=\ngithub.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U=\ngithub.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=\ngithub.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=\ngithub.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=\ngithub.com/Azure/go-autorest/autorest/adal v0.9.20 h1:gJ3E98kMpFB1MFqQCvA1yFab8vthOeD4VlFRQULxahg=\ngithub.com/Azure/go-autorest/autorest/adal v0.9.20/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=\ngithub.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=\ngithub.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=\ngithub.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=\ngithub.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw=\ngithub.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU=\ngithub.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=\ngithub.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=\ngithub.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=\ngithub.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=\ngithub.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=\ngithub.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28=\ngithub.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=\ngithub.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=\ngithub.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU=\ngithub.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=\ngithub.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=\ngithub.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=\ngithub.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU=\ngithub.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=\ngithub.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=\ngithub.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=\ngithub.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=\ngithub.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=\ngithub.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=\ngithub.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=\ngithub.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=\ngithub.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8=\ngithub.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=\ngithub.com/Masterminds/squirrel v1.5.3 h1:YPpoceAcxuzIljlr5iWpNKaql7hLeG1KLSrhvdHpkZc=\ngithub.com/Masterminds/squirrel v1.5.3/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10=\ngithub.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY=\ngithub.com/Microsoft/hcsshim v0.9.3 h1:k371PzBuRrz2b+ebGuI2nVgVhgsVX60jMfSw80NECxo=\ngithub.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=\ngithub.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=\ngithub.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=\ngithub.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=\ngithub.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=\ngithub.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=\ngithub.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs=\ngithub.com/ahmetb/go-linq/v3 v3.2.0 h1:BEuMfp+b59io8g5wYzNoFe9pWPalRklhlhbiU3hYZDE=\ngithub.com/ahmetb/go-linq/v3 v3.2.0/go.mod h1:haQ3JfOeWK8HpVxMtHHEMPVgBKiYyQ+f1/kLZh/cj9U=\ngithub.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=\ngithub.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=\ngithub.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=\ngithub.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=\ngithub.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=\ngithub.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=\ngithub.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=\ngithub.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=\ngithub.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=\ngithub.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=\ngithub.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=\ngithub.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=\ngithub.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=\ngithub.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY=\ngithub.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=\ngithub.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=\ngithub.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=\ngithub.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=\ngithub.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=\ngithub.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=\ngithub.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=\ngithub.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=\ngithub.com/bep/debounce v1.2.0 h1:wXds8Kq8qRfwAOpAxHrJDbCXgC5aHSzgQb/0gKsHQqo=\ngithub.com/bep/debounce v1.2.0/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=\ngithub.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=\ngithub.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=\ngithub.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=\ngithub.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=\ngithub.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70=\ngithub.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=\ngithub.com/bugsnag/bugsnag-go v1.5.3 h1:yeRUT3mUE13jL1tGwvoQsKdVbAsQx9AJ+fqahKveP04=\ngithub.com/bugsnag/panicwrap v1.2.0 h1:OzrKrRvXis8qEvOkfcxNcYbOd2O7xXS2nnKMEMABFQA=\ngithub.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=\ngithub.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=\ngithub.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=\ngithub.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=\ngithub.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=\ngithub.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 h1:7aWHqerlJ41y6FOsEUvknqgXnGmJyJSbjhAWq5pO4F8=\ngithub.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=\ngithub.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=\ngithub.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=\ngithub.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=\ngithub.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=\ngithub.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=\ngithub.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=\ngithub.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=\ngithub.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=\ngithub.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=\ngithub.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=\ngithub.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=\ngithub.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=\ngithub.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4=\ngithub.com/containerd/containerd v1.6.6 h1:xJNPhbrmz8xAMDNoVjHy9YHtWwEQNS+CDkcIRh7t8Y0=\ngithub.com/containerd/containerd v1.6.6/go.mod h1:ZoP1geJldzCVY3Tonoz7b1IXk8rIX0Nltt5QE4OMNk0=\ngithub.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=\ngithub.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=\ngithub.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=\ngithub.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=\ngithub.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk=\ngithub.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=\ngithub.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=\ngithub.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=\ngithub.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=\ngithub.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=\ngithub.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=\ngithub.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=\ngithub.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=\ngithub.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=\ngithub.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=\ngithub.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=\ngithub.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=\ngithub.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE=\ngithub.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=\ngithub.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=\ngithub.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=\ngithub.com/distribution/distribution/v3 v3.0.0-20220526142353-ffbd94cbe269 h1:hbCT8ZPPMqefiAWD2ZKjn7ypokIGViTvBBg/ExLSdCk=\ngithub.com/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32PaqRpvoEkKBy5M=\ngithub.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=\ngithub.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=\ngithub.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=\ngithub.com/docker/docker v20.10.17+incompatible h1:JYCuMrWaVNophQTOrMMoSwudOVEfcegoZZrleKc1xwE=\ngithub.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=\ngithub.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o=\ngithub.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c=\ngithub.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=\ngithub.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=\ngithub.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=\ngithub.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=\ngithub.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=\ngithub.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=\ngithub.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=\ngithub.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=\ngithub.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=\ngithub.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=\ngithub.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f h1:8GDPb0tCY8LQ+OJ3dbHb5sA6YZWXFORQYZx5sdsTlMs=\ngithub.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=\ngithub.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=\ngithub.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw=\ngithub.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=\ngithub.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=\ngithub.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=\ngithub.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=\ngithub.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=\ngithub.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=\ngithub.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=\ngithub.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=\ngithub.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=\ngithub.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=\ngithub.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=\ngithub.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=\ngithub.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=\ngithub.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84=\ngithub.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=\ngithub.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww=\ngithub.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=\ngithub.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM=\ngithub.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=\ngithub.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb h1:wCrNShQidLmvVWn/0PikGmpdP0vtQmnvyRg3ZBEhczw=\ngithub.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb/go.mod h1:wx3gB6dbIfBRcucp94PI9Bt3I0F2c/MyNEWuhzpWiwk=\ngithub.com/fatedier/frp v0.44.0 h1:rVzMveryBKV5H2cH/8Y0qwbxMatw2uA/etgIiCT5HoY=\ngithub.com/fatedier/frp v0.44.0/go.mod h1:NahedvXauelo3mcioq3gahG3BdhTfJ4Gia6rRQnE02A=\ngithub.com/fatedier/golib v0.1.1-0.20220321042308-c306138b83ac h1:td1FJwN/oz8+9GldeEm3YdBX0Husc0FSPywLesZxi4w=\ngithub.com/fatedier/golib v0.1.1-0.20220321042308-c306138b83ac/go.mod h1:fLV0TLwHqrnB/L3jbNl67Gn6PCLggDGHniX1wLrA2Qo=\ngithub.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible h1:ssXat9YXFvigNge/IkkZvFMn8yeYKFX+uI6wn2mLJ74=\ngithub.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible/go.mod h1:YpCOaxj7vvMThhIQ9AfTOPW2sfztQR5WDfs7AflSy4s=\ngithub.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=\ngithub.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=\ngithub.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=\ngithub.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=\ngithub.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=\ngithub.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=\ngithub.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0=\ngithub.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=\ngithub.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=\ngithub.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=\ngithub.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=\ngithub.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=\ngithub.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=\ngithub.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=\ngithub.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=\ngithub.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=\ngithub.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=\ngithub.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=\ngithub.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8=\ngithub.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=\ngithub.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=\ngithub.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=\ngithub.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=\ngithub.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=\ngithub.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=\ngithub.com/go-gorp/gorp/v3 v3.0.2 h1:ULqJXIekoqMx29FI5ekXXFoH1dT2Vc8UhnRzBg+Emz4=\ngithub.com/go-gorp/gorp/v3 v3.0.2/go.mod h1:BJ3q1ejpV8cVALtcXvXaXyTOlMmJhWDxTmncaR6rwBY=\ngithub.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=\ngithub.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=\ngithub.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=\ngithub.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=\ngithub.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=\ngithub.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=\ngithub.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=\ngithub.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=\ngithub.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=\ngithub.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=\ngithub.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=\ngithub.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=\ngithub.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=\ngithub.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro=\ngithub.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A=\ngithub.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4=\ngithub.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=\ngithub.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=\ngithub.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=\ngithub.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=\ngithub.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=\ngithub.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=\ngithub.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=\ngithub.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=\ngithub.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=\ngithub.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=\ngithub.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=\ngithub.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng=\ngithub.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=\ngithub.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=\ngithub.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=\ngithub.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=\ngithub.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=\ngithub.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=\ngithub.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=\ngithub.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=\ngithub.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=\ngithub.com/go-playground/validator/v10 v10.6.1/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk=\ngithub.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0=\ngithub.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=\ngithub.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=\ngithub.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=\ngithub.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=\ngithub.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=\ngithub.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=\ngithub.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=\ngithub.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=\ngithub.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU=\ngithub.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs=\ngithub.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0=\ngithub.com/gobuffalo/packd v1.0.1/go.mod h1:PP2POP3p3RXGz7Jh6eYEf93S7vA2za6xM7QT85L4+VY=\ngithub.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XEWlY=\ngithub.com/gobuffalo/packr/v2 v2.8.3/go.mod h1:0SahksCVcx4IMnigTjiFuyldmTrdTctXsOdiU5KwbKc=\ngithub.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=\ngithub.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=\ngithub.com/goccy/go-json v0.9.7 h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM=\ngithub.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=\ngithub.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=\ngithub.com/godror/godror v0.24.2/go.mod h1:wZv/9vPiUib6tkoDl+AZ/QLf5YZgMravZ7jxH2eQWAE=\ngithub.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=\ngithub.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=\ngithub.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=\ngithub.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=\ngithub.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=\ngithub.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=\ngithub.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU=\ngithub.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=\ngithub.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=\ngithub.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=\ngithub.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=\ngithub.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=\ngithub.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=\ngithub.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=\ngithub.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=\ngithub.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=\ngithub.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=\ngithub.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=\ngithub.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=\ngithub.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=\ngithub.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=\ngithub.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=\ngithub.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=\ngithub.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=\ngithub.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=\ngithub.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=\ngithub.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=\ngithub.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=\ngithub.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=\ngithub.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=\ngithub.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=\ngithub.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=\ngithub.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=\ngithub.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=\ngithub.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=\ngithub.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=\ngithub.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=\ngithub.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=\ngithub.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk=\ngithub.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k=\ngithub.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=\ngithub.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=\ngithub.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=\ngithub.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=\ngithub.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=\ngithub.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0=\ngithub.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E=\ngithub.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=\ngithub.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=\ngithub.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=\ngithub.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=\ngithub.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=\ngithub.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=\ngithub.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=\ngithub.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=\ngithub.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=\ngithub.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=\ngithub.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=\ngithub.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=\ngithub.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=\ngithub.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=\ngithub.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=\ngithub.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=\ngithub.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=\ngithub.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=\ngithub.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=\ngithub.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=\ngithub.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=\ngithub.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=\ngithub.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=\ngithub.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=\ngithub.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=\ngithub.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=\ngithub.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=\ngithub.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=\ngithub.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=\ngithub.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=\ngithub.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=\ngithub.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=\ngithub.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=\ngithub.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=\ngithub.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=\ngithub.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=\ngithub.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=\ngithub.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=\ngithub.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=\ngithub.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=\ngithub.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY=\ngithub.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo=\ngithub.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=\ngithub.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=\ngithub.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=\ngithub.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=\ngithub.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=\ngithub.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=\ngithub.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=\ngithub.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=\ngithub.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=\ngithub.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=\ngithub.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=\ngithub.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=\ngithub.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=\ngithub.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=\ngithub.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=\ngithub.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=\ngithub.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=\ngithub.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=\ngithub.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=\ngithub.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=\ngithub.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=\ngithub.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=\ngithub.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=\ngithub.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=\ngithub.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=\ngithub.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=\ngithub.com/hashicorp/yamux v0.0.0-20210707203944-259a57b3608c h1:nqkErwUGfpZZMqj29WZ9U/wz2OpJVDuiokLhE/3Y7IQ=\ngithub.com/hashicorp/yamux v0.0.0-20210707203944-259a57b3608c/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=\ngithub.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=\ngithub.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=\ngithub.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=\ngithub.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=\ngithub.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=\ngithub.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=\ngithub.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=\ngithub.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=\ngithub.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=\ngithub.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=\ngithub.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=\ngithub.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=\ngithub.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=\ngithub.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=\ngithub.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=\ngithub.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=\ngithub.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=\ngithub.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=\ngithub.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=\ngithub.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=\ngithub.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=\ngithub.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=\ngithub.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=\ngithub.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=\ngithub.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=\ngithub.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=\ngithub.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=\ngithub.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=\ngithub.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=\ngithub.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=\ngithub.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=\ngithub.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=\ngithub.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=\ngithub.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw=\ngithub.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=\ngithub.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=\ngithub.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=\ngithub.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=\ngithub.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=\ngithub.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=\ngithub.com/klauspost/cpuid/v2 v2.0.6 h1:dQ5ueTiftKxp0gyjKSx5+8BtPWkyQbd95m8Gys/RarI=\ngithub.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=\ngithub.com/klauspost/reedsolomon v1.9.15 h1:g2erWKD2M6rgnPf89fCji6jNlhMKMdXcuNHMW1SYCIo=\ngithub.com/klauspost/reedsolomon v1.9.15/go.mod h1:eqPAcE7xar5CIzcdfwydOEdcmchAKAP/qs14y4GCBOk=\ngithub.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=\ngithub.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=\ngithub.com/kortschak/utter v1.0.1/go.mod h1:vSmSjbyrlKjjsL71193LmzBOKgwePk9DH6uFaWHIInc=\ngithub.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=\ngithub.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=\ngithub.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=\ngithub.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=\ngithub.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=\ngithub.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=\ngithub.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=\ngithub.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=\ngithub.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw=\ngithub.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o=\ngithub.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk=\ngithub.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw=\ngithub.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=\ngithub.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=\ngithub.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=\ngithub.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=\ngithub.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=\ngithub.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs=\ngithub.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=\ngithub.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=\ngithub.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=\ngithub.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=\ngithub.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=\ngithub.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=\ngithub.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=\ngithub.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=\ngithub.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=\ngithub.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=\ngithub.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=\ngithub.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=\ngithub.com/maordavidov/go-k8s-portforward v0.0.0-20221009144733-274c2bdf14a1 h1:HD2tJ1NopsEHC+C4FCDgeJyZmWyKtPEfjmhrgrK9vMA=\ngithub.com/maordavidov/go-k8s-portforward v0.0.0-20221009144733-274c2bdf14a1/go.mod h1:/9RMlzAZflIp1zvVaJaoF6uCSJ/zmDtiJdKMbZqMb20=\ngithub.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI=\ngithub.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc=\ngithub.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY=\ngithub.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI=\ngithub.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI=\ngithub.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=\ngithub.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=\ngithub.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=\ngithub.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=\ngithub.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=\ngithub.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=\ngithub.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=\ngithub.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=\ngithub.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=\ngithub.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI=\ngithub.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=\ngithub.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=\ngithub.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=\ngithub.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=\ngithub.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=\ngithub.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=\ngithub.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=\ngithub.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=\ngithub.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=\ngithub.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=\ngithub.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=\ngithub.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4=\ngithub.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=\ngithub.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=\ngithub.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=\ngithub.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=\ngithub.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=\ngithub.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=\ngithub.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=\ngithub.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=\ngithub.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=\ngithub.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=\ngithub.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=\ngithub.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=\ngithub.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=\ngithub.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=\ngithub.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=\ngithub.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=\ngithub.com/mittwald/go-helm-client v0.11.3 h1:x1HcdPkWO8F+vSdUIrrz0MYO8vlSAwTOzTv2v+LfDC8=\ngithub.com/mittwald/go-helm-client v0.11.3/go.mod h1:KPQlej7swowdlqncc4RGLStZuhgX5J+2KKxRY2mR4uo=\ngithub.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=\ngithub.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=\ngithub.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=\ngithub.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=\ngithub.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI=\ngithub.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc=\ngithub.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw=\ngithub.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=\ngithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=\ngithub.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=\ngithub.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=\ngithub.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=\ngithub.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=\ngithub.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=\ngithub.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=\ngithub.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=\ngithub.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=\ngithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=\ngithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=\ngithub.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=\ngithub.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=\ngithub.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=\ngithub.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=\ngithub.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=\ngithub.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=\ngithub.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=\ngithub.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=\ngithub.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=\ngithub.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=\ngithub.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=\ngithub.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=\ngithub.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=\ngithub.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=\ngithub.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=\ngithub.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=\ngithub.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=\ngithub.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=\ngithub.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU=\ngithub.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=\ngithub.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=\ngithub.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=\ngithub.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=\ngithub.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=\ngithub.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=\ngithub.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=\ngithub.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=\ngithub.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec=\ngithub.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=\ngithub.com/operator-framework/helm-operator-plugins v0.0.11 h1:u2odF2qJ8y1DswCJBt28tvM7PDNIiA8Yc8bjsC1fpKA=\ngithub.com/operator-framework/helm-operator-plugins v0.0.11/go.mod h1:X5HB7sPe/cyLg7qZ25k1icC5DKh06oTf3BV8j4kWuxY=\ngithub.com/operator-framework/operator-lib v0.11.0 h1:eYzqpiOfq9WBI4Trddisiq/X9BwCisZd3rIzmHRC9Z8=\ngithub.com/operator-framework/operator-lib v0.11.0/go.mod h1:RpyKhFAoG6DmKTDIwMuO6pI3LRc8IE9rxEYWy476o6g=\ngithub.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=\ngithub.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=\ngithub.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=\ngithub.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU=\ngithub.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=\ngithub.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=\ngithub.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=\ngithub.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=\ngithub.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8=\ngithub.com/pires/go-proxyproto v0.6.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=\ngithub.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=\ngithub.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=\ngithub.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=\ngithub.com/poy/onpar v0.0.0-20190519213022-ee068f8ea4d1 h1:oL4IBbcqwhhNWh31bjOX8C/OCy0zs9906d/VUru+bqg=\ngithub.com/poy/onpar v0.0.0-20190519213022-ee068f8ea4d1/go.mod h1:nSbFQvMj97ZyhFRSJYtut+msi4sOY6zJDGCdSc+/rZU=\ngithub.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=\ngithub.com/pquerna/cachecontrol v0.1.0 h1:yJMy84ti9h/+OEWa752kBTKv4XC30OtVVHYv/8cTqKc=\ngithub.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI=\ngithub.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=\ngithub.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=\ngithub.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=\ngithub.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=\ngithub.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=\ngithub.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=\ngithub.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=\ngithub.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34=\ngithub.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=\ngithub.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=\ngithub.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=\ngithub.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=\ngithub.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=\ngithub.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=\ngithub.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=\ngithub.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=\ngithub.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=\ngithub.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=\ngithub.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=\ngithub.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=\ngithub.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=\ngithub.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=\ngithub.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=\ngithub.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=\ngithub.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=\ngithub.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=\ngithub.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=\ngithub.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=\ngithub.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=\ngithub.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=\ngithub.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=\ngithub.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=\ngithub.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=\ngithub.com/rodaine/table v1.0.1/go.mod h1:UVEtfBsflpeEcD56nF4F5AocNFta0ZuolpSVdPtlmP4=\ngithub.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=\ngithub.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=\ngithub.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=\ngithub.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=\ngithub.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=\ngithub.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=\ngithub.com/rubenv/sql-migrate v1.1.1 h1:haR5Hn8hbW9/SpAICrXoZqXnywS7Q5WijwkQENPeNWY=\ngithub.com/rubenv/sql-migrate v1.1.1/go.mod h1:/7TZymwxN8VWumcIxw1jjHEcR1djpdkMHQPT4FWdnbQ=\ngithub.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=\ngithub.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=\ngithub.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=\ngithub.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=\ngithub.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=\ngithub.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=\ngithub.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=\ngithub.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=\ngithub.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=\ngithub.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=\ngithub.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=\ngithub.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=\ngithub.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=\ngithub.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=\ngithub.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=\ngithub.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=\ngithub.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=\ngithub.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=\ngithub.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=\ngithub.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=\ngithub.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=\ngithub.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=\ngithub.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=\ngithub.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=\ngithub.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=\ngithub.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=\ngithub.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=\ngithub.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=\ngithub.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=\ngithub.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=\ngithub.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=\ngithub.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=\ngithub.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=\ngithub.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=\ngithub.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=\ngithub.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=\ngithub.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=\ngithub.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=\ngithub.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=\ngithub.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=\ngithub.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=\ngithub.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=\ngithub.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=\ngithub.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=\ngithub.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=\ngithub.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=\ngithub.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=\ngithub.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=\ngithub.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=\ngithub.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=\ngithub.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=\ngithub.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=\ngithub.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=\ngithub.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 h1:89CEmDvlq/F7SJEOqkIdNDGJXrQIhuIx9D2DBXjavSU=\ngithub.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU=\ngithub.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b h1:fj5tQ8acgNUr6O8LEplsxDhUIe2573iLkJc+PqnzZTI=\ngithub.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4=\ngithub.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=\ngithub.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=\ngithub.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=\ngithub.com/txn2/kubefwd v1.22.3 h1:g4pokBsl8tsQ1Le3leQbXAn9fnMiR5SeLcWzTVgZ5vA=\ngithub.com/txn2/kubefwd v1.22.3/go.mod h1:NC6az38fvqAmS1yKYLigyv6fhbXQiIjS9QrudSzSyno=\ngithub.com/txn2/txeh v1.3.0 h1:vnbv63htVMZCaQgLqVBxKvj2+HHHFUzNW7I183zjg3E=\ngithub.com/txn2/txeh v1.3.0/go.mod h1:O7M6gUTPeMF+vsa4c4Ipx3JDkOYrruB1Wry8QRsMcw8=\ngithub.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=\ngithub.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=\ngithub.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=\ngithub.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=\ngithub.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=\ngithub.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=\ngithub.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=\ngithub.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=\ngithub.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=\ngithub.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=\ngithub.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=\ngithub.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=\ngithub.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=\ngithub.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=\ngithub.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E=\ngithub.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0=\ngithub.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=\ngithub.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=\ngithub.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=\ngithub.com/yvasiyarov/go-metrics v0.0.0-20150112132944-c25f46c4b940 h1:p7OofyZ509h8DmPLh8Hn+EIIZm/xYhdZHJ9GnXHdr6U=\ngithub.com/yvasiyarov/gorelic v0.0.7 h1:4DTF1WOM2ZZS/xMOkTFBOcb6XiHu/PKn3rVo6dbewQE=\ngithub.com/yvasiyarov/newrelic_platform_go v0.0.0-20160601141957-9c099fbc30e9 h1:AsFN8kXcCVkUFHyuzp1FtYbzp1nCO/H6+1uPSGEyPzM=\ngithub.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=\ngithub.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=\ngo.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=\ngo.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=\ngo.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=\ngo.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=\ngo.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=\ngo.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=\ngo.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=\ngo.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=\ngo.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=\ngo.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=\ngo.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=\ngo.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=\ngo.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc=\ngo.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4=\ngo.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo=\ngo.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM=\ngo.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU=\ngo.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw=\ngo.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc=\ngo.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE=\ngo.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE=\ngo.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw=\ngo.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=\ngo.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc=\ngo.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=\ngo.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=\ngo.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=\ngo.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=\ngo.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=\ngo.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=\ngo.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=\ngo.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=\ngo.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=\ngo.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=\ngo.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=\ngo.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=\ngo.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=\ngo.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=\ngo.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=\ngolang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=\ngolang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=\ngolang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=\ngolang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=\ngolang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=\ngolang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=\ngolang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=\ngolang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM=\ngolang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=\ngolang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=\ngolang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=\ngolang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=\ngolang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=\ngolang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=\ngolang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=\ngolang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=\ngolang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=\ngolang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=\ngolang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=\ngolang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=\ngolang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=\ngolang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=\ngolang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=\ngolang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=\ngolang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=\ngolang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=\ngolang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=\ngolang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=\ngolang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=\ngolang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=\ngolang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=\ngolang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=\ngolang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=\ngolang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=\ngolang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=\ngolang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=\ngolang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=\ngolang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=\ngolang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=\ngolang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=\ngolang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=\ngolang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=\ngolang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=\ngolang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=\ngolang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=\ngolang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=\ngolang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=\ngolang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=\ngolang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=\ngolang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=\ngolang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=\ngolang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=\ngolang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=\ngolang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=\ngolang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=\ngolang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=\ngolang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=\ngolang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=\ngolang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=\ngolang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=\ngolang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=\ngolang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=\ngolang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=\ngolang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=\ngolang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=\ngolang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=\ngolang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=\ngolang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=\ngolang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=\ngolang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=\ngolang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=\ngolang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=\ngolang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=\ngolang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=\ngolang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=\ngolang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=\ngolang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=\ngolang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=\ngolang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=\ngolang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=\ngolang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=\ngolang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=\ngolang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=\ngolang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=\ngolang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=\ngolang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=\ngolang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=\ngolang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U=\ngolang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=\ngolang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=\ngolang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=\ngolang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=\ngolang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=\ngolang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=\ngolang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=\ngolang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=\ngolang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=\ngolang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=\ngolang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=\ngolang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=\ngolang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=\ngolang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=\ngolang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=\ngolang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=\ngolang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=\ngolang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=\ngolang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=\ngolang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=\ngolang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=\ngolang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=\ngolang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=\ngolang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=\ngolang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=\ngolang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=\ngolang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=\ngolang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY=\ngomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY=\ngoogle.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=\ngoogle.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=\ngoogle.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=\ngoogle.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=\ngoogle.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=\ngoogle.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=\ngoogle.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=\ngoogle.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=\ngoogle.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=\ngoogle.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=\ngoogle.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=\ngoogle.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=\ngoogle.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=\ngoogle.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=\ngoogle.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=\ngoogle.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=\ngoogle.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=\ngoogle.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=\ngoogle.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=\ngoogle.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=\ngoogle.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=\ngoogle.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=\ngoogle.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=\ngoogle.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=\ngoogle.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=\ngoogle.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=\ngoogle.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=\ngoogle.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=\ngoogle.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=\ngoogle.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=\ngoogle.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=\ngoogle.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=\ngoogle.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=\ngoogle.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=\ngoogle.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=\ngoogle.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=\ngoogle.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=\ngoogle.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=\ngoogle.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=\ngoogle.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=\ngoogle.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=\ngoogle.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=\ngoogle.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=\ngoogle.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=\ngoogle.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=\ngoogle.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=\ngoogle.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=\ngoogle.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=\ngoogle.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=\ngoogle.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=\ngoogle.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=\ngoogle.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=\ngoogle.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=\ngoogle.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=\ngoogle.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=\ngoogle.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=\ngoogle.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=\ngoogle.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=\ngoogle.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=\ngoogle.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=\ngoogle.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=\ngoogle.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=\ngoogle.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=\ngoogle.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=\ngoogle.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=\ngoogle.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=\ngoogle.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=\ngoogle.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=\ngoogle.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=\ngoogle.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=\ngoogle.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=\ngoogle.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 h1:hrbNEivu7Zn1pxvHk6MBrq9iE22woVILTHqexqBxe6I=\ngoogle.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=\ngoogle.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=\ngoogle.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=\ngoogle.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=\ngoogle.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=\ngoogle.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=\ngoogle.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=\ngoogle.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=\ngoogle.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=\ngoogle.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=\ngoogle.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=\ngoogle.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=\ngoogle.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=\ngoogle.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=\ngoogle.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=\ngoogle.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=\ngoogle.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=\ngoogle.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=\ngoogle.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=\ngoogle.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=\ngoogle.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=\ngoogle.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=\ngoogle.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=\ngoogle.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=\ngoogle.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=\ngoogle.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=\ngoogle.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=\ngoogle.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8=\ngoogle.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=\ngoogle.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=\ngoogle.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=\ngoogle.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=\ngoogle.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=\ngoogle.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=\ngoogle.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=\ngoogle.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=\ngoogle.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=\ngoogle.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=\ngoogle.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=\ngoogle.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=\ngoogle.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=\ngoogle.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=\ngopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=\ngopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=\ngopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=\ngopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=\ngopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=\ngopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=\ngopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=\ngopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=\ngopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=\ngopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=\ngopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=\ngopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=\ngopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=\ngopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=\ngopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=\ngopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=\ngopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=\ngotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=\ngotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=\nhelm.sh/helm/v3 v3.9.1 h1:i1ChBu5ZB01kMaN2Y4KaC7J6viT58L2pHXWrXJ0Ny58=\nhelm.sh/helm/v3 v3.9.1/go.mod h1:y/dJc/0Lzcn40jgd85KQXnufhFF7sr4v6L/vYMLRaRM=\nhonnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=\nhonnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=\nhonnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=\nk8s.io/api v0.21.2/go.mod h1:Lv6UGJZ1rlMI1qusN8ruAp9PUBFyBwpEHAdG24vIsiU=\nk8s.io/api v0.24.2/go.mod h1:AHqbSkTm6YrQ0ObxjO3Pmp/ubFF/KuM7jU+3khoBsOg=\nk8s.io/api v0.24.3/go.mod h1:elGR/XSZrS7z7cSZPzVWaycpJuGIw57j9b95/1PdJNI=\nk8s.io/api v0.25.2 h1:v6G8RyFcwf0HR5jQGIAYlvtRNrxMJQG1xJzaSeVnIS8=\nk8s.io/api v0.25.2/go.mod h1:qP1Rn4sCVFwx/xIhe+we2cwBLTXNcheRyYXwajonhy0=\nk8s.io/apiextensions-apiserver v0.25.0 h1:CJ9zlyXAbq0FIW8CD7HHyozCMBpDSiH7EdrSTCZcZFY=\nk8s.io/apiextensions-apiserver v0.25.0/go.mod h1:3pAjZiN4zw7R8aZC5gR0y3/vCkGlAjCazcg1me8iB/E=\nk8s.io/apimachinery v0.21.2/go.mod h1:CdTY8fU/BlvAbJ2z/8kBwimGki5Zp8/fbVuLY8gJumM=\nk8s.io/apimachinery v0.24.2/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=\nk8s.io/apimachinery v0.24.3/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=\nk8s.io/apimachinery v0.25.2 h1:WbxfAjCx+AeN8Ilp9joWnyJ6xu9OMeS/fsfjK/5zaQs=\nk8s.io/apimachinery v0.25.2/go.mod h1:hqqA1X0bsgsxI6dXsJ4HnNTBOmJNxyPp8dw3u2fSHwA=\nk8s.io/apiserver v0.25.0 h1:8kl2ifbNffD440MyvHtPaIz1mw4mGKVgWqM0nL+oyu4=\nk8s.io/apiserver v0.25.0/go.mod h1:BKwsE+PTC+aZK+6OJQDPr0v6uS91/HWxX7evElAH6xo=\nk8s.io/cli-runtime v0.24.2/go.mod h1:1LIhKL2RblkhfG4v5lZEt7FtgFG5mVb8wqv5lE9m5qY=\nk8s.io/cli-runtime v0.24.3 h1:O9YvUHrDSCQUPlsqVmaqDrueqjpJ7IO6Yas9B6xGSoo=\nk8s.io/cli-runtime v0.24.3/go.mod h1:In84wauoMOqa7JDvDSXGbf8lTNlr70fOGpYlYfJtSqA=\nk8s.io/client-go v0.21.2/go.mod h1:HdJ9iknWpbl3vMGtib6T2PyI/VYxiZfq936WNVHBRrA=\nk8s.io/client-go v0.24.2/go.mod h1:zg4Xaoo+umDsfCWr4fCnmLEtQXyCNXCvJuSsglNcV30=\nk8s.io/client-go v0.24.3/go.mod h1:AAovolf5Z9bY1wIg2FZ8LPQlEdKHjLI7ZD4rw920BJw=\nk8s.io/client-go v0.25.2 h1:SUPp9p5CwM0yXGQrwYurw9LWz+YtMwhWd0GqOsSiefo=\nk8s.io/client-go v0.25.2/go.mod h1:i7cNU7N+yGQmJkewcRD2+Vuj4iz7b30kI8OcL3horQ4=\nk8s.io/code-generator v0.24.2/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w=\nk8s.io/component-base v0.24.2/go.mod h1:ucHwW76dajvQ9B7+zecZAP3BVqvrHoOxm8olHEg0nmM=\nk8s.io/component-base v0.25.0 h1:haVKlLkPCFZhkcqB6WCvpVxftrg6+FK5x1ZuaIDaQ5Y=\nk8s.io/component-base v0.25.0/go.mod h1:F2Sumv9CnbBlqrpdf7rKZTmmd2meJq0HizeyY/yAFxk=\nk8s.io/component-helpers v0.24.2/go.mod h1:TRQPBQKfmqkmV6c0HAmUs8cXVNYYYLsXy4zu8eODi9g=\nk8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=\nk8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=\nk8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=\nk8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=\nk8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=\nk8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=\nk8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=\nk8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ=\nk8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=\nk8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE=\nk8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=\nk8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk=\nk8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA=\nk8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU=\nk8s.io/kubectl v0.24.2 h1:+RfQVhth8akUmIc2Ge8krMl/pt66V7210ka3RE/p0J4=\nk8s.io/kubectl v0.24.2/go.mod h1:+HIFJc0bA6Tzu5O/YcuUt45APAxnNL8LeMuXwoiGsPg=\nk8s.io/metrics v0.24.2/go.mod h1:5NWURxZ6Lz5gj8TFU83+vdWIVASx7W8lwPpHYCqopMo=\nk8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=\nk8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=\nk8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=\nk8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4=\nk8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=\noras.land/oras-go v1.2.0 h1:yoKosVIbsPoFMqAIFHTnrmOuafHal+J/r+I5bdbVWu4=\noras.land/oras-go v1.2.0/go.mod h1:pFNs7oHp2dYsYMSS82HaX5l4mpnGO7hbpPN6EWH2ltc=\nrsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=\nrsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=\nrsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=\nsigs.k8s.io/controller-runtime v0.13.0 h1:iqa5RNciy7ADWnIc8QxCbOX5FEKVR3uxVxKHRMc2WIQ=\nsigs.k8s.io/controller-runtime v0.13.0/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI=\nsigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY=\nsigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k=\nsigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=\nsigs.k8s.io/kustomize/api v0.11.4 h1:/0Mr3kfBBNcNPOW5Qwk/3eb8zkswCwnqQxxKtmrTkRo=\nsigs.k8s.io/kustomize/api v0.11.4/go.mod h1:k+8RsqYbgpkIrJ4p9jcdPqe8DprLxFUUO0yNOq8C+xI=\nsigs.k8s.io/kustomize/cmd/config v0.10.6/go.mod h1:/S4A4nUANUa4bZJ/Edt7ZQTyKOY9WCER0uBS1SW2Rco=\nsigs.k8s.io/kustomize/kustomize/v4 v4.5.4/go.mod h1:Zo/Xc5FKD6sHl0lilbrieeGeZHVYCA4BzxeAaLI05Bg=\nsigs.k8s.io/kustomize/kyaml v0.13.6 h1:eF+wsn4J7GOAXlvajv6OknSunxpcOBQQqsnPxObtkGs=\nsigs.k8s.io/kustomize/kyaml v0.13.6/go.mod h1:yHP031rn1QX1lr/Xd934Ri/xdVNG8BE2ECa78Ht/kEg=\nsigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=\nsigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=\nsigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=\nsigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=\nsigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=\nsigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=\nsigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=\nsigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=\n"
  },
  {
    "path": "pkg/clients/helm/helm.go",
    "content": "package helm\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\thelmclient \"github.com/mittwald/go-helm-client\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/clients/kube\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/constants\"\n\t\"helm.sh/helm/v3/pkg/repo\"\n\t\"time\"\n)\n\ntype Helm struct {\n\tnamespace  string\n\thelmClient helmclient.Client\n}\n\ntype EMPTY struct {\n}\n\nfunc MustNew(kube *kube.Kube) *Helm {\n\n\tclient, err := helmclient.NewClientFromRestConf(&helmclient.RestConfClientOptions{\n\t\tOptions: &helmclient.Options{\n\t\t\tNamespace: kube.Namespace,\n\t\t\tDebug:     true,\n\t\t\tDebugLog: func(format string, v ...interface{}) {\n\t\t\t\tlog.Infof(format, v)\n\t\t\t},\n\t\t},\n\t\tRestConfig: kube.Config,\n\t})\n\n\tif err != nil {\n\t\tlog.Panicf(\"fail creating helm client, more info: '%s'\", err.Error())\n\t}\n\n\terr = client.AddOrUpdateChartRepo(repo.Entry{\n\t\tName: constants.DcodeSlug,\n\t\tURL:  constants.DcodeChartRepo,\n\t})\n\n\tif err != nil {\n\t\tlog.Panicf(\"fail adding Dcode's chart repo, more info: '%s'\", err.Error())\n\t}\n\n\terr = client.UpdateChartRepos()\n\tif err != nil {\n\t\tlog.Panicf(\"fail updating Dcode's helm repo, more info: %s\", err.Error())\n\t}\n\n\treturn &Helm{\n\t\tkube.Namespace,\n\t\tclient,\n\t}\n}\n\n//func (c *Helm) InstallOrUpgradeFrpServer(chartVersion string, values *models.FRPServerValues) error {\n//\n//\treleaseName := values.KubeTunnelServiceName()\n//\n//\tvaluesYaml, err := yaml.Marshal(values)\n//\tif err != nil {\n//\t\treturn fmt.Errorf(\"err: fail to parse values.yaml more info: '%s'\", err.Error())\n//\t}\n//\n//\treturn install(c, constants.KubeTunnelChartName, chartVersion, releaseName, valuesYaml)\n//}\n\nfunc (c *Helm) InstallKubeTunnelOperator(chartVersion string) error {\n\n\treleaseName := \"kubetunnel-operator\"\n\n\treturn install(c, constants.KubetunnelOperatorChartName, chartVersion, releaseName, true, []byte{})\n}\n\nfunc install(c *Helm, chartName string, chartVersion string, releaseName string, replace bool, valuesYaml []byte) error {\n\n\treturn installWithNamespace(c, chartName, chartVersion, releaseName, c.namespace, replace, valuesYaml)\n}\n\nfunc installWithNamespace(c *Helm, chartName string, chartVersion string, releaseName string, namespace string, replace bool, valuesYaml []byte) error {\n\n\tchartSpec := helmclient.ChartSpec{\n\t\tReleaseName:     releaseName,\n\t\tRecreate:        replace,\n\t\tChartName:       chartName,\n\t\tAtomic:          true,\n\t\tVersion:         chartVersion,\n\t\tNamespace:       namespace,\n\t\tCreateNamespace: true,\n\t\tUpgradeCRDs:     true,\n\t\tWait:            true,\n\t\tReplace:         replace,\n\t\tValuesYaml:      string(valuesYaml),\n\t\tTimeout:         time.Second * 30,\n\t}\n\n\tif _, err := c.helmClient.InstallOrUpgradeChart(context.Background(), &chartSpec, nil); err != nil {\n\t\treturn fmt.Errorf(\"err: fail installing %s chart. more info: %s\", chartName, err.Error())\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/clients/helm/helm_test.go",
    "content": "package helm_test\n\nimport (\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/clients/helm\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/clients/kube\"\n\t\"testing\"\n)\n\nfunc TestInstallingOperator(t *testing.T) {\n\n\tclient := kube.MustNew(\"/Users/maordavidov/dcode/gitlab-cicd-kubeconfig.yaml\", \"kubetunnel\")\n\n\thelmClient := helm.MustNew(client)\n\n\terr := helmClient.InstallKubeTunnelOperator(\"0.0.6\")\n\n\tassert.NoError(t, err)\n}\n"
  },
  {
    "path": "pkg/clients/helm/models/pod_selector_label.go",
    "content": "package models\n\nimport \"fmt\"\n\ntype PodSelectorLabel struct {\n\tKey   string\n\tValue string\n}\n\nfunc (p PodSelectorLabel) String() string {\n\n\treturn fmt.Sprintf(\"%s: %s\", p.Key, p.Value)\n}\n\nfunc (p PodSelectorLabel) MarshalYAML() (interface{}, error) {\n\n\treturn p.String(), nil\n}\n"
  },
  {
    "path": "pkg/clients/kube/kube.go",
    "content": "package kube\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\tportforward \"github.com/maordavidov/go-k8s-portforward\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/clients/kube/servicecontext\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/constants\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/models\"\n\tv12 \"k8s.io/api/authorization/v1\"\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/client-go/rest\"\n\t\"k8s.io/client-go/tools/clientcmd\"\n\t\"strconv\"\n\t\"strings\"\n)\n\ntype Kube struct {\n\tInnerKubeClient *kubernetes.Clientset\n\tConfig          *rest.Config\n\tNamespace       string\n}\n\nfunc MustNew(kubeConf string, namespace string) *Kube {\n\n\tkube, err := New(kubeConf, namespace)\n\n\tif err != nil {\n\t\tlog.Panic(err.Error())\n\t}\n\n\treturn kube\n}\n\nfunc New(kubeConf string, namespace string) (kube *Kube, err error) {\n\n\tkubeClient, config, err := createInClusterKubeClient()\n\n\tif err != nil {\n\n\t\tvar kubeConfig clientcmd.ClientConfig\n\t\tkubeClient, kubeConfig, _ = mustCreateOutOfClusterKubeClient(kubeConf)\n\n\t\tconfig, _ = kubeConfig.ClientConfig()\n\n\t\tif len(namespace) == 0 {\n\t\t\tnamespace, _, _ = kubeConfig.Namespace()\n\t\t}\n\t}\n\n\tkube = &Kube{\n\t\tkubeClient,\n\t\tconfig,\n\t\tnamespace,\n\t}\n\n\treturn kube, nil\n}\n\nfunc (k *Kube) GetPodLabelsByLabelSelector(namespace string, podLabelSelectors map[string]string) (map[string]string, error) {\n\n\tlabelSelector, err := labels.ValidatedSelectorFromSet(podLabelSelectors)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tpods, err := k.InnerKubeClient.CoreV1().Pods(namespace).List(context.Background(), v1.ListOptions{\n\t\tLabelSelector: labelSelector.String(),\n\t\tLimit:         1,\n\t})\n\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif len(pods.Items) == 0 {\n\n\t\treturn nil, fmt.Errorf(\"could not find pods. host: '%s' namespace: '%s', selector: '%s'\", k.Config.Host, namespace, labelSelector.String())\n\t}\n\n\treturn pods.Items[0].Labels, nil\n}\n\nfunc (k *Kube) GetServiceContextWithNamespace(name string, namespace string) (*servicecontext.ServiceContext, error) {\n\tif len(namespace) == 0 {\n\t\tnamespace = k.Namespace\n\t}\n\n\tsvc, err := k.InnerKubeClient.CoreV1().Services(namespace).Get(context.Background(), name, v1.GetOptions{})\n\tif err != nil {\n\n\t\terr = fmt.Errorf(\"namespace: '%s' svc: '%s' not found at host: '%s'\", k.Namespace, name, k.Config.Host)\n\t\treturn nil, err\n\t}\n\n\tctx := servicecontext.ServiceContext{\n\t\tServiceName:   svc.Name,\n\t\tLabelSelector: svc.Spec.Selector,\n\t\tPorts:         svc.Spec.Ports,\n\t}\n\n\treturn &ctx, nil\n}\nfunc (k *Kube) GetServiceContext(name string) (*servicecontext.ServiceContext, error) {\n\n\treturn k.GetServiceContextWithNamespace(name, k.Namespace)\n}\n\nfunc (k *Kube) ListServiceNamesWithoutKubeTunnel() (serviceNames []string, err error) {\n\n\tservices, err := k.InnerKubeClient.CoreV1().Services(k.Namespace).List(context.Background(), v1.ListOptions{})\n\n\tif err != nil || services == nil {\n\t\treturn\n\t}\n\n\tfor _, svc := range services.Items {\n\n\t\tif strings.HasPrefix(svc.Name, constants.KubetunnelSlug) {\n\t\t\tcontinue\n\t\t}\n\n\t\tserviceNames = append(serviceNames, svc.Name)\n\t}\n\n\treturn\n}\n\nfunc (k *Kube) PortForward(serviceName string, port string) (listeningPort int, err error) {\n\n\tservice, err := k.GetServiceContext(serviceName)\n\n\tif err != nil {\n\t\treturn -1, err\n\t}\n\n\tportInt, err := strconv.Atoi(port)\n\tif err != nil {\n\t\treturn -1, err\n\t}\n\n\tpf := &portforward.PortForward{\n\t\tNamespace: k.Namespace,\n\t\tLabels: v1.LabelSelector{\n\t\t\tMatchLabels: service.LabelSelector,\n\t\t},\n\t\tDestinationPort: portInt,\n\t\tConfig:          k.Config,\n\t\tClientset:       k.InnerKubeClient,\n\t}\n\n\tlisteningPort, err = pf.Start(context.Background())\n\tif err != nil {\n\t\treturn -1, fmt.Errorf(\"error starting port forward: %s\", err)\n\t}\n\n\tlog.Printf(\"Started tunnel on %d\\n\", pf.ListenPort)\n\n\t// TODO: how to stop? pf.Stop()..? do we need to listen on stop??\n\n\treturn listeningPort, nil\n}\n\nfunc (k *Kube) CreateKubeTunnelResource(resourceSpec models.KubeTunnelResourceSpec) error {\n\tvar body []byte\n\n\tresource := models.KubeTunnelResource{\n\t\tTypeMeta: v1.TypeMeta{\n\t\t\tKind:       constants.KubeTunnelKind,\n\t\t\tAPIVersion: constants.KubeTunnelApiVersion,\n\t\t},\n\t\tMetadata: v1.ObjectMeta{\n\t\t\tName: resourceSpec.KubeTunnelServiceName(),\n\t\t},\n\t\tSpec: resourceSpec,\n\t}\n\n\turl := fmt.Sprintf(\"/apis/%s/namespaces/%s/%ss\", constants.KubeTunnelApiVersion, k.Namespace, constants.KubetunnelSlug)\n\n\tdata, err := k.InnerKubeClient.RESTClient().\n\t\tGet().\n\t\tAbsPath(fmt.Sprintf(\"%s/%s\", url, resource.Metadata.Name)).\n\t\tDoRaw(context.TODO())\n\n\tif err != nil {\n\n\t\tif body, err = json.Marshal(resource); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tdata, err = k.InnerKubeClient.RESTClient().\n\t\t\tPost().\n\t\t\tAbsPath(url).\n\t\t\tBody(body).\n\t\t\tDoRaw(context.TODO())\n\t} else {\n\n\t\tvar oldResource models.KubeTunnelResource\n\t\tif err = json.Unmarshal(data, &oldResource); err != nil {\n\t\t\treturn fmt.Errorf(\"unable to update existing CRD. please manually delete kubetunnel: %s and run again\", resource.Metadata.Name)\n\t\t}\n\n\t\tresource.Metadata.ResourceVersion = oldResource.Metadata.ResourceVersion\n\n\t\tif body, err = json.Marshal(resource); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tdata, err = k.InnerKubeClient.RESTClient().\n\t\t\tPut().\n\t\t\tAbsPath(fmt.Sprintf(\"%s/%s\", url, resource.Metadata.Name)).\n\t\t\tBody(body).\n\t\t\tDoRaw(context.TODO())\n\t}\n\n\tlog.Debug(string(data))\n\treturn err\n}\n\nfunc (k *Kube) ConnectivityCheck() error {\n\n\t_, err := k.InnerKubeClient.Discovery().ServerVersion()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to connect kubernetes host: '%s', check KUBECONFIG set or ~/.kube/config is configured correctly\", k.Config.Host)\n\t}\n\n\treturn nil\n}\n\nfunc (k *Kube) RBACCheck() error {\n\n\t// Check RBAC permissions for each of the requested namespaces\n\trequiredPermissions := []v12.ResourceAttributes{\n\t\t{Verb: \"list\", Resource: \"pods\"},\n\t\t{Verb: \"get\", Resource: \"pods\"},\n\t\t{Verb: \"watch\", Resource: \"pods\"},\n\t\t{Verb: \"get\", Resource: \"services\"},\n\t}\n\n\tfor _, perm := range requiredPermissions {\n\n\t\tvar accessReview = &v12.SelfSubjectAccessReview{\n\t\t\tSpec: v12.SelfSubjectAccessReviewSpec{\n\t\t\t\tResourceAttributes: &perm,\n\t\t\t},\n\t\t}\n\t\taccessReview, err := k.InnerKubeClient.AuthorizationV1().SelfSubjectAccessReviews().Create(context.TODO(), accessReview, v1.CreateOptions{})\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"unable to connect kubernetes host: '%s', more info: '%s'\", k.Config.Host, err.Error())\n\t\t}\n\t\tif accessReview.Status.Allowed == false {\n\t\t\treturn fmt.Errorf(\"host: '%s', namespace: '%s' missing RBAC permission: %v\", k.Config.Host, k.Namespace, perm)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc createInClusterKubeClient() (*kubernetes.Clientset, *rest.Config, error) {\n\tinClusterConf, err := rest.InClusterConfig()\n\n\tif err != nil {\n\t\tlog.Warnf(\"fail to get InClusterConfig, err: %s\", err.Error())\n\t\treturn nil, nil, err\n\t}\n\n\tclient, err := kubernetes.NewForConfig(inClusterConf)\n\tif err != nil {\n\t\tlog.Warnf(\"fail to create new config from in cluster, err: %s\", err.Error())\n\t\treturn nil, nil, err\n\t}\n\n\tlog.Info(\"connected using in cluster config\")\n\n\treturn client, inClusterConf, nil\n}\n\nfunc mustCreateOutOfClusterKubeClient(kubeConf string) (*kubernetes.Clientset, clientcmd.ClientConfig, error) {\n\n\tvar kubeConfig clientcmd.ClientConfig\n\n\tif kubeConf == \"\" {\n\t\tloadingRules := clientcmd.NewDefaultClientConfigLoadingRules()\n\t\tconfigOverrides := &clientcmd.ConfigOverrides{}\n\t\tkubeConfig = clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides)\n\t} else {\n\n\t\tconf, err := clientcmd.LoadFromFile(kubeConf)\n\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"err: unable to load kubeconfig from path: '%s'. \\\"%s\\\"\", kubeConf, err.Error())\n\t\t}\n\n\t\tkubeConfig = clientcmd.NewDefaultClientConfig(*conf, &clientcmd.ConfigOverrides{})\n\t}\n\n\tconfig, err := kubeConfig.ClientConfig()\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"err: unable to read kubeconfig. \\\"%s\\\"\", err.Error())\n\t}\n\n\tkubeClient, err := kubernetes.NewForConfig(config)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"err: unable to create kube client. \\\"%s\\\"\", err.Error())\n\t}\n\n\treturn kubeClient, kubeConfig, nil\n}\n"
  },
  {
    "path": "pkg/clients/kube/kube_test.go",
    "content": "package kube_test\n\nimport (\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/clients/kube\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/models\"\n\t\"testing\"\n)\n\nfunc TestGetServiceWithSinglePortOnDefaultNamespace(t *testing.T) {\n\n\tclient := kube.MustNew(\"\", \"\")\n\n\tcontext, err := client.GetServiceContext(\"kubetunnel-svc\")\n\n\tassert.NoError(t, err)\n\tassert.NotNil(t, context)\n\tassert.Len(t, context.Ports, 1)\n}\n\nfunc TestGetServiceWithMultiplePortsOnDefaultNamespace(t *testing.T) {\n\n\tclient := kube.MustNew(\"\", \"\")\n\n\tcontext, err := client.GetServiceContext(\"kubetunnel-multi-svc\")\n\n\tassert.NoError(t, err)\n\tassert.NotNil(t, context)\n\tassert.Len(t, context.Ports, 2)\n}\n\nfunc TestGetServiceFromExplicitNamespaceWithMultipleLables(t *testing.T) {\n\n\tclient := kube.MustNew(\"\", \"kubetunnel-explicit\")\n\n\tcontext, err := client.GetServiceContext(\"kubetunnel-svc\")\n\n\tassert.NoError(t, err)\n\tassert.NotNil(t, context)\n\tassert.Len(t, context.Ports, 1)\n\tassert.Len(t, context.LabelSelector, 2)\n}\n\nfunc TestKubePortForward(t *testing.T) {\n\n\tclient := kube.MustNew(\"/Users/maordavidov/dcode/gitlab-cicd-kubeconfig.yaml\", \"kubetunnel\")\n\n\tlisteningPort, err := client.PortForward(\"kubetunnel-nginx\", \"7000\")\n\n\tassert.NoError(t, err)\n\tassert.NotEqual(t, -1, listeningPort)\n}\n\nfunc TestCreateKubeTunnelResource(t *testing.T) {\n\n\tclient := kube.MustNew(\"/Users/maordavidov/dcode/gitlab-cicd-kubeconfig.yaml\", \"kubetunnel\")\n\n\terr := client.CreateKubeTunnelResource(models.KubeTunnelResourceSpec{\n\t\tPorts:       models.Ports{Values: []string{\"80\", \"8081\"}},\n\t\tServiceName: \"nginx\",\n\t\tPodSelectorLabels: map[string]string{\n\t\t\t\"app\": \"nginx\",\n\t\t},\n\t})\n\n\tassert.NoError(t, err)\n}\n\nfunc TestGetPodLabelsByServiceName(t *testing.T) {\n\n\tclient := kube.MustNew(\"/Users/maordavidov/dcode/gitlab-cicd-kubeconfig.yaml\", \"kubetunnel\")\n\n\tcontext, err := client.GetServiceContext(\"nginx\")\n\n\tassert.NoError(t, err)\n\tassert.NotNil(t, context)\n\n\tlabels, err := client.GetPodLabelsByLabelSelector(\"kubetunnel\", context.LabelSelector)\n\tassert.NoError(t, err)\n\tassert.NotNil(t, labels)\n}\n"
  },
  {
    "path": "pkg/clients/kube/patch_operation.go",
    "content": "package kube\n\ntype PatchOperation struct {\n\tOp    string `json:\"op\"`\n\tPath  string `json:\"path\"`\n\tValue string `json:\"value\"`\n}\n"
  },
  {
    "path": "pkg/clients/kube/servicecontext/service_context.go",
    "content": "package servicecontext\n\nimport v1 \"k8s.io/api/core/v1\"\n\ntype ServiceContext struct {\n\tServiceName   string\n\tLabelSelector map[string]string\n\tPorts         []v1.ServicePort\n}\n"
  },
  {
    "path": "pkg/clients/kube/servicecontext/utils.go",
    "content": "package servicecontext\n\nimport (\n\t\"fmt\"\n\t\"github.com/ahmetb/go-linq/v3\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/constants\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/frp/frpc\"\n\tfrpmodels \"github.com/we-dcode/kube-tunnel/pkg/frp/models\"\n\tkubeTunnelModels \"github.com/we-dcode/kube-tunnel/pkg/models\"\n\tv1 \"k8s.io/api/core/v1\"\n\t\"strconv\"\n)\n\nfunc ToKubeTunnelResourceSpec(ctx *ServiceContext, podLabels map[string]string) kubeTunnelModels.KubeTunnelResourceSpec {\n\n\tvar ports []string\n\n\tlinq.From(ctx.Ports).Select(func(kubePort interface{}) interface{} {\n\t\treturn strconv.Itoa(int(kubePort.(v1.ServicePort).Port))\n\t}).ToSlice(&ports)\n\n\t//labelSelectors := make(map[string]string)\n\t//\n\t//for key, value := range ctx.LabelSelector {\n\t//\n\t//\tlabelSelectors[key] = fmt.Sprintf(\"%s-%s\", constants.KubetunnelSlug, value)\n\t//}\n\n\tpodLabels[constants.KubetunnelSlug] = ctx.ServiceName\n\n\treturn kubeTunnelModels.KubeTunnelResourceSpec{\n\t\tPorts:       kubeTunnelModels.Ports{Values: ports},\n\t\tServiceName: ctx.ServiceName,\n\t\tPodLabels:   podLabels,\n\t}\n}\n\nfunc ToFRPClientPairs(localIP string, remotePortByLocal map[string]string, ctx *ServiceContext) []frpc.ServicePair {\n\n\tvar servicePairs []frpc.ServicePair\n\n\tlocalPortByRemote := make(map[string]string)\n\n\tfor k, v := range remotePortByLocal {\n\t\tlocalPortByRemote[v] = k\n\t}\n\n\tlinq.From(ctx.Ports).Select(func(kubePort interface{}) interface{} {\n\n\t\tport := strconv.Itoa(int(kubePort.(v1.ServicePort).Port))\n\n\t\tlocalPort := localPortByRemote[port]\n\n\t\tif localPort == \"\" {\n\t\t\treturn nil // port not found in map\n\t\t}\n\n\t\treturn frpc.ServicePair{\n\t\t\tName: fmt.Sprintf(\"%s-%s\", ctx.ServiceName, port),\n\t\t\tService: frpmodels.Service{\n\t\t\t\tType:       \"tcp\",\n\t\t\t\tRemotePort: port,\n\t\t\t\tLocalIP:    localIP,\n\t\t\t\tLocalPort:  localPort, //TODO: check what happen if port is not found in map\n\t\t\t},\n\t\t}\n\n\t}).Where(func(servicePair interface{}) bool {\n\t\treturn servicePair != nil\n\t}).ToSlice(&servicePairs)\n\n\treturn servicePairs\n}\n"
  },
  {
    "path": "pkg/clients/kube/servicecontext/utils_test.go",
    "content": "package servicecontext_test\n\nimport (\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/clients/kube/servicecontext\"\n\tv1 \"k8s.io/api/core/v1\"\n\t\"testing\"\n)\n\nfunc TestServiceContextToFRPSValues(t *testing.T) {\n\n\tsvcContext := servicecontext.ServiceContext{\n\t\tServiceName: \"kubetunnel-svc-test\",\n\t\tLabelSelector: map[string]string{\n\t\t\t\"kuku\": \"riku\",\n\t\t\t\"abra\": \"kadabra\",\n\t\t\t\"foo\":  \"bar\",\n\t\t},\n\t\tPorts: []v1.ServicePort{\n\t\t\t{\n\t\t\t\tPort: 80,\n\t\t\t},\n\t\t\t{\n\t\t\t\tPort: 443,\n\t\t\t},\n\t\t},\n\t}\n\n\tvalues := servicecontext.ToKubeTunnelResourceSpec(&svcContext)\n\n\tassert.NotNil(t, values)\n\n\tassert.Equal(t, svcContext.ServiceName, values.ServiceName)\n\tassert.Len(t, values.Ports.Values, 2)\n\tassert.Len(t, values.PodSelectorLabels, 3)\n}\n\nfunc TestWhenCallingToFRPClientPairs_AndNotAllPortMapFound_MapOnlyExistingPorts(t *testing.T) {\n\n\tsvcContext := servicecontext.ServiceContext{\n\t\tServiceName: \"kubetunnel-svc-test\",\n\t\tPorts: []v1.ServicePort{\n\t\t\t{\n\t\t\t\tPort: 80,\n\t\t\t},\n\t\t\t{\n\t\t\t\tPort: 443,\n\t\t\t},\n\t\t},\n\t}\n\n\tportMapping := map[string]string{\n\t\t\"56172\": \"80\",\n\t}\n\n\tvalues := servicecontext.ToFRPClientPairs(\"127.0.0.1\", portMapping, &svcContext)\n\n\tassert.NotNil(t, values)\n\tassert.Len(t, values, 1)\n}\n\nfunc TestWhenCallingToFRPClientPairs_AndAllPortMapFound_MapAllPorts(t *testing.T) {\n\n\tsvcContext := servicecontext.ServiceContext{\n\t\tServiceName: \"kubetunnel-svc-test\",\n\t\tPorts: []v1.ServicePort{\n\t\t\t{\n\t\t\t\tPort: 80,\n\t\t\t},\n\t\t\t{\n\t\t\t\tPort: 443,\n\t\t\t},\n\t\t},\n\t}\n\n\tportMapping := map[string]string{\n\t\t\"56172\": \"80\",\n\t\t\"56171\": \"443\",\n\t}\n\n\tvalues := servicecontext.ToFRPClientPairs(\"127.0.0.1\", portMapping, &svcContext)\n\n\tassert.NotNil(t, values)\n\tassert.Len(t, values, 2)\n}\n"
  },
  {
    "path": "pkg/constants/constants.go",
    "content": "package constants\n\nconst (\n\tDcodeChartRepo              = \"https://we-dcode.github.io/kubetunnel\"\n\tDcodeSlug                   = \"we-dcode\"\n\tKubetunnelOperatorChartName = DcodeSlug + \"/kubetunnel-operator\"\n\tFRPServerPort               = \"7000\"\n\tKubetunnelSlug              = \"kubetunnel\"\n\tKubeTunnelApiVersion        = \"application.dcode.tech/v1\"\n\tKubeTunnelKind              = \"Kubetunnel\"\n)\n"
  },
  {
    "path": "pkg/frp/frpc/frpclient.go",
    "content": "package frpc\n\nimport (\n\t\"fmt\"\n\t\"github.com/fatedier/frp/client\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/frp/frputil\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/frp/models\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/notify\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/utils/tomlutil\"\n)\n\ntype ServicePair struct {\n\tName    string\n\tService models.Service\n}\n\n// Execute - This code was copied from frpc and modified a bit to support kubetunnel requirements\nfunc Execute(common models.Common, servicePair []ServicePair) (cancelChan *notify.CancellationChannel, err error) {\n\n\ttomlString := createToml(common, servicePair)\n\n\tcfg, pxyCfgs, visitorCfgs, err := frputil.ParseClientConfig([]byte(tomlString))\n\tif err != nil {\n\n\t\treturn nil, fmt.Errorf(\"fail to start frpc. more info: '%s'\", err.Error())\n\t}\n\n\tsvr, errRet := client.NewService(cfg, pxyCfgs, visitorCfgs, \"\")\n\tif errRet != nil {\n\t\terr = errRet\n\t\treturn nil, err\n\t}\n\n\tcancelChan = notify.NewCancellationChannelWithCallback(func() {\n\t\tsvr.Close()\n\t})\n\n\tgo func() {\n\t\terr = svr.Run()\n\t\tcancelChan.CancelWithReason(err) // if finish with reason\n\t}()\n\n\treturn cancelChan, nil\n}\n\nfunc createToml(common models.Common, servicePair []ServicePair) string {\n\tfrpConfig := models.FrpClientConfig{\n\t\t\"common\": common,\n\t}\n\n\tfor _, element := range servicePair {\n\n\t\tfrpConfig[element.Name] = element.Service\n\t}\n\n\ttomlString, _ := tomlutil.Marshal(frpConfig)\n\n\treturn tomlString\n}\n"
  },
  {
    "path": "pkg/frp/frpc/frpclient_test.go",
    "content": "package frpc_test\n\nimport (\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/frp/frpc\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/frp/models\"\n\t\"testing\"\n)\n\nfunc TestInstallingKubetunnelGC(t *testing.T) {\n\n\tcommon := models.Common{\n\t\tServerAddress: \"localhost\",\n\t\tServerPort:    \"7001\",\n\t}\n\n\tsvc := []frpc.ServicePair{\n\t\t{\n\t\t\tName: \"google\",\n\t\t\tService: models.Service{\n\t\t\t\tType:       \"tcp\",\n\t\t\t\tRemotePort: \"80\",\n\t\t\t\tLocalIP:    \"google.com\",\n\t\t\t\tLocalPort:  \"80\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tName: \"microsoft\",\n\t\t\tService: models.Service{\n\t\t\t\tType:       \"tcp\",\n\t\t\t\tRemotePort: \"8081\",\n\t\t\t\tLocalIP:    \"microsoft.com\",\n\t\t\t\tLocalPort:  \"80\",\n\t\t\t},\n\t\t},\n\t}\n\n\t_, err := frpc.Execute(common, svc)\n\n\tassert.NoError(t, err)\n}\n"
  },
  {
    "path": "pkg/frp/frpc/manager.go",
    "content": "package frpc\n\nimport (\n\t\"fmt\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/txn2/kubefwd/pkg/fwdport\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/constants\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/frp/models\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/notify\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/notify/killsignal\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/utils/hostsutils\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/utils/tcputil\"\n\t\"strings\"\n\t\"time\"\n)\n\ntype Manager struct {\n\tCommon      models.Common\n\tServicePair []ServicePair\n}\n\nfunc NewManager(common models.Common, servicePair []ServicePair, hostFile *fwdport.HostFileWithLock) *Manager {\n\n\treturn &Manager{\n\t\tcommon,\n\t\tservicePair,\n\t}\n}\n\nfunc (m *Manager) RunFRPc() {\n\n\tfor killsignal.HasKillSignaled() == false {\n\n\t\tm.WaitForLocalPortToBecomeAvailable()\n\n\t\tcancelChan, err := Execute(m.Common, m.ServicePair)\n\t\tif err != nil {\n\t\t\tlog.Panicf(\"unable to start frp client, err: %s\", err.Error())\n\t\t}\n\n\t\tgo func() {\n\t\t\tm.WaitForLocalPortToBecomeUnavailableAndCancel(cancelChan)\n\t\t}()\n\n\t\tcancelChan.WaitForCancellation()\n\t}\n\n\tlog.Info(\"exit frp manager\")\n\n}\n\nfunc (m *Manager) WaitForLocalPortToBecomeAvailable() {\n\n\t// TODO: assuming we are using a single service at the time\n\thost := m.ServicePair[0].Service.LocalIP\n\tport := m.ServicePair[0].Service.LocalPort\n\n\tfor killsignal.HasKillSignaled() == false && tcputil.IsAvailable(host, port) == false {\n\t\ttime.Sleep(time.Millisecond * 500)\n\t}\n}\n\nfunc (m *Manager) WaitForLocalPortToBecomeUnavailableAndCancel(channel *notify.CancellationChannel) {\n\n\t// TODO: assuming we are using a single service at the time\n\thost := m.ServicePair[0].Service.LocalIP\n\tport := m.ServicePair[0].Service.LocalPort\n\n\tfor killsignal.HasKillSignaled() == false && channel.IsCancelled() == false && tcputil.IsAvailable(host, port) {\n\t\ttime.Sleep(time.Millisecond * 500)\n\t}\n\n\tif killsignal.HasKillSignaled() == false && channel.IsCancelled() == false {\n\t\tchannel.CancelWithReason(fmt.Errorf(\"service is unavailable at address: %s:%s, shutting down frpc\", host, port))\n\t}\n}\n\nfunc ChangeHostToKubeTunnel(hostFile *fwdport.HostFileWithLock, kubeTunnelServerDns string) {\n\n\toriginalServiceDns := strings.Replace(kubeTunnelServerDns, fmt.Sprintf(\"%s-\", constants.KubetunnelSlug), \"\", 1)\n\n\thostsutils.ReplaceAddressForHost(hostFile.Hosts, originalServiceDns, kubeTunnelServerDns)\n}\n"
  },
  {
    "path": "pkg/frp/frpc/manager_test.go",
    "content": "package frpc_test\n\nimport (\n\t\"github.com/we-dcode/kube-tunnel/pkg/frp/frpc\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/frp/models\"\n\t\"testing\"\n)\n\nfunc TestFrpClientManager(t *testing.T) {\n\n\tcommon := models.Common{\n\t\tServerAddress: \"kubetunnel-demo\",\n\t\tServerPort:    \"7000\",\n\t}\n\n\tsvc := []frpc.ServicePair{\n\t\t{\n\t\t\tName: \"local_app\",\n\t\t\tService: models.Service{\n\t\t\t\tType:       \"tcp\",\n\t\t\t\tRemotePort: \"80\",\n\t\t\t\tLocalIP:    \"localhost\",\n\t\t\t\tLocalPort:  \"22285\",\n\t\t\t},\n\t\t},\n\t}\n\n\tmanager := frpc.NewManager(common, svc, nil)\n\n\tmanager.RunFRPc()\n\n}\n"
  },
  {
    "path": "pkg/frp/frputil/parser.go",
    "content": "package frputil\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"github.com/fatedier/frp/pkg/config\"\n\t\"os\"\n\t\"path/filepath\"\n)\n\nfunc ParseClientConfig(toml []byte) (\n\tcfg config.ClientCommonConf,\n\tpxyCfgs map[string]config.ProxyConf,\n\tvisitorCfgs map[string]config.VisitorConf,\n\terr error,\n) {\n\tvar content []byte\n\n\tcontent, err = config.RenderContent(toml)\n\n\t//content, err = config.GetRenderedConfFromFile(filePath)\n\tif err != nil {\n\t\treturn\n\t}\n\tconfigBuffer := bytes.NewBuffer(nil)\n\tconfigBuffer.Write(content)\n\n\t// Parse common section.\n\tcfg, err = config.UnmarshalClientConfFromIni(content)\n\tif err != nil {\n\t\treturn\n\t}\n\tcfg.Complete()\n\tif err = cfg.Validate(); err != nil {\n\t\terr = fmt.Errorf(\"Parse config error: %v\", err)\n\t\treturn\n\t}\n\n\t// Aggregate proxy configs from include files.\n\tvar buf []byte\n\tbuf, err = getIncludeContents(cfg.IncludeConfigFiles)\n\tif err != nil {\n\t\terr = fmt.Errorf(\"getIncludeContents error: %v\", err)\n\t\treturn\n\t}\n\tconfigBuffer.WriteString(\"\\n\")\n\tconfigBuffer.Write(buf)\n\n\t// Parse all proxy and visitor configs.\n\tpxyCfgs, visitorCfgs, err = config.LoadAllProxyConfsFromIni(cfg.User, configBuffer.Bytes(), cfg.Start)\n\tif err != nil {\n\t\treturn\n\t}\n\treturn\n}\n\n// getIncludeContents renders all configs from paths.\n// files format can be a single file path or directory or regex path.\nfunc getIncludeContents(paths []string) ([]byte, error) {\n\tout := bytes.NewBuffer(nil)\n\tfor _, path := range paths {\n\t\tabsDir, err := filepath.Abs(filepath.Dir(path))\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif _, err := os.Stat(absDir); os.IsNotExist(err) {\n\t\t\treturn nil, err\n\t\t}\n\t\tfiles, err := os.ReadDir(absDir)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfor _, fi := range files {\n\t\t\tif fi.IsDir() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tabsFile := filepath.Join(absDir, fi.Name())\n\t\t\tif matched, _ := filepath.Match(filepath.Join(absDir, filepath.Base(path)), absFile); matched {\n\t\t\t\ttmpContent, err := config.GetRenderedConfFromFile(absFile)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"render extra config %s error: %v\", absFile, err)\n\t\t\t\t}\n\t\t\t\tout.Write(tmpContent)\n\t\t\t\tout.WriteString(\"\\n\")\n\t\t\t}\n\t\t}\n\t}\n\treturn out.Bytes(), nil\n}\n"
  },
  {
    "path": "pkg/frp/frputil/parser_test.go",
    "content": "package frputil_test\n\nimport (\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/frp/frputil\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/frp/models\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/utils/tomlutil\"\n\t\"testing\"\n)\n\nfunc TestGetServiceWithSinglePortOnDefaultNamespace(t *testing.T) {\n\n\tfrpConfig := models.FrpClientConfig{\n\t\t\"common\": models.Common{\n\t\t\tServerAddress: \"localhost\",\n\t\t\tServerPort:    \"7001\",\n\t\t},\n\t\t\"rabbit\": models.Service{\n\t\t\tType:       \"tcp\",\n\t\t\tRemotePort: \"5672\",\n\t\t\tLocalIP:    \"localhost\",\n\t\t\tLocalPort:  \"5672\",\n\t\t},\n\t\t\"rabbit_management_ui\": models.Service{\n\t\t\tType:       \"tcp\",\n\t\t\tRemotePort: \"15672\",\n\t\t\tLocalIP:    \"localhost\",\n\t\t\tLocalPort:  \"15672\",\n\t\t},\n\t}\n\n\ttomlString, err := tomlutil.Marshal(frpConfig)\n\n\tconf, pxyCfgs, visitorCfgs, err := frputil.ParseClientConfig([]byte(tomlString))\n\n\tassert.NotNil(t, conf)\n\tassert.NotNil(t, pxyCfgs)\n\tassert.NotNil(t, visitorCfgs)\n\tassert.NoError(t, err)\n}\n"
  },
  {
    "path": "pkg/frp/models/frp_client_config.go",
    "content": "package models\n\ntype FrpClientConfig map[string]interface{}\n\n//type FrpClientConfig struct {\n//\tCommon Common `toml:\"common,omitempty\"`\n//\tServices map[string]Service `toml:\"services,omitempty\"`\n//}\n\ntype Common struct {\n\tServerAddress string `toml:\"server_addr,omitempty\"`\n\tServerPort    string `toml:\"server_port,omitempty\"`\n}\n\ntype Service struct {\n\tType       string `toml:\"type,omitempty\"`\n\tRemotePort string `toml:\"remote_port,omitempty\"`\n\tLocalIP    string `toml:\"local_ip,omitempty\"`\n\tLocalPort  string `toml:\"local_port,omitempty\"`\n}\n"
  },
  {
    "path": "pkg/installer/pod.go",
    "content": "package installer\n\n\n"
  },
  {
    "path": "pkg/kubefwd/fwdsvcregistry/fwdsvcregistryaccessor.go",
    "content": "package fwdsvcregistry\n\n\n\n"
  },
  {
    "path": "pkg/kubefwd/kubefwd.go",
    "content": "package kubefwd\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"github.com/bep/debounce\"\n\t\"github.com/txn2/kubefwd/cmd/kubefwd/services\"\n\t\"github.com/txn2/kubefwd/pkg/fwdcfg\"\n\t\"github.com/txn2/kubefwd/pkg/fwdhost\"\n\t\"github.com/txn2/kubefwd/pkg/fwdport\"\n\t\"github.com/txn2/kubefwd/pkg/fwdservice\"\n\t\"github.com/txn2/kubefwd/pkg/fwdsvcregistry\"\n\t\"github.com/txn2/txeh\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/clients/kube\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/constants\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/models\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/notify/killsignal\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/utils/hostsutils\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/utils/tcputil\"\n\t\"io/ioutil\"\n\tv1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/selection\"\n\t\"k8s.io/apimachinery/pkg/watch\"\n\t\"k8s.io/client-go/tools/cache\"\n\t\"os\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cobra\"\n)\n\nvar globalUsage = ``\nvar Version = \"0.0.0\"\n\nfunc init() {\n\t// quiet version\n\targs := os.Args[1:]\n\tif len(args) == 2 && args[0] == \"version\" && args[1] == \"quiet\" {\n\t\tfmt.Println(Version)\n\t\tos.Exit(0)\n\t}\n\n\tlog.SetOutput(&LogOutputSplitter{})\n\tif len(args) > 0 && args[0] == \"completion\" {\n\t\tlog.SetOutput(ioutil.Discard)\n\t}\n}\n\nfunc newRootCmd() *cobra.Command {\n\tcmd := &cobra.Command{\n\t\tUse:   \"kubefwd\",\n\t\tShort: \"Expose Kubernetes services for local development.\",\n\t\tExample: \" kubefwd services --help\\n\" +\n\t\t\t\"  kubefwd svc -n the-project\\n\" +\n\t\t\t\"  kubefwd svc -n the-project -l env=dev,component=api\\n\" +\n\t\t\t\"  kubefwd svc -n the-project -f metadata.name=service-name\\n\" +\n\t\t\t\"  kubefwd svc -n default -l \\\"app in (ws, api)\\\"\\n\" +\n\t\t\t\"  kubefwd svc -n default -n the-project\\n\" +\n\t\t\t\"  kubefwd svc -n the-project -m 80:8080 -m 443:1443\\n\" +\n\t\t\t\"  kubefwd svc -n the-project -z path/to/conf.yml\\n\" +\n\t\t\t\"  kubefwd svc -n the-project -r svc.ns:127.3.3.1\\n\" +\n\t\t\t\"  kubefwd svc --all-namespaces\",\n\n\t\tLong: globalUsage,\n\t}\n\n\tcmd.AddCommand(services.Cmd)\n\n\treturn cmd\n}\n\ntype LogOutputSplitter struct{}\n\nfunc (splitter *LogOutputSplitter) Write(p []byte) (n int, err error) {\n\tif bytes.Contains(p, []byte(\"level=error\")) || bytes.Contains(p, []byte(\"level=warn\")) {\n\t\treturn os.Stderr.Write(p)\n\t}\n\treturn os.Stdout.Write(p)\n}\n\n// Execute - This code was copied from kubefwd and modified a bit to support kubetunnel requirements\nfunc Execute(kubeClient *kube.Kube, frpsValues *models.KubeTunnelResourceSpec, channel chan error) *fwdport.HostFileWithLock {\n\n\tlog.Println(\"Press [Ctrl-C] to stop forwarding.\")\n\tlog.Println(\"'cat /etc/hosts' to see all host entries.\")\n\n\thostFile, err := txeh.NewHostsDefault()\n\tif err != nil {\n\t\tlog.Fatalf(\"HostFile error: %s\", err.Error())\n\t\tos.Exit(1)\n\t}\n\n\tlog.Printf(\"Loaded hosts file %s\\n\", hostFile.ReadFilePath)\n\n\tmsg, err := fwdhost.BackupHostFile(hostFile)\n\tif err != nil {\n\t\tlog.Fatalf(\"Error backing up hostfile: %s\\n\", err.Error())\n\t\tos.Exit(1)\n\t}\n\n\thostsutils.HostsCleanup(hostFile)\n\n\tlog.Printf(\"HostFile management: %s\", msg)\n\n\t// if no context override\n\tfwdsvcregistry.Init(killsignal.CancellationChannel.C)\n\n\tnsWatchesDone := &sync.WaitGroup{} // We'll wait on this to exit the program. Done() indicates that all namespace watches have shutdown cleanly.\n\n\tnsWatchesDone.Add(1)\n\n\tconfigGetter := fwdcfg.NewConfigGetter()\n\n\trestClient, _ := configGetter.GetRESTClient()\n\n\tnameSpaceOpts := services.NamespaceOpts{\n\t\tClientSet: *kubeClient.InnerKubeClient,\n\t\tNamespace: kubeClient.Namespace,\n\n\t\t// For parallelization of ip handout,\n\t\t// each cluster and namespace has its own ip range\n\t\tNamespaceIPLock:   &sync.Mutex{},\n\t\tListOptions:       metav1.ListOptions{},\n\t\tHostFile:          &fwdport.HostFileWithLock{Hosts: hostFile},\n\t\tClientConfig:      *kubeClient.Config,\n\t\tDomain:            constants.KubetunnelSlug,\n\t\tRESTClient:        *restClient,\n\t\tClusterN:          0,\n\t\tNamespaceN:        0,\n\t\tManualStopChannel: killsignal.CancellationChannel.C,\n\t}\n\n\tgo func(npo services.NamespaceOpts) {\n\t\twatchServiceEvents(&nameSpaceOpts, killsignal.CancellationChannel.C)\n\t\tnsWatchesDone.Done()\n\t}(nameSpaceOpts)\n\n\tgo func() {\n\t\tnsWatchesDone.Wait()\n\t\tlog.Debugf(\"namespace watchers is done\")\n\n\t\t// Shutdown all active services\n\t\t<-fwdsvcregistry.Done()\n\n\t\tlog.Infof(\"Clean exit\")\n\t}()\n\n\tgo func() {\n\t\tWaitUntilKubeTunnelIsUp(frpsValues, fwdsvcregistry.Done())\n\t\tchannel <- nil\n\t}()\n\n\treturn nameSpaceOpts.HostFile\n}\n\nfunc WaitUntilKubeTunnelIsUp(frpsValues *models.KubeTunnelResourceSpec, done <-chan struct{}) {\n\n\thost := frpsValues.KubeTunnelServiceName()\n\n\t// TODO: Do I need to wait for interrupt here or it's already handled?\n\tfor tcputil.IsAvailable(host, constants.FRPServerPort) == false {\n\n\t\t// If Done already request (Interrupt event) then break the loop\n\t\tif IsChannelClosed(done) {\n\t\t\tbreak\n\t\t}\n\n\t\ttime.Sleep(200 * time.Millisecond)\n\t}\n}\n\nfunc IsChannelClosed(ch <-chan struct{}) bool {\n\tselect {\n\tcase <-ch:\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\nfunc watchServiceEvents(opts *services.NamespaceOpts, stopListenCh <-chan struct{}) {\n\t// Apply filtering\n\toptionsModifier := func(options *metav1.ListOptions) {\n\t\toptions.FieldSelector = opts.ListOptions.FieldSelector\n\t\toptions.LabelSelector = opts.ListOptions.LabelSelector\n\t}\n\n\t// Construct the informer object which will query the api server,\n\t// and send events to our handler functions\n\t// https://engineering.bitnami.com/articles/kubewatch-an-example-of-kubernetes-custom-controller.html\n\t_, controller := cache.NewInformer(\n\t\t&cache.ListWatch{\n\t\t\tListFunc: func(options metav1.ListOptions) (runtime.Object, error) {\n\t\t\t\toptionsModifier(&options)\n\t\t\t\treturn opts.ClientSet.CoreV1().Services(opts.Namespace).List(context.TODO(), options)\n\t\t\t},\n\t\t\tWatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {\n\t\t\t\toptions.Watch = true\n\t\t\t\toptionsModifier(&options)\n\t\t\t\treturn opts.ClientSet.CoreV1().Services(opts.Namespace).Watch(context.TODO(), options)\n\t\t\t},\n\t\t},\n\t\t&v1.Service{},\n\t\t0,\n\t\tcache.ResourceEventHandlerFuncs{\n\t\t\tAddFunc: func(obj interface{}) {\n\t\t\t\tAddServiceHandler(opts, obj)\n\t\t\t},\n\t\t\tDeleteFunc: opts.DeleteServiceHandler,\n\t\t\tUpdateFunc: func(oldObj, newObj interface{}) {\n\t\t\t\tUpdateServiceHandler(opts, oldObj, newObj)\n\t\t\t},\n\t\t},\n\t)\n\n\t// Start the informer, blocking call until we receive a stop signal\n\tcontroller.Run(stopListenCh)\n\tlog.Infof(\"Stopped watching Service events in namespace %s in %s context\", opts.Namespace, opts.Context)\n}\n\nfunc AddServiceHandler(opts *services.NamespaceOpts, obj interface{}) {\n\n\tsvc, ok := obj.(*v1.Service)\n\tif !ok {\n\t\topts.AddServiceHandler(obj)\n\t\treturn\n\t}\n\n\tselector := labels.Set(svc.Spec.Selector).AsSelector()\n\n\t_, containsKey := svc.Spec.Selector[constants.KubetunnelSlug]\n\n\tif containsKey == false && strings.HasPrefix(svc.Name, constants.KubetunnelSlug) == false {\n\n\t\tnotKubeTunnelAgent, err := labels.NewRequirement(fmt.Sprintf(\"%s-app\", constants.KubetunnelSlug), selection.NotEquals, []string{svc.Name})\n\n\t\tif err != nil {\n\n\t\t\tlog.Panicf(\"PANIC: unable to port-forward svc: '%s', please see internal error and try again. err: %s\", svc.Name, err.Error())\n\t\t}\n\n\t\tselector = selector.Add([]labels.Requirement{*notKubeTunnelAgent}...)\n\n\t}\n\n\t// Check if service has a valid config to do forwarding\n\n\tstringSelector := selector.String()\n\n\tif stringSelector == \"\" {\n\t\tlog.Warnf(\"WARNING: No Pod selector for service %s.%s, skipping\\n\", svc.Name, svc.Namespace)\n\t\treturn\n\t}\n\n\t// Define a service to forward\n\tsvcfwd := &fwdservice.ServiceFWD{\n\t\tClientSet:                opts.ClientSet,\n\t\tContext:                  opts.Context,\n\t\tNamespace:                opts.Namespace,\n\t\tHostfile:                 opts.HostFile,\n\t\tClientConfig:             opts.ClientConfig,\n\t\tRESTClient:               opts.RESTClient,\n\t\tNamespaceN:               opts.NamespaceN,\n\t\tClusterN:                 opts.ClusterN,\n\t\tDomain:                   opts.Domain,\n\t\tPodLabelSelector:         stringSelector,\n\t\tNamespaceServiceLock:     opts.NamespaceIPLock,\n\t\tSvc:                      svc,\n\t\tHeadless:                 svc.Spec.ClusterIP == \"None\",\n\t\tPortForwards:             make(map[string]*fwdport.PortForwardOpts),\n\t\tSyncDebouncer:            debounce.New(5 * time.Second),\n\t\tDoneChannel:              make(chan struct{}),\n\t\tPortMap:                  opts.ParsePortMap(nil),\n\t\tForwardConfigurationPath: \"\",\n\t\tForwardIPReservations:    nil,\n\t}\n\n\t// Add the service to the catalog of services being forwarded\n\tfwdsvcregistry.Add(svcfwd)\n\n}\n\nfunc UpdateServiceHandler(opts *services.NamespaceOpts, oldObj interface{}, newObj interface{}) {\n\tkey, err := cache.MetaNamespaceKeyFunc(newObj)\n\tif err == nil {\n\t\tlog.Printf(\"update service %s. replacing dns port-forwarding\", key)\n\t}\n\n\topts.DeleteServiceHandler(oldObj)\n\n\tAddServiceHandler(opts, newObj)\n}\n"
  },
  {
    "path": "pkg/kubetunnel.go",
    "content": "package pkg\n\nimport (\n\t\"fmt\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/txn2/kubefwd/pkg/fwdport\"\n\t\"github.com/txn2/kubefwd/pkg/utils\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/clients/helm\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/clients/kube\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/clients/kube/servicecontext\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/constants\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/frp/frpc\"\n\tfrpmodels \"github.com/we-dcode/kube-tunnel/pkg/frp/models\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/kubefwd\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/models\"\n\t\"os\"\n)\n\ntype KubeTunnel struct {\n\tkubeClient *kube.Kube\n\thelmClient *helm.Helm\n}\n\ntype KubeTunnelConf struct {\n\tServiceName       string\n\tKubeTunnelPortMap map[string]string\n\tLocalIP           string\n}\n\nfunc MustNewKubeTunnel(kubeConfig string, namespace string, privileged bool) *KubeTunnel {\n\n\tif len(kubeConfig) > 0 {\n\t\t_ = os.Setenv(\"KUBECONFIG\", kubeConfig) // Workaround for internal client created by kubefwd\n\t}\n\n\tkubeClient := kube.MustNew(kubeConfig, namespace)\n\n\terr := kubeClient.ConnectivityCheck()\n\tif err != nil {\n\t\tlog.Panicf(err.Error())\n\t}\n\n\terr = kubeClient.RBACCheck()\n\tif err != nil {\n\t\tlog.Panicf(err.Error())\n\t}\n\n\tif privileged {\n\t\terr = CheckRootPermissions()\n\t\tif err != nil {\n\t\t\tlog.Panicf(err.Error())\n\t\t}\n\t}\n\n\thelmClient := helm.MustNew(kubeClient)\n\n\treturn &KubeTunnel{\n\t\tkubeClient: kubeClient,\n\t\thelmClient: helmClient,\n\t}\n}\n\nfunc (ct *KubeTunnel) Install(operatorVersion string) {\n\n\terr := ct.helmClient.InstallKubeTunnelOperator(operatorVersion)\n\tif err != nil {\n\t\tlog.Panic(err.Error())\n\t}\n}\n\nfunc (ct *KubeTunnel) CreateTunnel(tunnelConf KubeTunnelConf) {\n\n\tsvcCtx, err := ct.kubeClient.GetServiceContext(tunnelConf.ServiceName)\n\tif err != nil {\n\t\tlog.Panic(err.Error())\n\t}\n\n\tlabels, err := ct.kubeClient.GetPodLabelsByLabelSelector(ct.kubeClient.Namespace, svcCtx.LabelSelector)\n\tif err != nil {\n\t\tlog.Panic(err.Error())\n\t}\n\n\tkubeTunnelResourceSpec := servicecontext.ToKubeTunnelResourceSpec(svcCtx, labels)\n\n\tif err = ct.kubeClient.CreateKubeTunnelResource(kubeTunnelResourceSpec); err != nil {\n\n\t\tlog.Panicf(\"fail creating kubetunnel CRD, internal error: %s\", err.Error())\n\t}\n\n\tkubefwdSyncChannel := make(chan error)\n\tvar hostFile *fwdport.HostFileWithLock\n\n\tgo func(ktrs *models.KubeTunnelResourceSpec) {\n\t\thostFile = kubefwd.Execute(ct.kubeClient, ktrs, kubefwdSyncChannel)\n\t}(&kubeTunnelResourceSpec)\n\n\terr = <-kubefwdSyncChannel\n\n\tif err != nil {\n\t\tlog.Panicf(\"fail executing kubefwd: %s\", err.Error())\n\t}\n\n\tlog.Info(\"executing frpc\")\n\n\tcommon := frpmodels.Common{\n\t\tServerAddress: fmt.Sprintf(\"%s-%s\", constants.KubetunnelSlug, kubeTunnelResourceSpec.ServiceName),\n\t\tServerPort:    constants.FRPServerPort,\n\t}\n\n\tservicePortsPairs := servicecontext.ToFRPClientPairs(tunnelConf.LocalIP, tunnelConf.KubeTunnelPortMap, svcCtx)\n\n\tfrpcManager := frpc.NewManager(common, servicePortsPairs, hostFile)\n\n\tfrpcManager.RunFRPc()\n}\n\nfunc CheckRootPermissions() error {\n\n\thasRoot, err := utils.CheckRoot()\n\n\tif !hasRoot {\n\t\tlog.Errorf(`\nThis program requires superuser privileges to run. These\nprivileges are required to add IP address aliases to your\nloopback interface. Superuser privileges are also needed\nto listen on low port numbers for these IP addresses.\n\nTry:\n - sudo -E kubetunnel (Unix)\n - Running a shell with administrator rights (Windows)\n\n`)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"root check failure: %s\", err.Error())\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/kubetunnel_test.go",
    "content": "package pkg_test\n\nimport (\n\t\"github.com/we-dcode/kube-tunnel/pkg\"\n\t\"testing\"\n)\n\nfunc TestRunningKubeTunnelE2E2(t *testing.T) {\n\n\tkubeTunnel := pkg.MustNewKubeTunnel(\"/Users/maordavidov/dcode/gitlab-cicd-kubeconfig.yaml\", \"kubetunnel\", true)\n\n\t//kubeTunnel.Install(\"0.0.12\")\n\n\tkubeTunnel.CreateTunnel(pkg.KubeTunnelConf{\n\t\tServiceName: \"nginx\",\n\t\tLocalIP:     \"localhost\",\n\t\tKubeTunnelPortMap: map[string]string{\n\t\t\t\"8081\": \"80\",\n\t\t},\n\t})\n\n\t//assert.NoError(t, err)\n}\n"
  },
  {
    "path": "pkg/models/kubetunnel_resource.go",
    "content": "package models\n\nimport (\n\t\"fmt\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"strings\"\n)\n\ntype KubeTunnelResource struct {\n\tmetav1.TypeMeta\n\tMetadata metav1.ObjectMeta      `json:\"metadata\" yaml:\"metadata\"`\n\tSpec     KubeTunnelResourceSpec `json:\"spec\" yaml:\"spec\"`\n}\n\ntype KubeTunnelResourceSpec struct {\n\tPorts       Ports             `json:\"env_ports\" yaml:\"env_ports\"`\n\tServiceName string            `json:\"env_service_name,omitempty\" yaml:\"env_service_name,omitempty\"`\n\tPodLabels   map[string]string `json:\"pod_labels,omitempty\" yaml:\"pod_labels,omitempty\"`\n}\n\nfunc (v *KubeTunnelResourceSpec) KubeTunnelServiceName() string {\n\n\treturn fmt.Sprintf(\"kubetunnel-%s\", v.ServiceName)\n}\n\ntype Ports struct {\n\tValues []string\n}\n\nfunc (p Ports) String() string {\n\n\treturn strings.Join(p.Values, \",\")\n}\n\nfunc (p Ports) MarshalYAML() (interface{}, error) {\n\n\treturn fmt.Sprintf(\"\\\"%s\\\"\", p.String()), nil\n}\n\nfunc (p *Ports) UnmarshalJSON(b []byte) error {\n\n\ts := string(b)\n\n\tvalues := strings.Split(s, \",\")\n\n\tfor _, value := range values {\n\t\tp.Values = append(p.Values, strings.Trim(value, \"\\\"\"))\n\t}\n\n\treturn nil\n}\n\nfunc (p Ports) MarshalJSON() ([]byte, error) {\n\treturn []byte(fmt.Sprintf(\"\\\"%s\\\"\", p.String())), nil\n}\n"
  },
  {
    "path": "pkg/notify/cancellation_channel.go",
    "content": "package notify\n\nimport \"sync\"\n\ntype CancellationChannel struct {\n\tonce     sync.Once\n\tC        chan struct{}\n\tReason   error\n\tcallback func()\n}\n\nfunc NewCancellationChannel() *CancellationChannel {\n\n\treturn &CancellationChannel{\n\t\tC: make(chan struct{}),\n\t}\n}\n\nfunc NewCancellationChannelWithCallback(callback func()) *CancellationChannel {\n\n\treturn &CancellationChannel{\n\t\tC:        make(chan struct{}),\n\t\tcallback: callback,\n\t}\n}\n\nfunc (s *CancellationChannel) WaitForCancellation() {\n\t<-s.C\n}\n\nfunc (s *CancellationChannel) Cancel() {\n\ts.once.Do(func() {\n\t\tclose(s.C)\n\t\tif s.callback != nil {\n\t\t\ts.callback()\n\t\t}\n\t})\n}\n\nfunc (s *CancellationChannel) CancelWithReason(reason error) {\n\ts.Cancel()\n\ts.Reason = reason\n}\n\nfunc (s *CancellationChannel) IsCancelled() bool {\n\n\tisCancelled := true\n\n\tselect {\n\tcase <-s.C:\n\tdefault:\n\t\tisCancelled = false\n\t}\n\n\treturn isCancelled\n}\n"
  },
  {
    "path": "pkg/notify/cancellation_channel_test.go",
    "content": "package notify_test\n\nimport (\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/notify\"\n\t\"testing\"\n)\n\nfunc TestSignal_HasNotified(t *testing.T) {\n\n\tsignal := notify.NewCancellationChannel()\n\n\tassert.False(t, signal.IsCancelled())\n\n\tsignal.Cancel()\n\n\tassert.True(t, signal.IsCancelled())\n}\n\nfunc TestSignal_CancelledTwice(t *testing.T) {\n\n\tsignal := notify.NewCancellationChannel()\n\n\tsignal.Cancel()\n\tsignal.Cancel()\n\tassert.True(t, signal.IsCancelled())\n}\n"
  },
  {
    "path": "pkg/notify/killsignal/killsignal.go",
    "content": "package killsignal\n\nimport (\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/notify\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\t\"time\"\n)\n\nvar (\n\tCancellationChannel *notify.CancellationChannel\n)\n\nfunc init() {\n\n\tCancellationChannel = notify.NewCancellationChannel()\n\n\tgo func() {\n\t\tsigint := make(chan os.Signal, 1)\n\t\tsignal.Notify(sigint, os.Interrupt, syscall.SIGTERM)\n\t\tdefer func() {\n\t\t\tsignal.Stop(sigint)\n\n\t\t\ttime.Sleep(time.Second * 1)\n\t\t\tlog.Info(\"Good bye\")\n\t\t\tos.Exit(0)\n\t\t}()\n\t\t<-sigint\n\t\tlog.Infof(\"Received shutdown signal\")\n\t\tCancellationChannel.Cancel()\n\t}()\n}\n\nfunc WaitForKillSignal() {\n\tCancellationChannel.WaitForCancellation()\n}\n\nfunc HasKillSignaled() bool {\n\treturn CancellationChannel.IsCancelled()\n}\n"
  },
  {
    "path": "pkg/operator/.dockerignore",
    "content": "# More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file\n# Ignore build and test binaries.\nbin/\ntestbin/\n"
  },
  {
    "path": "pkg/operator/.gitignore",
    "content": "\n# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\nbin\n\n# editor and IDE paraphernalia\n.idea\n*.swp\n*.swo\n*~\n"
  },
  {
    "path": "pkg/operator/PROJECT",
    "content": "domain: dcode.tech\nlayout:\n- hybrid.helm.sdk.operatorframework.io/v1-alpha\nplugins:\n  manifests.sdk.operatorframework.io/v2: {}\n  scorecard.sdk.operatorframework.io/v2: {}\nprojectName: operator\nrepo: github.com/we-dcode/kube-tunnel\nresources:\n- api:\n    crdVersion: v1\n    namespaced: true\n  domain: dcode.tech\n  group: application\n  kind: Kubetunnel\n  version: v1\nversion: \"3\"\n"
  },
  {
    "path": "pkg/operator/bundle/manifests/application.dcode.tech_kubetunnels.yaml",
    "content": "apiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  creationTimestamp: null\n  name: kubetunnels.application.dcode.tech\nspec:\n  group: application.dcode.tech\n  names:\n    kind: Kubetunnel\n    listKind: KubetunnelList\n    plural: kubetunnels\n    singular: kubetunnel\n  scope: Namespaced\n  versions:\n  - additionalPrinterColumns:\n    - jsonPath: .spec.isConnected\n      name: Is Connected\n      type: boolean\n    - jsonPath: .spec.client\n      name: Client\n      type: string\n    name: v1\n    schema:\n      openAPIV3Schema:\n        description: Kubetunnel is the Schema for the kubetunnels API\n        properties:\n          apiVersion:\n            description: 'APIVersion defines the versioned schema of this representation\n              of an object. Servers should convert recognized schemas to the latest\n              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'\n            type: string\n          client:\n            default: none\n            description: Client defines name of client\n            type: string\n            x-kubernetes-preserve-unknown-fields: true\n          isConnected:\n            default: false\n            description: Connected defines if connected to client\n            type: boolean\n            x-kubernetes-preserve-unknown-fields: true\n          kind:\n            description: 'Kind is a string value representing the REST resource this\n              object represents. Servers may infer this from the endpoint the client\n              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'\n            type: string\n          metadata:\n            type: object\n          spec:\n            description: Spec defines the desired state of Kubetunnel\n            type: object\n            x-kubernetes-preserve-unknown-fields: true\n          status:\n            description: Status defines the observed state of Kubetunnel\n            type: object\n            x-kubernetes-preserve-unknown-fields: true\n        type: object\n    served: true\n    storage: true\n    subresources:\n      status: {}\nstatus:\n  acceptedNames:\n    kind: \"\"\n    plural: \"\"\n  conditions: null\n  storedVersions: null\n"
  },
  {
    "path": "pkg/operator/bundle/manifests/operator-controller-manager-metrics-service_v1_service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  creationTimestamp: null\n  labels:\n    control-plane: controller-manager\n  name: operator-controller-manager-metrics-service\nspec:\n  ports:\n  - name: https\n    port: 8443\n    protocol: TCP\n    targetPort: https\n  selector:\n    control-plane: controller-manager\nstatus:\n  loadBalancer: {}\n"
  },
  {
    "path": "pkg/operator/bundle/manifests/operator-kube-tunnel-operator_v1_service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  creationTimestamp: null\n  labels:\n    app.kubernetes.io/instance: kube-tunnel-operator\n  name: operator-kube-tunnel-operator\nspec:\n  internalTrafficPolicy: Cluster\n  ipFamilies:\n  - IPv4\n  ipFamilyPolicy: SingleStack\n  ports:\n  - name: http\n    port: 80\n    targetPort: http\n  selector:\n    control-plane: controller-manager\n  type: ClusterIP\nstatus:\n  loadBalancer: {}\n"
  },
  {
    "path": "pkg/operator/bundle/manifests/operator-manager-config_v1_configmap.yaml",
    "content": "apiVersion: v1\ndata:\n  controller_manager_config.yaml: |\n    apiVersion: controller-runtime.sigs.k8s.io/v1alpha1\n    kind: ControllerManagerConfig\n    health:\n      healthProbeBindAddress: :8081\n    metrics:\n      bindAddress: 127.0.0.1:8080\n    webhook:\n      port: 9443\n    leaderElection:\n      leaderElect: true\n      resourceName: 5dbd2493.dcode.tech\n    # leaderElectionReleaseOnCancel defines if the leader should step down volume\n    # when the Manager ends. This requires the binary to immediately end when the\n    # Manager is stopped, otherwise, this setting is unsafe. Setting this significantly\n    # speeds up voluntary leader transitions as the new leader don't have to wait\n    # LeaseDuration time first.\n    # In the default scaffold provided, the program ends immediately after\n    # the manager stops, so would be fine to enable this option. However,\n    # if you are doing or is intended to do any operation such as perform cleanups\n    # after the manager stops then its usage might be unsafe.\n    # leaderElectionReleaseOnCancel: true\nkind: ConfigMap\nmetadata:\n  name: operator-manager-config\n"
  },
  {
    "path": "pkg/operator/bundle/manifests/operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  creationTimestamp: null\n  name: operator-metrics-reader\nrules:\n- nonResourceURLs:\n  - /metrics\n  verbs:\n  - get\n"
  },
  {
    "path": "pkg/operator/bundle/manifests/operator.clusterserviceversion.yaml",
    "content": "apiVersion: operators.coreos.com/v1alpha1\nkind: ClusterServiceVersion\nmetadata:\n  annotations:\n    alm-examples: |-\n      [\n        {\n          \"apiVersion\": \"application.dcode.tech/v1\",\n          \"kind\": \"Kubetunnel\",\n          \"metadata\": {\n            \"name\": \"kubetunnel-sample\"\n          },\n          \"spec\": {\n            \"env_ports\": \"8080\",\n            \"env_service_name\": \"nginx\",\n            \"operator\": {\n              \"service\": {\n                \"name\": \"operator-kube-tunnel-operator\"\n              }\n            },\n            \"pod_selector_labels\": {\n              \"name\": \"nginx\"\n            }\n          }\n        }\n      ]\n    capabilities: Basic Install\n    operators.operatorframework.io/builder: operator-sdk-v1.23.0\n    operators.operatorframework.io/project_layout: hybrid.helm.sdk.operatorframework.io/v1-alpha\n  name: operator.v0.0.4\n  namespace: placeholder\nspec:\n  apiservicedefinitions: {}\n  customresourcedefinitions:\n    owned:\n    - kind: Kubetunnel\n      name: kubetunnels.application.dcode.tech\n      version: v1\n  description: operator for managing kubetunnels\n  displayName: kubetunnel-operator\n  icon:\n  - base64data: \"\"\n    mediatype: \"\"\n  install:\n    spec:\n      clusterPermissions:\n      - rules:\n        - apiGroups:\n          - \"\"\n          resources:\n          - namespaces\n          - roles\n          verbs:\n          - get\n        - apiGroups:\n          - \"\"\n          - rbac.authorization.k8s.io\n          - roles.rbac.authorization.k8s.io\n          - authorization.k8s.io\n          resources:\n          - secrets\n          - configmaps\n          - rolebindings\n          - roles\n          verbs:\n          - '*'\n        - apiGroups:\n          - \"\"\n          resources:\n          - events\n          verbs:\n          - create\n        - apiGroups:\n          - application.dcode.tech\n          resources:\n          - kubetunnels\n          - kubetunnels/status\n          - kubetunnels/finalizers\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - \"\"\n          resources:\n          - serviceaccounts\n          - services\n          - roles\n          verbs:\n          - '*'\n        - apiGroups:\n          - apps\n          resources:\n          - deployments\n          verbs:\n          - '*'\n        - apiGroups:\n          - authentication.k8s.io\n          resources:\n          - tokenreviews\n          verbs:\n          - create\n        - apiGroups:\n          - authorization.k8s.io\n          resources:\n          - subjectaccessreviews\n          verbs:\n          - create\n        serviceAccountName: operator-controller-manager\n      deployments:\n      - label:\n          control-plane: controller-manager\n        name: operator-controller-manager\n        spec:\n          replicas: 1\n          selector:\n            matchLabels:\n              control-plane: controller-manager\n          strategy: {}\n          template:\n            metadata:\n              annotations:\n                kubectl.kubernetes.io/default-container: manager\n              labels:\n                control-plane: controller-manager\n            spec:\n              containers:\n              - args:\n                - --secure-listen-address=0.0.0.0:8443\n                - --upstream=http://127.0.0.1:8080/\n                - --logtostderr=true\n                - --v=0\n                image: gcr.io/kubebuilder/kube-rbac-proxy:v0.13.0\n                name: kube-rbac-proxy\n                ports:\n                - containerPort: 8443\n                  name: https\n                  protocol: TCP\n                resources:\n                  limits:\n                    cpu: 500m\n                    memory: 128Mi\n                  requests:\n                    cpu: 5m\n                    memory: 64Mi\n                securityContext:\n                  allowPrivilegeEscalation: false\n                  capabilities:\n                    drop:\n                    - ALL\n              - args:\n                - --health-probe-bind-address=:8081\n                - --metrics-bind-address=127.0.0.1:8080\n                - --leader-elect\n                - --leader-election-id=operator\n                env:\n                - name: POD_NAMESPACE\n                  valueFrom:\n                    fieldRef:\n                      fieldPath: metadata.namespace\n                image: eliranw/kube-tunnel-operator:0.0.4\n                livenessProbe:\n                  httpGet:\n                    path: /healthz\n                    port: 8081\n                  initialDelaySeconds: 15\n                  periodSeconds: 20\n                name: manager\n                ports:\n                - containerPort: 8083\n                  name: http\n                  protocol: TCP\n                readinessProbe:\n                  httpGet:\n                    path: /readyz\n                    port: 8081\n                  initialDelaySeconds: 5\n                  periodSeconds: 10\n                resources:\n                  limits:\n                    cpu: 500m\n                    memory: 128Mi\n                  requests:\n                    cpu: 10m\n                    memory: 64Mi\n                securityContext:\n                  allowPrivilegeEscalation: false\n                  capabilities:\n                    drop:\n                    - ALL\n              securityContext:\n                runAsNonRoot: true\n              serviceAccountName: operator-controller-manager\n              terminationGracePeriodSeconds: 10\n      permissions:\n      - rules:\n        - apiGroups:\n          - \"\"\n          resources:\n          - configmaps\n          verbs:\n          - get\n          - list\n          - watch\n          - create\n          - update\n          - patch\n          - delete\n        - apiGroups:\n          - coordination.k8s.io\n          resources:\n          - leases\n          verbs:\n          - get\n          - list\n          - watch\n          - create\n          - update\n          - patch\n          - delete\n        - apiGroups:\n          - \"\"\n          resources:\n          - events\n          verbs:\n          - create\n          - patch\n        serviceAccountName: operator-controller-manager\n    strategy: deployment\n  installModes:\n  - supported: false\n    type: OwnNamespace\n  - supported: false\n    type: SingleNamespace\n  - supported: false\n    type: MultiNamespace\n  - supported: true\n    type: AllNamespaces\n  keywords:\n  - tunnel\n  - kubernetes\n  - debug\n  links:\n  - name: Operator\n    url: https://operator.domain\n  maturity: alpha\n  provider:\n    name: dcode\n  version: 0.0.4\n"
  },
  {
    "path": "pkg/operator/bundle/metadata/annotations.yaml",
    "content": "annotations:\n  # Core bundle annotations.\n  operators.operatorframework.io.bundle.mediatype.v1: registry+v1\n  operators.operatorframework.io.bundle.manifests.v1: manifests/\n  operators.operatorframework.io.bundle.metadata.v1: metadata/\n  operators.operatorframework.io.bundle.package.v1: operator\n  operators.operatorframework.io.bundle.channels.v1: alpha\n  operators.operatorframework.io.metrics.builder: operator-sdk-v1.23.0\n  operators.operatorframework.io.metrics.mediatype.v1: metrics+v1\n  operators.operatorframework.io.metrics.project_layout: hybrid.helm.sdk.operatorframework.io/v1-alpha\n\n  # Annotations for testing.\n  operators.operatorframework.io.test.mediatype.v1: scorecard+v1\n  operators.operatorframework.io.test.config.v1: tests/scorecard/\n"
  },
  {
    "path": "pkg/operator/bundle/tests/scorecard/config.yaml",
    "content": "apiVersion: scorecard.operatorframework.io/v1alpha3\nkind: Configuration\nmetadata:\n  name: config\nstages:\n- parallel: true\n  tests:\n  - entrypoint:\n    - scorecard-test\n    - basic-check-spec\n    image: quay.io/operator-framework/scorecard-test:v1.23.0\n    labels:\n      suite: basic\n      test: basic-check-spec-test\n    storage:\n      spec:\n        mountPath: {}\n  - entrypoint:\n    - scorecard-test\n    - olm-bundle-validation\n    image: quay.io/operator-framework/scorecard-test:v1.23.0\n    labels:\n      suite: olm\n      test: olm-bundle-validation-test\n    storage:\n      spec:\n        mountPath: {}\n  - entrypoint:\n    - scorecard-test\n    - olm-crds-have-validation\n    image: quay.io/operator-framework/scorecard-test:v1.23.0\n    labels:\n      suite: olm\n      test: olm-crds-have-validation-test\n    storage:\n      spec:\n        mountPath: {}\n  - entrypoint:\n    - scorecard-test\n    - olm-crds-have-resources\n    image: quay.io/operator-framework/scorecard-test:v1.23.0\n    labels:\n      suite: olm\n      test: olm-crds-have-resources-test\n    storage:\n      spec:\n        mountPath: {}\n  - entrypoint:\n    - scorecard-test\n    - olm-spec-descriptors\n    image: quay.io/operator-framework/scorecard-test:v1.23.0\n    labels:\n      suite: olm\n      test: olm-spec-descriptors-test\n    storage:\n      spec:\n        mountPath: {}\n  - entrypoint:\n    - scorecard-test\n    - olm-status-descriptors\n    image: quay.io/operator-framework/scorecard-test:v1.23.0\n    labels:\n      suite: olm\n      test: olm-status-descriptors-test\n    storage:\n      spec:\n        mountPath: {}\nstorage:\n  spec:\n    mountPath: {}\n"
  },
  {
    "path": "pkg/operator/bundle.Dockerfile",
    "content": "FROM scratch\n\n# Core bundle labels.\nLABEL operators.operatorframework.io.bundle.mediatype.v1=registry+v1\nLABEL operators.operatorframework.io.bundle.manifests.v1=manifests/\nLABEL operators.operatorframework.io.bundle.metadata.v1=metadata/\nLABEL operators.operatorframework.io.bundle.package.v1=operator\nLABEL operators.operatorframework.io.bundle.channels.v1=alpha\nLABEL operators.operatorframework.io.metrics.builder=operator-sdk-v1.23.0\nLABEL operators.operatorframework.io.metrics.mediatype.v1=metrics+v1\nLABEL operators.operatorframework.io.metrics.project_layout=hybrid.helm.sdk.operatorframework.io/v1-alpha\n\n# Labels for testing.\nLABEL operators.operatorframework.io.test.mediatype.v1=scorecard+v1\nLABEL operators.operatorframework.io.test.config.v1=tests/scorecard/\n\n# Copy files to locations specified by labels.\nCOPY bundle/manifests /manifests/\nCOPY bundle/metadata /metadata/\nCOPY bundle/tests/scorecard /tests/scorecard/\n"
  },
  {
    "path": "pkg/operator/config/crd/bases/application.dcode.tech_kubetunnels.yaml",
    "content": "---\napiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  name: kubetunnels.application.dcode.tech\nspec:\n  group: application.dcode.tech\n  names:\n    kind: Kubetunnel\n    listKind: KubetunnelList\n    plural: kubetunnels\n    singular: kubetunnel\n  scope: Namespaced\n  versions:\n  - additionalPrinterColumns:\n        - jsonPath: .spec.isConnected\n          name: Is Connected\n          type: boolean\n        - jsonPath: .spec.client\n          name: Client\n          type: string\n    name: v1\n    schema:\n      openAPIV3Schema:\n        description: Kubetunnel is the Schema for the kubetunnels API\n        properties:\n          apiVersion:\n            description: 'APIVersion defines the versioned schema of this representation\n              of an object. Servers should convert recognized schemas to the latest\n              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'\n            type: string\n          kind:\n            description: 'Kind is a string value representing the REST resource this\n              object represents. Servers may infer this from the endpoint the client\n              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'\n            type: string\n          metadata:\n            type: object\n          spec:\n            description: Spec defines the desired state of Kubetunnel\n            type: object\n            x-kubernetes-preserve-unknown-fields: true\n          status:\n            description: Status defines the observed state of Kubetunnel\n            type: object\n            x-kubernetes-preserve-unknown-fields: true\n          isConnected:\n            description: Connected defines if connected to client\n            type: boolean\n            default: false\n            x-kubernetes-preserve-unknown-fields: true\n          client:\n            description: Client defines name of client\n            type: string\n            default: none\n            x-kubernetes-preserve-unknown-fields: true\n\n        type: object\n    served: true\n    storage: true\n    subresources:\n      status: {}\n"
  },
  {
    "path": "pkg/operator/config/crd/kustomization.yaml",
    "content": "# This kustomization.yaml is not intended to be run by itself,\n# since it depends on service name and namespace that are out of this kustomize package.\n# It should be run by config/default\nresources:\n- bases/application.dcode.tech_kubetunnels.yaml\n#+kubebuilder:scaffold:crdkustomizeresource\n"
  },
  {
    "path": "pkg/operator/config/default/kustomization.yaml",
    "content": "# Adds namespace to all resources.\nnamespace: operator-system\n\n# Value of this field is prepended to the\n# names of all resources, e.g. a deployment named\n# \"wordpress\" becomes \"alices-wordpress\".\n# Note that it should also match with the prefix (text before '-') of the namespace\n# field above.\nnamePrefix: operator-\n\n# Labels to add to all resources and selectors.\n#labels:\n#- includeSelectors: true\n#  pairs:\n#    someName: someValue\n\nresources:\n- ../crd\n- ../rbac\n- ../manager\n# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in\n# crd/kustomization.yaml\n#- ../webhook\n# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required.\n#- ../certmanager\n# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.\n#- ../prometheus\n\npatchesStrategicMerge:\n# Protect the /metrics endpoint by putting it behind auth.\n# If you want your controller-manager to expose the /metrics\n# endpoint w/o any authn/z, please comment the following line.\n- manager_auth_proxy_patch.yaml\n\n# Mount the controller config file for loading manager configurations\n# through a ComponentConfig type\n#- manager_config_patch.yaml\n\n# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in\n# crd/kustomization.yaml\n#- manager_webhook_patch.yaml\n\n# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'.\n# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks.\n# 'CERTMANAGER' needs to be enabled to use ca injection\n#- webhookcainjection_patch.yaml\n\n# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix.\n# Uncomment the following replacements to add the cert-manager CA injection annotations\n#replacements:\n#  - source: # Add cert-manager annotation to ValidatingWebhookConfiguration, MutatingWebhookConfiguration and CRDs\n#      kind: Certificate\n#      group: cert-manager.io\n#      version: v1\n#      name: serving-cert # this name should match the one in certificate.yaml\n#      fieldPath: .metadata.namespace # namespace of the certificate CR\n#    targets:\n#      - select:\n#          kind: ValidatingWebhookConfiguration\n#        fieldPaths:\n#          - .metadata.annotations.[cert-manager.io/inject-ca-from]\n#        options:\n#          delimiter: '/'\n#          index: 0\n#          create: true\n#      - select:\n#          kind: MutatingWebhookConfiguration\n#        fieldPaths:\n#          - .metadata.annotations.[cert-manager.io/inject-ca-from]\n#        options:\n#          delimiter: '/'\n#          index: 0\n#          create: true\n#      - select:\n#          kind: CustomResourceDefinition\n#        fieldPaths:\n#          - .metadata.annotations.[cert-manager.io/inject-ca-from]\n#        options:\n#          delimiter: '/'\n#          index: 0\n#          create: true\n#  - source:\n#      kind: Certificate\n#      group: cert-manager.io\n#      version: v1\n#      name: serving-cert # this name should match the one in certificate.yaml\n#      fieldPath: .metadata.name\n#    targets:\n#      - select:\n#          kind: ValidatingWebhookConfiguration\n#        fieldPaths:\n#          - .metadata.annotations.[cert-manager.io/inject-ca-from]\n#        options:\n#          delimiter: '/'\n#          index: 1\n#          create: true\n#      - select:\n#          kind: MutatingWebhookConfiguration\n#        fieldPaths:\n#          - .metadata.annotations.[cert-manager.io/inject-ca-from]\n#        options:\n#          delimiter: '/'\n#          index: 1\n#          create: true\n#      - select:\n#          kind: CustomResourceDefinition\n#        fieldPaths:\n#          - .metadata.annotations.[cert-manager.io/inject-ca-from]\n#        options:\n#          delimiter: '/'\n#          index: 1\n#          create: true\n#  - source: # Add cert-manager annotation to the webhook Service\n#      kind: Service\n#      version: v1\n#      name: webhook-service\n#      fieldPath: .metadata.name # namespace of the service\n#    targets:\n#      - select:\n#          kind: Certificate\n#          group: cert-manager.io\n#          version: v1\n#        fieldPaths:\n#          - .spec.dnsNames.0\n#          - .spec.dnsNames.1\n#        options:\n#          delimiter: '.'\n#          index: 0\n#          create: true\n#  - source:\n#      kind: Service\n#      version: v1\n#      name: webhook-service\n#      fieldPath: .metadata.namespace # namespace of the service\n#    targets:\n#      - select:\n#          kind: Certificate\n#          group: cert-manager.io\n#          version: v1\n#        fieldPaths:\n#          - .spec.dnsNames.0\n#          - .spec.dnsNames.1\n#        options:\n#          delimiter: '.'\n#          index: 1\n#          create: true\n"
  },
  {
    "path": "pkg/operator/config/default/manager_auth_proxy_patch.yaml",
    "content": "# This patch inject a sidecar container which is a HTTP proxy for the\n# controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews.\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: controller-manager\n  namespace: system\nspec:\n  template:\n    spec:\n      containers:\n      - name: kube-rbac-proxy\n        securityContext:\n          allowPrivilegeEscalation: false\n          capabilities:\n            drop:\n              - \"ALL\"\n        image: gcr.io/kubebuilder/kube-rbac-proxy:v0.13.0\n        args:\n        - \"--secure-listen-address=0.0.0.0:8443\"\n        - \"--upstream=http://127.0.0.1:8080/\"\n        - \"--logtostderr=true\"\n        - \"--v=0\"\n        ports:\n        - containerPort: 8443\n          protocol: TCP\n          name: https\n        resources:\n          limits:\n            cpu: 500m\n            memory: 128Mi\n          requests:\n            cpu: 5m\n            memory: 64Mi\n      - name: manager\n        args:\n        - \"--health-probe-bind-address=:8081\"\n        - \"--metrics-bind-address=127.0.0.1:8080\"\n        - \"--leader-elect\"\n        - \"--leader-election-id=operator\"\n"
  },
  {
    "path": "pkg/operator/config/default/manager_config_patch.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: controller-manager\n  namespace: system\nspec:\n  template:\n    spec:\n      containers:\n      - name: manager\n        args:\n        - \"--config=controller_manager_config.yaml\"\n        volumeMounts:\n        - name: manager-config\n          mountPath: /controller_manager_config.yaml\n          subPath: controller_manager_config.yaml\n      volumes:\n      - name: manager-config\n        configMap:\n          name: manager-config\n"
  },
  {
    "path": "pkg/operator/config/manager/controller_manager_config.yaml",
    "content": "apiVersion: controller-runtime.sigs.k8s.io/v1alpha1\nkind: ControllerManagerConfig\nhealth:\n  healthProbeBindAddress: :8081\nmetrics:\n  bindAddress: 127.0.0.1:8080\nwebhook:\n  port: 9443\nleaderElection:\n  leaderElect: true\n  resourceName: 5dbd2493.dcode.tech\n# leaderElectionReleaseOnCancel defines if the leader should step down volume\n# when the Manager ends. This requires the binary to immediately end when the\n# Manager is stopped, otherwise, this setting is unsafe. Setting this significantly\n# speeds up voluntary leader transitions as the new leader don't have to wait\n# LeaseDuration time first.\n# In the default scaffold provided, the program ends immediately after\n# the manager stops, so would be fine to enable this option. However,\n# if you are doing or is intended to do any operation such as perform cleanups\n# after the manager stops then its usage might be unsafe.\n# leaderElectionReleaseOnCancel: true\n"
  },
  {
    "path": "pkg/operator/config/manager/kustomization.yaml",
    "content": "resources:\n- manager.yaml\n\ngeneratorOptions:\n  disableNameSuffixHash: true\n\nconfigMapGenerator:\n- files:\n  - controller_manager_config.yaml\n  name: manager-config\napiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\nimages:\n- name: controller\n  newName: eliranw/kube-tunnel-operator\n  newTag: 0.0.4\n"
  },
  {
    "path": "pkg/operator/config/manager/manager.yaml",
    "content": "apiVersion: v1\nkind: Namespace\nmetadata:\n  labels:\n    control-plane: controller-manager\n  name: system\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: controller-manager\n  namespace: system\n  labels:\n    control-plane: controller-manager\nspec:\n  selector:\n    matchLabels:\n      control-plane: controller-manager\n  replicas: 1\n  template:\n    metadata:\n      annotations:\n        kubectl.kubernetes.io/default-container: manager\n      labels:\n        control-plane: controller-manager\n    spec:\n      securityContext:\n        runAsNonRoot: true\n        # TODO(user): For common cases that do not require escalating privileges\n        # it is recommended to ensure that all your Pods/Containers are restrictive.\n        # More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted\n        # Please uncomment the following code if your project does NOT have to work on old Kubernetes\n        # versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ).\n        # seccompProfile:\n        #   type: RuntimeDefault\n      containers:\n      - args:\n        - --leader-elect\n        - --leader-election-id=operator\n        image: controller:latest\n        name: manager\n        env:\n        - name: POD_NAMESPACE\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.namespace\n        securityContext:\n          allowPrivilegeEscalation: false\n          capabilities:\n            drop:\n              - \"ALL\"\n        livenessProbe:\n          httpGet:\n            path: /healthz\n            port: 8081\n          initialDelaySeconds: 15\n          periodSeconds: 20\n        ports:\n        - containerPort: 8083\n          name: http\n          protocol: TCP\n        readinessProbe:\n          httpGet:\n            path: /readyz\n            port: 8081\n          initialDelaySeconds: 5\n          periodSeconds: 10\n        # TODO(user): Configure the resources accordingly based on the project requirements.\n        # More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/\n        resources:\n          limits:\n            cpu: 500m\n            memory: 128Mi\n          requests:\n            cpu: 10m\n            memory: 64Mi\n      serviceAccountName: controller-manager\n      terminationGracePeriodSeconds: 10\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    app.kubernetes.io/instance: kube-tunnel-operator\n  name: kube-tunnel-operator\n  namespace: operator-system\nspec:\n  internalTrafficPolicy: Cluster\n  ipFamilies:\n  - IPv4\n  ipFamilyPolicy: SingleStack\n  ports:\n  - name: http\n    port: 80\n    targetPort: http\n  selector:\n    control-plane: controller-manager\n  type: ClusterIP\n"
  },
  {
    "path": "pkg/operator/config/manifests/bases/operator.clusterserviceversion.yaml",
    "content": "apiVersion: operators.coreos.com/v1alpha1\nkind: ClusterServiceVersion\nmetadata:\n  annotations:\n    alm-examples: '[]'\n    capabilities: Basic Install\n  name: operator.v0.0.0\n  namespace: placeholder\nspec:\n  apiservicedefinitions: {}\n  customresourcedefinitions: {}\n  description: operator for managing kubetunnels\n  displayName: kubetunnel-operator\n  icon:\n  - base64data: \"\"\n    mediatype: \"\"\n  install:\n    spec:\n      deployments: null\n    strategy: \"\"\n  installModes:\n  - supported: false\n    type: OwnNamespace\n  - supported: false\n    type: SingleNamespace\n  - supported: false\n    type: MultiNamespace\n  - supported: true\n    type: AllNamespaces\n  keywords:\n  - tunnel\n  - kubernetes\n  - debug\n  links:\n  - name: Operator\n    url: https://operator.domain\n  maturity: alpha\n  provider:\n    name: dcode\n  version: 0.0.0\n"
  },
  {
    "path": "pkg/operator/config/manifests/kustomization.yaml",
    "content": "# These resources constitute the fully configured set of manifests\n# used to generate the 'manifests/' directory in a bundle.\nresources:\n- bases/operator.clusterserviceversion.yaml\n- ../default\n- ../samples\n- ../scorecard\n"
  },
  {
    "path": "pkg/operator/config/prometheus/kustomization.yaml",
    "content": "resources:\n- monitor.yaml\n"
  },
  {
    "path": "pkg/operator/config/prometheus/monitor.yaml",
    "content": "\n# Prometheus Monitor Service (Metrics)\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  labels:\n    control-plane: controller-manager\n  name: controller-manager-metrics-monitor\n  namespace: system\nspec:\n  endpoints:\n    - path: /metrics\n      port: https\n      scheme: https\n      bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n      tlsConfig:\n        insecureSkipVerify: true\n  selector:\n    matchLabels:\n      control-plane: controller-manager\n"
  },
  {
    "path": "pkg/operator/config/rbac/auth_proxy_client_clusterrole.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: metrics-reader\nrules:\n- nonResourceURLs:\n  - \"/metrics\"\n  verbs:\n  - get\n"
  },
  {
    "path": "pkg/operator/config/rbac/auth_proxy_role.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: proxy-role\nrules:\n- apiGroups:\n  - authentication.k8s.io\n  resources:\n  - tokenreviews\n  verbs:\n  - create\n- apiGroups:\n  - authorization.k8s.io\n  resources:\n  - subjectaccessreviews\n  verbs:\n  - create\n"
  },
  {
    "path": "pkg/operator/config/rbac/auth_proxy_role_binding.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: proxy-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: proxy-role\nsubjects:\n- kind: ServiceAccount\n  name: controller-manager\n  namespace: system\n"
  },
  {
    "path": "pkg/operator/config/rbac/auth_proxy_service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    control-plane: controller-manager\n  name: controller-manager-metrics-service\n  namespace: system\nspec:\n  ports:\n  - name: https\n    port: 8443\n    protocol: TCP\n    targetPort: https\n  selector:\n    control-plane: controller-manager\n"
  },
  {
    "path": "pkg/operator/config/rbac/kubetunnel_editor_role.yaml",
    "content": "# permissions for end users to edit kubetunnels.\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: kubetunnel-editor-role\nrules:\n- apiGroups:\n  - application.dcode.tech\n  resources:\n  - kubetunnels\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - application.dcode.tech\n  resources:\n  - kubetunnels/status\n  verbs:\n  - get\n"
  },
  {
    "path": "pkg/operator/config/rbac/kubetunnel_viewer_role.yaml",
    "content": "# permissions for end users to view kubetunnels.\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: kubetunnel-viewer-role\nrules:\n- apiGroups:\n  - application.dcode.tech\n  resources:\n  - kubetunnels\n  verbs:\n  - get\n  - list\n  - watch\n- apiGroups:\n  - application.dcode.tech\n  resources:\n  - kubetunnels/status\n  verbs:\n  - get\n"
  },
  {
    "path": "pkg/operator/config/rbac/kustomization.yaml",
    "content": "resources:\n# All RBAC will be applied under this service account in\n# the deployment namespace. You may comment out this resource\n# if your manager will use a service account that exists at\n# runtime. Be sure to update RoleBinding and ClusterRoleBinding\n# subjects if changing service account names.\n- service_account.yaml\n- role.yaml\n- role_binding.yaml\n- leader_election_role.yaml\n- leader_election_role_binding.yaml\n# Comment the following 4 lines if you want to disable\n# the auth proxy (https://github.com/brancz/kube-rbac-proxy)\n# which protects your /metrics endpoint.\n- auth_proxy_service.yaml\n- auth_proxy_role.yaml\n- auth_proxy_role_binding.yaml\n- auth_proxy_client_clusterrole.yaml\n"
  },
  {
    "path": "pkg/operator/config/rbac/leader_election_role.yaml",
    "content": "# permissions to do leader election.\napiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n  name: leader-election-role\nrules:\n- apiGroups:\n  - \"\"\n  resources:\n  - configmaps\n  verbs:\n  - get\n  - list\n  - watch\n  - create\n  - update\n  - patch\n  - delete\n- apiGroups:\n  - coordination.k8s.io\n  resources:\n  - leases\n  verbs:\n  - get\n  - list\n  - watch\n  - create\n  - update\n  - patch\n  - delete\n- apiGroups:\n  - \"\"\n  resources:\n  - events\n  verbs:\n  - create\n  - patch\n"
  },
  {
    "path": "pkg/operator/config/rbac/leader_election_role_binding.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  name: leader-election-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: Role\n  name: leader-election-role\nsubjects:\n- kind: ServiceAccount\n  name: controller-manager\n  namespace: system\n"
  },
  {
    "path": "pkg/operator/config/rbac/role.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: manager-role\nrules:\n##\n## Base operator rules\n##\n# We need to get namespaces so the operator can read namespaces to ensure they exist\n- apiGroups:\n  - \"\"\n  resources:\n  - namespaces\n  - roles\n  verbs:\n  - get\n# We need to manage Helm release secrets\n- apiGroups:\n  - \"\"\n  - rbac.authorization.k8s.io\n  - roles.rbac.authorization.k8s.io\n  - authorization.k8s.io\n  resources:\n  - secrets\n  - configmaps\n  - rolebindings\n  - roles\n  verbs:\n  - \"*\"\n# We need to create events on CRs about things happening during reconciliation\n- apiGroups:\n  - \"\"\n  resources:\n  - events\n  verbs:\n  - create\n\n##\n## Rules for application.dcode.tech/v1, Kind: Kubetunnel\n##\n- apiGroups:\n  - application.dcode.tech\n  resources:\n  - kubetunnels\n  - kubetunnels/status\n  - kubetunnels/finalizers\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- verbs:\n  - \"*\"\n  apiGroups:\n  - \"\"\n  resources:\n  - \"serviceaccounts\"\n  - \"services\"\n  - \"roles\"\n- verbs:\n  - \"*\"\n  apiGroups:\n  - \"apps\"\n  resources:\n  - \"deployments\"\n\n#+kubebuilder:scaffold:rules\n"
  },
  {
    "path": "pkg/operator/config/rbac/role_binding.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: manager-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: manager-role\nsubjects:\n- kind: ServiceAccount\n  name: controller-manager\n  namespace: system\n"
  },
  {
    "path": "pkg/operator/config/rbac/service_account.yaml",
    "content": "apiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: controller-manager\n  namespace: system\n"
  },
  {
    "path": "pkg/operator/config/samples/application_v1_kubetunnel.yaml",
    "content": "apiVersion: application.dcode.tech/v1\nkind: Kubetunnel\nmetadata:\n  name: kubetunnel-sample\nspec:\n  env_service_name: nginx\n  env_ports: \"8081\"\n  pod_selector_labels:\n    name: nginx\n"
  },
  {
    "path": "pkg/operator/config/samples/kustomization.yaml",
    "content": "## Append samples you want in your CSV to this file as resources ##\nresources:\n- application_v1_kubetunnel.yaml\n#+kubebuilder:scaffold:manifestskustomizesamples\n"
  },
  {
    "path": "pkg/operator/config/samples/values.yaml",
    "content": "replicaCount: 1\nnamespace: frps\nimage:\n  repository: snowdreamtech/frps\n  tag: latest\n  pullPolicy: IfNotPresent\n\nserviceMonitor:\n  enable: false\n\n# frp server configuration\nconfigInline: |\n  [common]\n  bind_port = 7000\n  dashboard_port = 7500\n  enable_prometheus = true\n\n\n# Example parameters - these should be sent from client\nenv_service_name: nginx\nenv_ports: \"80,8080\"\npod_selector_labels:\n  app.kubernetes.io/instance: nginx\n  app.kubernetes.io/name: nginx\n\n# healthcheck\nhealthInline: |\n  #!/bin/bash\n  echo \"Service is $SERVICE_NAME\"\n  for port in ${PORTS//,/ }\n  do\n    echo \"curl http://localhost:$port..\"\n    if curl --fail http://localhost:$port; then\n      echo \"succeeded with port $port!\"\n    else\n      echo \"failed port $port..\"\n      kubectl patch svc ${SERVICE_NAME} --type=json -p=\"[{'op': 'remove', 'path': '/spec/selector/kube-tunnel'}]\"\n      exit 1\n    fi\n  done\n  echo \"All ports are successful. Patching service to kube-tunnel..\"\n  kubectl patch service ${SERVICE_NAME} -p '{\"spec\":{\"selector\":{\"kube-tunnel\": \"true\"}}}'\n\nconfigSecretName: \"\"\nenvSecretName: \"\"\n\nports:\n  http:\n    port: 7000\n    servicePort: 7000\n    protocol: TCP\n  https:\n    port: 443\n  udp:\n    port: 7001\n    protocol: UDP\n  kcp:\n    port: 80\n    protocol: UDP\n  dashboard:\n    port: 7500\n\nservice:\n  type: ClusterIP\n\nimagePullSecrets: []\nnameOverride: \"\"\nfullnameOverride: \"\"\n\nserviceAccount:\n  # Specifies whether a service account should be created\n  create: true\n  # Annotations to add to the service account\n  annotations: {}\n  # The name of the service account to use.\n  # If not set and create is true, a name is generated using the fullname template\n  name: \"\"\n\npodAnnotations: {}\n\npodSecurityContext: {}\n# fsGroup: 2000\n\nsecurityContext: {}\n  # capabilities:\n  #   drop:\n  #   - ALL\n# readOnlyRootFilesystem: true\n# runAsNonRoot: true\n# runAsUser: 1000\n\n\nresources: {}\n  # We usually recommend not to specify default resources and to leave this as a conscious\n  # choice for the user. This also increases chances charts run on environments with little\n  # resources, such as Minikube. If you do want to specify resources, uncomment the following\n  # lines, adjust them as necessary, and remove the curly braces after 'resources:'.\n  # limits:\n  #   cpu: 100m\n  #   memory: 128Mi\n# requests:\n#   cpu: 100m\n#   memory: 128Mi\n\nautoscaling:\n  enabled: false\n  minReplicas: 1\n  maxReplicas: 100\n  targetCPUUtilizationPercentage: 80\n  # targetMemoryUtilizationPercentage: 80\n\nnodeSelector: {}\n\ntolerations: []\n\naffinity: {}\n"
  },
  {
    "path": "pkg/operator/config/scorecard/bases/config.yaml",
    "content": "apiVersion: scorecard.operatorframework.io/v1alpha3\nkind: Configuration\nmetadata:\n  name: config\nstages:\n- parallel: true\n  tests: []\n"
  },
  {
    "path": "pkg/operator/config/scorecard/kustomization.yaml",
    "content": "resources:\n- bases/config.yaml\npatchesJson6902:\n- path: patches/basic.config.yaml\n  target:\n    group: scorecard.operatorframework.io\n    version: v1alpha3\n    kind: Configuration\n    name: config\n- path: patches/olm.config.yaml\n  target:\n    group: scorecard.operatorframework.io\n    version: v1alpha3\n    kind: Configuration\n    name: config\n#+kubebuilder:scaffold:patchesJson6902\n"
  },
  {
    "path": "pkg/operator/config/scorecard/patches/basic.config.yaml",
    "content": "- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - basic-check-spec\n    image: quay.io/operator-framework/scorecard-test:v1.23.0\n    labels:\n      suite: basic\n      test: basic-check-spec-test\n"
  },
  {
    "path": "pkg/operator/config/scorecard/patches/olm.config.yaml",
    "content": "- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-bundle-validation\n    image: quay.io/operator-framework/scorecard-test:v1.23.0\n    labels:\n      suite: olm\n      test: olm-bundle-validation-test\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-crds-have-validation\n    image: quay.io/operator-framework/scorecard-test:v1.23.0\n    labels:\n      suite: olm\n      test: olm-crds-have-validation-test\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-crds-have-resources\n    image: quay.io/operator-framework/scorecard-test:v1.23.0\n    labels:\n      suite: olm\n      test: olm-crds-have-resources-test\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-spec-descriptors\n    image: quay.io/operator-framework/scorecard-test:v1.23.0\n    labels:\n      suite: olm\n      test: olm-spec-descriptors-test\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-status-descriptors\n    image: quay.io/operator-framework/scorecard-test:v1.23.0\n    labels:\n      suite: olm\n      test: olm-status-descriptors-test\n"
  },
  {
    "path": "pkg/operator/hack/boilerplate.go.txt",
    "content": "/*\nCopyright 2022.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/"
  },
  {
    "path": "pkg/operator/helm-charts/kubetunnel/Chart.yaml",
    "content": "apiVersion: v2\nname: kube-tunnel\ndescription: A Helm chart for kube-tunnel server\ntype: application\nversion: 0.2.8\nappVersion: v0.1.0\nmaintainers:\n  - name: Eliran Wolf\n    email: eliran@dcode.tech\n  - name: Maor Davidov\n    email: maor@dcode.tech\n  - name: Tamir Shaul\n    email: tshaul@gmail.com\n"
  },
  {
    "path": "pkg/operator/helm-charts/kubetunnel/README.md",
    "content": "# kube-tunnel server\n\n## \nThere are multiple roles installed in the namespace:\n1. List/Get/Watch/Delete pods and deployments for garbage collection pod\n2. Patch services for frps pod\n"
  },
  {
    "path": "pkg/operator/helm-charts/kubetunnel/templates/NOTES.txt",
    "content": "Enjoy kube-tunnel !\n"
  },
  {
    "path": "pkg/operator/helm-charts/kubetunnel/templates/_helpers.tpl",
    "content": "{{/*\nExpand the name of the chart.\n*/}}\n{{- define \"kubetunnel.name\" -}}\n{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix \"-\" }}\n{{- end }}\n\n{{/*\nCreate a default fully qualified app name.\nWe truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).\nIf release name contains chart name it will be used as a full name.\n*/}}\n{{- define \"kubetunnel.fullname\" -}}\n{{- if .Values.fullnameOverride }}\n{{- .Values.fullnameOverride | trunc 63 | trimSuffix \"-\" }}\n{{- else }}\n{{- $name := default .Chart.Name .Values.nameOverride }}\n{{- if contains $name .Release.Name }}\n{{- .Release.Name | trunc 63 | trimSuffix \"-\" }}\n{{- else }}\n{{- printf \"%s-%s\" .Release.Name $name | trunc 63 | trimSuffix \"-\" }}\n{{- end }}\n{{- end }}\n{{- end }}\n\n{{/*\nCreate chart name and version as used by the chart label.\n*/}}\n{{- define \"kubetunnel.chart\" -}}\n{{- printf \"%s-%s\" .Chart.Name .Chart.Version | replace \"+\" \"_\" | trunc 63 | trimSuffix \"-\" }}\n{{- end }}\n\n{{/*\nCommon labels\n*/}}\n{{- define \"kubetunnel.labels\" -}}\nhelm.sh/chart: {{ include \"kubetunnel.chart\" . }}\n{{ include \"kubetunnel.selectorLabels\" . }}\n{{- if .Chart.AppVersion }}\napp.kubernetes.io/version: {{ .Chart.AppVersion | quote }}\n{{- end }}\napp.kubernetes.io/managed-by: {{ .Release.Service }}\n{{- end }}\n\n{{/*\nSelector labels\n*/}}\n{{- define \"kubetunnel.selectorLabels\" -}}\n{{- end }}\n\n{{/*\nCreate the name of the service account to use\n*/}}\n{{- define \"kubetunnel.serviceAccountName\" -}}\n{{- if .Values.serviceAccount.create }}\n{{- default (include \"kubetunnel.fullname\" .) .Values.serviceAccount.name }}\n{{- else }}\n{{- default \"default\" .Values.serviceAccount.name }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "pkg/operator/helm-charts/kubetunnel/templates/conf.sec.yaml",
    "content": "{{if not .Values.configSecretName}}\napiVersion: v1\nkind: Secret\nmetadata:\n  name: {{ .Release.Name }}-config\n  labels:\n  {{- include \"kubetunnel.labels\" . | nindent 4 }}\nstringData:\n  frps.ini: |\n    {{.Values.configInline | nindent 4}}\n\n    {{end}}\n"
  },
  {
    "path": "pkg/operator/helm-charts/kubetunnel/templates/deployment.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: {{ .Release.Name }}\n  labels:\n    {{- include \"kubetunnel.labels\" . | nindent 4 }}\n    kubetunnel-app: {{  .Values.env_service_name }}\n    we-dcode-app: kubetunnel\n    {{- range $key, $val := .Values.pod_labels }}\n    {{ $key }}: {{ $val | quote }}\n    {{- end}}\nspec:\n  {{- if not .Values.autoscaling.enabled }}\n  replicas: {{ .Values.replicaCount }}\n  {{- end }}\n  selector:\n    matchLabels:\n      kubetunnel-app: {{  .Values.env_service_name }}\n      we-dcode-app: kubetunnel\n  template:\n    metadata:\n      {{- with .Values.podAnnotations }}\n      annotations:\n        {{- toYaml . | nindent 8 }}\n      {{- end }}\n      labels:\n        {{- include \"kubetunnel.labels\" . | nindent 8 }}\n        kubetunnel-app: {{  .Values.env_service_name }}\n        we-dcode-app: kubetunnel\n        meta.helm.sh/release-name:  {{ .Release.Name }}\n        {{- range $key, $val := .Values.pod_labels }}\n        {{ $key }}: {{ $val | quote }}\n        {{- end}}\n    spec:\n      {{- with .Values.imagePullSecrets }}\n      imagePullSecrets:\n        {{- toYaml . | nindent 8 }}\n      {{- end }}\n      serviceAccountName: {{ include \"kubetunnel.serviceAccountName\" . }}\n      securityContext:\n        {{- toYaml .Values.podSecurityContext | nindent 8 }}\n      containers:\n        - name: kube-tunnel-server\n          image: dcodetech/kubetunnel:1.1.4\n          readinessProbe:\n            httpGet:\n              path: /health\n              port: 8080\n            periodSeconds: 1\n            failureThreshold: 1\n\n          env:\n          - name: POD_NAMESPACE\n            valueFrom:\n              fieldRef:\n                fieldPath: metadata.namespace\n          envFrom:\n          - configMapRef:\n              name: {{ .Release.Name }}-env\n        - name: {{ .Chart.Name }}\n          securityContext:\n            {{- toYaml .Values.securityContext | nindent 12 }}\n          image: \"{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}\"\n          imagePullPolicy: {{ .Values.image.pullPolicy }}\n          volumeMounts:\n            - mountPath: /etc/frp\n              name: frp-conf\n          ports:\n            {{- range $k,$v := .Values.ports}}\n            - name: {{$k}}\n              containerPort: {{$v.port}}\n              protocol: {{$v.protocol | default \"TCP\"}}\n            {{- end}}\n          resources:\n            {{- toYaml .Values.resources | nindent 12 }}\n      {{- with .Values.nodeSelector }}\n      nodeSelector:\n        {{- toYaml . | nindent 8 }}\n      {{- end }}\n      {{- with .Values.affinity }}\n      affinity:\n        {{- toYaml . | nindent 8 }}\n      {{- end }}\n      {{- with .Values.tolerations }}\n      tolerations:\n        {{- toYaml . | nindent 8 }}\n      {{- end }}\n      volumes:\n        - name: frp-conf\n          secret:\n            {{- if .Values.configSecretName}}\n            secretName: {{.Values.configSecretName }}\n            {{- else}}\n            secretName: {{ .Release.Name }}-config\n            {{- end}}\n        - name: frp-health\n          secret:\n            {{- if .Values.configSecretName}}\n            secretName: {{.Values.configSecretName }}\n            {{- else}}\n            secretName: {{ .Release.Name }}-health\n            {{- end}}\n            defaultMode: 0777\n"
  },
  {
    "path": "pkg/operator/helm-charts/kubetunnel/templates/env-conf.yaml",
    "content": "apiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: {{ .Release.Name }}-env\ndata:\n  PORTS: {{ .Values.env_ports | quote }}\n  SERVICE_NAME: {{  .Values.env_service_name }}\n  OPERATOR_NAMESPACE: {{  .Values.operator.namespace }}\n  OPERATOR_SVC_NAME: {{  .Values.operator.service.name }}\n  OPERATOR_PORT: {{ .Values.operator.service.port | quote }}\n"
  },
  {
    "path": "pkg/operator/helm-charts/kubetunnel/templates/health-cm.yaml",
    "content": "apiVersion: v1\nkind: Secret\nmetadata:\n  name: {{ .Release.Name }}-health\n  labels:\n  {{- include \"kubetunnel.labels\" . | nindent 4 }}\nstringData:\n  health.sh: |\n    {{.Values.healthInline | nindent 4}}\n"
  },
  {
    "path": "pkg/operator/helm-charts/kubetunnel/templates/kube-exec-rb.yaml",
    "content": "# This role binding allows \"jane\" to read pods in the \"default\" namespace.\n# You need to already have a Role named \"pod-reader\" in that namespace.\napiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  name: {{ .Release.Name }}-rb\nsubjects:\n# You can specify more than one \"subject\"\n- kind: ServiceAccount\n  name: {{ include \"kubetunnel.serviceAccountName\" . }}\n  namespace: {{ .Release.Namespace }}\nroleRef:\n  # \"roleRef\" specifies the binding to a Role / ClusterRole\n  kind: Role #this must be Role or ClusterRole\n  name: {{ include \"kubetunnel.serviceAccountName\" . }}-role\n  apiGroup: rbac.authorization.k8s.io\n"
  },
  {
    "path": "pkg/operator/helm-charts/kubetunnel/templates/kube-exec-role.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n  name: {{ include \"kubetunnel.serviceAccountName\" . }}-role\nrules:\n- apiGroups: [\"\"] # \"\" indicates the core API group\n  resources: [\"pods\"]\n  verbs: [\"get\", \"watch\", \"list\"]\n- apiGroups: [\"\"] # \"\" indicates the core API group\n  resources: [\"services\"]\n  verbs: [\"get\", \"watch\", \"list\", \"update\", \"patch\"]\n"
  },
  {
    "path": "pkg/operator/helm-charts/kubetunnel/templates/service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  name: {{ .Release.Name }}\n  labels:\n    {{- include \"kubetunnel.labels\" . | nindent 4 }}\nspec:\n  type: {{ .Values.service.type }}\n  ports:\n    {{- range $k,$v := .Values.ports}}\n    - name: {{$k}}\n      targetPort: {{$k}}\n      port: {{$v.servicePort | default $v.port}}\n      protocol: {{$v.protocol | default \"TCP\"}}\n    {{- end}}\n  selector:\n    kubetunnel-app: {{  .Values.env_service_name }}\n"
  },
  {
    "path": "pkg/operator/helm-charts/kubetunnel/templates/serviceaccount.yaml",
    "content": "{{- if .Values.serviceAccount.create -}}\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: {{ include \"kubetunnel.serviceAccountName\" . }}\n  labels:\n    {{- include \"kubetunnel.labels\" . | nindent 4 }}\n  {{- with .Values.serviceAccount.annotations }}\n  annotations:\n    {{- toYaml . | nindent 4 }}\n  {{- end }}\n{{- end }}\n"
  },
  {
    "path": "pkg/operator/helm-charts/kubetunnel/values.yaml",
    "content": "replicaCount: 1\nnamespace: frps\nimage:\n  repository: snowdreamtech/frps\n  tag: latest\n  pullPolicy: IfNotPresent\n\nserviceMonitor:\n  enable: false\n\n# frp server configuration\nconfigInline: |\n  [common]\n  bind_port = 7000\n  dashboard_port = 7500\n  enable_prometheus = true\n\n\n# healthcheck\nhealthInline: |\n  #!/bin/bash\n  echo \"Service is $SERVICE_NAME\"\n  for port in ${PORTS//,/ }\n  do\n    echo \"curl http://localhost:$port..\"\n    if curl --fail http://localhost:$port; then\n      echo \"succeeded with port $port!\"\n    else\n      echo \"failed port $port..\"\n      kubectl patch svc ${SERVICE_NAME} --type=json -p=\"[{'op': 'remove', 'path': '/spec/selector/kube-tunnel'}]\"\n      exit 1\n    fi\n  done\n  echo \"All ports are successful. Patching service to kube-tunnel..\"\n  kubectl patch service ${SERVICE_NAME} -p '{\"spec\":{\"selector\":{\"kube-tunnel\": \"true\"}}}'\n\nconfigSecretName: \"\"\nenvSecretName: \"\"\n\nports:\n  http:\n    port: 7000\n    servicePort: 7000\n    protocol: TCP\n  dashboard:\n    port: 7500\n\nservice:\n  type: ClusterIP\n\nimagePullSecrets: []\nnameOverride: \"\"\nfullnameOverride: \"\"\n\nserviceAccount:\n  # Specifies whether a service account should be created\n  create: true\n  # Annotations to add to the service account\n  annotations: {}\n  # The name of the service account to use.\n  # If not set and create is true, a name is generated using the fullname template\n  name: \"\"\n\npodAnnotations: {}\n\npodSecurityContext: {}\n# fsGroup: 2000\n\nsecurityContext: {}\n  # capabilities:\n  #   drop:\n  #   - ALL\n# readOnlyRootFilesystem: true\n# runAsNonRoot: true\n# runAsUser: 1000\n\n\nresources: {}\n  # We usually recommend not to specify default resources and to leave this as a conscious\n  # choice for the user. This also increases chances charts run on environments with little\n  # resources, such as Minikube. If you do want to specify resources, uncomment the following\n  # lines, adjust them as necessary, and remove the curly braces after 'resources:'.\n  # limits:\n  #   cpu: 100m\n  #   memory: 128Mi\n# requests:\n#   cpu: 100m\n#   memory: 128Mi\n\nautoscaling:\n  enabled: false\n  minReplicas: 1\n  maxReplicas: 100\n  targetCPUUtilizationPercentage: 80\n  # targetMemoryUtilizationPercentage: 80\n\nnodeSelector: {}\n\ntolerations: []\n\naffinity: {}\n"
  },
  {
    "path": "pkg/operator/watches.yaml",
    "content": "# Use the 'create api' subcommand to add watches to this file.\n- group: application.dcode.tech\n  version: v1\n  kind: Kubetunnel\n  chart: helm-charts/kubetunnel\n#+kubebuilder:scaffold:watch\n"
  },
  {
    "path": "pkg/utils/hostsutils/hostsutils.go",
    "content": "package hostsutils\n\nimport (\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/txn2/txeh\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/constants\"\n\t\"strings\"\n)\n\nfunc HostsCleanup(hosts *txeh.Hosts) {\n\n\tlog.Info(\"cleaning up all entries containing .kubetunnel host\")\n\n\tfor _, line := range *hosts.GetHostFileLines() {\n\n\t\tfor _, hostname := range line.Hostnames {\n\n\t\t\tif strings.Contains(hostname, constants.KubetunnelSlug) {\n\n\t\t\t\thosts.RemoveAddress(line.Address)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc ReplaceAddressForHost(hosts *txeh.Hosts, srcHost, dstHost string) {\n\n\tlog.Infof(\"replacing host: '%s' with: '%s'\", srcHost, dstHost)\n\n\tfound, newAddr, _ := hosts.HostAddressLookup(dstHost)\n\n\tif found == false {\n\t\tlog.Panicf(\"unable to locate host: %s in hosts file. please run %s again.\", dstHost, constants.KubetunnelSlug)\n\t}\n\n\tfor _, line := range *hosts.GetHostFileLines() {\n\n\t\tfor _, hostname := range line.Hostnames {\n\n\t\t\tif strings.EqualFold(srcHost, hostname) {\n\n\t\t\t\thosts.RemoveAddress(line.Address)\n\t\t\t\thosts.AddHosts(newAddr, line.Hostnames)\n\n\t\t\t\terr := hosts.Save()\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.Panicf(\"unable to save host: %s in hosts file. please run %s again. internal err: %s\", dstHost, constants.KubetunnelSlug, err.Error())\n\t\t\t\t}\n\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "pkg/utils/hostsutils/hostsutils_test.go",
    "content": "package hostsutils_test\n\nimport (\n\t\"github.com/txn2/txeh\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/utils/hostsutils\"\n\t\"gotest.tools/v3/assert\"\n\t\"testing\"\n)\n\nfunc TestReplaceHostAddress(t *testing.T) {\n\n\thostFile, err := txeh.NewHostsDefault()\n\n\tassert.NilError(t, err)\n\n\thostsutils.ReplaceAddressForHost(hostFile, \"nginx\", \"kubetunnel-nginx\")\n}\n"
  },
  {
    "path": "pkg/utils/logutil/logutil.go",
    "content": "package logutil\n\nimport (\n\t\"bytes\"\n\t\"os\"\n)\n\ntype LogOutputSplitter struct{}\n\nfunc (splitter *LogOutputSplitter) Write(p []byte) (n int, err error) {\n\tif bytes.Contains(p, []byte(\"level=error\")) || bytes.Contains(p, []byte(\"level=warn\")) {\n\t\treturn os.Stderr.Write(p)\n\t}\n\treturn os.Stdout.Write(p)\n}\n"
  },
  {
    "path": "pkg/utils/tcputil/tcputil.go",
    "content": "package tcputil\n\nimport (\n\tlog \"github.com/sirupsen/logrus\"\n\t\"net\"\n\t\"time\"\n)\n\nfunc IsAvailable(host string, port string) bool {\n\n\ttimeout := time.Second\n\tconn, err := net.DialTimeout(\"tcp\", net.JoinHostPort(host, port), timeout)\n\tif err != nil {\n\t\tlog.Debugf(\"connection error: %s\", err)\n\t\treturn false\n\t}\n\n\tdefer conn.Close()\n\tlog.Debugf(\"connection succeeded: %s\", net.JoinHostPort(host, port))\n\n\treturn true\n}\n"
  },
  {
    "path": "pkg/utils/tcputil/tcputil_test.go",
    "content": "package tcputil_test\n\nimport (\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/utils/tcputil\"\n\t\"testing\"\n)\n\nfunc TestFRPConnectivityWhenFRPCDestinationIsNotAvailable(t *testing.T) {\n\n\tisAvailable := tcputil.IsAvailable(\"localhost\", \"22285\")\n\n\tassert.True(t, isAvailable)\n}\n"
  },
  {
    "path": "pkg/utils/tomlutil/tomlutil.go",
    "content": "package tomlutil\n\nimport (\n\t\"github.com/BurntSushi/toml\"\n\t\"strings\"\n)\n\nfunc Marshal(v interface{}) (string, error)  {\n\n\tsb := strings.Builder{}\n\n\terr := toml.NewEncoder(&sb).Encode(&v)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn sb.String(), nil\n}"
  },
  {
    "path": "pkg/utils/tomlutil/tomlutil_test.go",
    "content": "package tomlutil_test\n\nimport (\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/frp/models\"\n\t\"github.com/we-dcode/kube-tunnel/pkg/utils/tomlutil\"\n\t\"testing\"\n)\n\nfunc TestMarshalTomlWithCommonOnly(t *testing.T) {\n\n\tfrpConfig := models.FrpClientConfig{\n\t\t\"Common\": models.Common{\n\t\t\tServerAddress: \"localhost\",\n\t\t\tServerPort:    \"7001\",\n\t\t},\n\t}\n\n\ttomlString, err := tomlutil.Marshal(frpConfig)\n\n\tassert.NoError(t, err)\n\tassert.NotEmpty(t, tomlString)\n}\n\nfunc TestMarshalTomlWithMultipleServices(t *testing.T) {\n\n\tfrpConfig := models.FrpClientConfig{\n\t\t\"common\": models.Common{\n\t\t\tServerAddress: \"localhost\",\n\t\t\tServerPort:    \"7001\",\n\t\t},\n\t\t\"rabbit\": models.Service{\n\t\t\tType:       \"tcp\",\n\t\t\tRemotePort: \"5672\",\n\t\t\tLocalIP:    \"localhost\",\n\t\t\tLocalPort:  \"5672\",\n\t\t},\n\t\t\"rabbit_management_ui\": models.Service{\n\t\t\tType:       \"tcp\",\n\t\t\tRemotePort: \"15672\",\n\t\t\tLocalIP:    \"localhost\",\n\t\t\tLocalPort:  \"15672\",\n\t\t},\n\t}\n\n\ttomlString, err := tomlutil.Marshal(frpConfig)\n\n\tassert.NoError(t, err)\n\tassert.NotEmpty(t, tomlString)\n}\n"
  }
]