[
  {
    "path": ".commitlintrc.yml",
    "content": "---\nextends:\n  - '@commitlint/config-angular'"
  },
  {
    "path": ".dockerignore",
    "content": "# More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file\n# Ignore all files which are not go type\n!**/*.go\n!**/*.mod\n!**/*.sum\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: Go\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\njobs:\n\n  build:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v2\n\n    - name: Set up Go\n      uses: actions/setup-go@v2\n      with:\n        go-version: 1.16.5\n\n    - name: Build\n      run: make build\n"
  },
  {
    "path": ".github/workflows/commitlint.yml",
    "content": "name: Commitlint\n\non: [pull_request]\n\njobs:\n  lint:\n    runs-on: ubuntu-latest\n    env:\n      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n    steps:\n      - uses: actions/checkout@v2\n        with:\n          fetch-depth: 0\n      - uses: wagoid/commitlint-github-action@v1\n        with:\n          configFile: './.commitlintrc.yml'"
  },
  {
    "path": ".github/workflows/e2e.yml",
    "content": "name: e2e\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\nenv:\n  VERSION: ${{ github.sha }}\n  SCRIPTS_DIR: test/scripts\n  E2E_KUBECONFIG_PATH: test/fixtures/config\n  FIXTURES_DIR: test/fixtures/manifests\n\njobs:\n\n  build:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v2\n\n    - name: Set up Go\n      uses: actions/setup-go@v2\n      with:\n        go-version: 1.16.5\n    - name: Build Image\n      run: make image\n    - name: Prepare envrionment\n      run: bash ${SCRIPTS_DIR}/pre.sh\n    - name: Install Minikube\n      run: bash ${SCRIPTS_DIR}/minikube.sh start\n    - name: Install kstone\n      run: bash ${SCRIPTS_DIR}/kstone.sh\n    - name: e2e test\n      run: make e2e"
  },
  {
    "path": ".github/workflows/golangci-lint.yml",
    "content": "name: golangci-lint\non:\n  push:\n    tags:\n      - v*\n    branches:\n      - master\n      - main\n  pull_request:\npermissions:\n  contents: read\n  # Optional: allow read access to pull request. Use with `only-new-issues` option.\n  # pull-requests: read\njobs:\n  golangci:\n    name: lint\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n      - uses: actions/setup-go@v3\n        with:\n          go-version: '1.17.8'\n      - name: golangci-lint\n        uses: golangci/golangci-lint-action@v3\n        with:\n          # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version\n          version: v1.38.0\n          # Optional: working directory, useful for monorepos\n          # working-directory: somedir\n\n          # Optional: golangci-lint command line arguments.\n          # args: --issues-exit-code=0\n\n          # Optional: show only new issues if it's a pull request. The default value is `false`.\n          # only-new-issues: true\n\n          # Optional: if set to true then the action will use pre-installed Go.\n          # skip-go-installation: true\n\n          # Optional: if set to true then the action don't cache or restore ~/go/pkg.\n          # skip-pkg-cache: true\n\n          # Optional: if set to true then the act\n"
  },
  {
    "path": ".gitignore",
    "content": "# OSX leaves these everywhere on SMB shares\n._*\n\n# OSX trash\n.DS_Store\n\n# Eclipse files\n.classpath\n.project\n.settings/**\n\n# Files generated by JetBrains IDEs, e.g. IntelliJ IDEA\n.idea/\n*.iml\n\n# Vscode files\n.vscode\n\n# This is where the result of the go build goes\n/output*/\n/_output*/\n/_output\n\n# Emacs save files\n*~\n\\#*\\#\n.\\#*\n\n# Vim-related files\n[._]*.s[a-w][a-z]\n[._]s[a-w][a-z]\n*.un~\nSession.vim\n.netrwhist\n\n# cscope-related files\ncscope.*\n\n# Go test binaries\n*.test\n/hack/.test-cmd-auth\n\n# JUnit test output from ginkgo e2e tests\n/junit*.xml\n\n# Mercurial files\n**/.hg\n**/.hg*\n\n# Vagrant\n.vagrant\nnetwork_closure.sh\n\n# Local cluster env variables\n/cluster/env.sh\n\n# Compiled binaries in third_party\n/third_party/pkg\n\n# Also ignore etcd installed by hack/install-etcd.sh\n/default.etcd\n\n# User cluster configs\n.kubeconfig\n\n.tags*\n\n# Version file for dockerized build\n.dockerized-kube-version-defs\n\n# Web UI\n/www/master/node_modules/\n/www/master/npm-debug.log\n/www/master/shared/config/development.json\n\n# Karma output\n/www/test_out\n\n# precommit temporary directories created by ./hack/verify-generated-docs.sh and ./hack/lib/util.sh\n/_tmp/\n/doc_tmp/\n\n# Test artifacts produced by Jenkins jobs\n/_artifacts/\n\n# Go dependencies installed on Jenkins\n/_gopath/\n\n# Config directories created by gcloud and gsutil on Jenkins\n/.config/gcloud*/\n/.gsutil/\n\n# CoreOS stuff\n/cluster/libvirt-coreos/coreos_*.img\n\n# Downloaded kstone binary release\n/kstone/\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\nbin\ntestbin/*\n\n# Output of the go coverage tool, specifically when used with LiteIDE\n*.out\n\n# direnv .envrc files\n.envrc\n\n# Downloaded kstone binary release tar ball\nkstone.tar.gz\n\n# generated files in any directory\n# TODO(thockin): uncomment this when we stop committing the generated files.\n#zz_generated.*\nzz_generated.openapi.go\nzz_generated_*_test.go\n\n# make-related metadata\n/.make/\n\n# Just in time generated data in the source, should never be committed\n/test/e2e/generated/bindata.go\n\n# This file used by some vendor repos (e.g. github.com/go-openapi/...) to store secret variables and should not be ignored\n!\\.drone\\.sec\n\n/bazel-*\n*.pyc\n\n# generated by verify-vendor.sh\nvendor\nvendordiff.patch\n\n/bin\n/127.0.0.1.etcd\n\n/docker/build"
  },
  {
    "path": ".golangci.yml",
    "content": "run:\n  # timeout for analysis, e.g. 30s, 5m\n  deadline: 10m\n  # include test files or not\n  tests: true\n  # disallowed from the implicit automatic updating of go.mod described above\n  modules-download-mode: readonly\n  # which dirs to skip: they won't be analyzed;\n  skip-dirs:\n    - third_party\n    - api\n    - web\n    - pkg/gateway/apis/config\n    - pkg/gateway/apis/config/v1\n    - pkg/registry/apis/config\n    - pkg/registry/apis/config/v1\n    - pkg/registry/harbor/client\n    - pkg/registry/harbor/helmClient\n    - pkg/monitor/apis/config\n    - pkg/monitor/apis/config/v1\n\nlinters:\n  disable-all: true\n  enable:\n    - unused\n    - gofmt\n    - ineffassign\n    - govet\n    - deadcode\n    - structcheck\n    - varcheck\n    - typecheck\n    - golint\n    - unconvert\n    - staticcheck\n    - gosimple\n\nissues:\n  exclude-rules:\n    - linters:\n        - staticcheck\n      text: \"SA1019:\"\n\nservice:\n  golangci-lint-version: 1.20.x\n"
  },
  {
    "path": "CHANGELOG/CHANGELOG.md",
    "content": "## v0.2.0-beta.2 (2022-06-08)\n<hr>\n\n### Features\n<hr>\n\nsupport import etcd v2 cluster. (@engow, @seanyan )\n\nadd compaction,lease metrics. (@tangcong )\n\nadd hostPath type for etcd backup operator. (@GeorgeGuo2018 )\n\n### Bug Fix\n\nfailed to add/remove member if affinity and toleration is nil. (@engow )\n\nfixed the issue that the editing page could not display cpu and memory resources. (@engow )\n\nfixed the issue that some paths data could not be viewed visually. (@engow )\n\nfixed the issue of backup management page 504 error.(@engow)\n\n\n\n## v0.2.0-beta.1 (2022-04-18)\n<hr>\n\n### Breaking Changes\n<hr>\n\nadd new API v1alpha2, refer to [migration document](../docs/migration/README.md) to migrate imported clusters API from v1alpha1 to v1alpha2. (@maudL1n, @lianghao208 )\n\n### Features\n<hr>\n\nsupport kstone-api and kstone-dashboard authentication, default username: ***admin***, default password: ***adm1n@kstone.io***. (@engow, @lianghao208 )\n\nsupport multiple namespaces. (@engow )\n\nsupport auth and tolerations, affinity. (@engow )\n\nsupport etcd cluster password authentication. (@lianghao208 )\n\nadd s3 backup and backup check. (@jianhaiqing )\n\n### Test\n<hr>\n\nadd e2e test for https kstone-etcd-operator cluster. (@maudL1n )\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 [yyyy] [name of copyright owner]\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": ".PHONY: all\nall: lint build\n\n# ==============================================================================\n# Build options\n\nROOT_PACKAGE=tkestack.io/kstone\nVERSION_PACKAGE=tkestack.io/kstone/pkg/app/version\n\n# ==============================================================================\n# Includes\n\ninclude build/lib/common.mk\ninclude build/lib/golang.mk\ninclude build/lib/image.mk\ninclude build/lib/gen.mk\n\n# ==============================================================================\n# Usage\n\ndefine USAGE_OPTIONS\n\nOptions:\n  DEBUG        Whether to generate debug symbols. Default is 0.\n  BINS         The binaries to build. Default is all of cmd.\n               This option is available when using: make build/build.multiarch\n               Example: make build BINS=\"kstone-api kstone-controller\"\n  IMAGES       Backend images to make. Default is all of cmd starting with kstone-.\n               This option is available when using: make image/image.multiarch/push/push.multiarch\n               Example: make image.multiarch IMAGES=\"kstone-api kstone-controller\"\n  PLATFORMS    The multiple platforms to build. Default is linux_amd64 and linux_arm64.\n               This option is available when using: make build.multiarch/image.multiarch/push.multiarch\n               Example: make image.multiarch IMAGES=\"kstone-api kstone-controller\" PLATFORMS=\"linux_amd64 linux_arm64\"\n  VERSION      The version information compiled into binaries.\n               The default is obtained from git.\n  V            Set to 1 enable verbose build. Default is 0.\nendef\nexport USAGE_OPTIONS\n\n# ==============================================================================\n# Targets\n\n## gen: Generate codes for API definitions.\n.PHONY: gen\ngen:\n\t@$(MAKE) gen.run\n\n## build: Build source code for host platform.\n.PHONY: build\nbuild:\n\t@$(MAKE) go.build\n\n## build.multiarch: Build source code for multiple platforms. See option PLATFORMS.\n.PHONY: build.multiarch\nbuild.multiarch:\n\t@$(MAKE) go.build.multiarch\n\n## image: Build docker images for host arch.\n.PHONY: image\nimage:\n\t@$(MAKE) image.build\n\n## image.multiarch: Build docker images for multiple platforms. See option PLATFORMS.\n.PHONY: image.multiarch\nimage.multiarch:\n\t@$(MAKE) image.build.multiarch\n\n## push: Build docker images for host arch and push images to registry.\n.PHONY: push\npush:\n\t@$(MAKE) image.push\n\n## push.multiarch: Build docker images for multiple platforms and push images to registry.\n.PHONY: push.multiarch\npush.multiarch:\n\t@$(MAKE) image.push.multiarch\n\n## manifest: Build docker images for host arch and push manifest list to registry.\n.PHONY: manifest\nmanifest:\n\t@$(MAKE) image.manifest.push\n\n## manifest.multiarch: Build docker images for multiple platforms and push manifest lists to registry.\n.PHONY: manifest.multiarch\nmanifest.multiarch:\n\t@$(MAKE) image.manifest.push.multiarch\n\n## clean: Remove all files that are created by building.\n.PHONY: clean\nclean:\n\t@$(MAKE) go.clean\n\n## lint: Check syntax and styling of go sources.\n.PHONY: lint\nlint:\n\t@$(MAKE) go.lint\n\n## test: Run unit test.\n.PHONY: test\ntest:\n\t@$(MAKE) go.test\n\n## e2e: Run e2e test.\n.PHONY: e2e\ne2e:\n\t@$(MAKE) go.e2e\n\n## release-test: test release\n.PHONY: release-test\nrelease-test:\n\t@go test -v -timeout=1200m tkestack.io/kstone/test/e2e\n\n## help: Show this help info.\n.PHONY: help\nhelp: Makefile\n\t@echo -e \"\\nUsage: make <TARGETS> <OPTIONS> ...\\n\\nTargets:\"\n\t@sed -n 's/^##//p' $< | column -t -s ':' |  sed -e 's/^/ /'\n\t@echo \"$$USAGE_OPTIONS\"\n"
  },
  {
    "path": "README.md",
    "content": "# Kstone\n\n<div align=center><img width=800 hight=300 src=\"docs/images/icon.png\" /></div>\n\n------\n\n[中文](README_CN.md)\n\nKstone is an [etcd](https://github.com/etcd-io/etcd) management platform, providing cluster management, monitoring, backup, inspection, data migration, visual viewing of etcd data, and intelligent diagnosis.\n\nKstone will help you efficiently manage etcd clusters, significantly reduce operation and maintenance costs, discover potential hazards in time, and improve the stability and user experience of k8s etcd storage.\n\n------\n\n## Features\n\n* Supports registration of existing clusters and creation of new etcd clusters.\n* Support prometheus monitoring, built-in rich etcd grafana panel diagram.\n* Support multiple data backup methods (minute-level backup to object storage, real-time backup by deploying learner).\n* Support multiple inspection strategies (data consistency, health, hot write requests, number of resource objects, etc.).\n* Built-in web console and visual view etcd data.\n* Lightweight, easy to install.\n* Support data migration(to do list).\n* Support intelligent diagnosis(to do list).\n\n\n## Architecture\n\nKstone consists of 5 components: kstone-etcdcluster-controller,kstone-etcd-operator,kstone-etcdinspection-controller,kstone-api, kstone-dashboard.\n\n![Architecture Of Kstone](docs/images/kstone-arch.png)\n\n## Components\n\n### [kstone](https://github.com/tkestack/kstone)\n\nkstone consists of kstone-etcdcluster-controller,kstone-etcdinspection-controller,kstone-api.\n\n### [kstone-etcd-operator](https://github.com/tkestack/kstone-etcd-operator)\n\nkstone-etcd-operator provides rich etcd cluster management capabilities.\nplease refer to [kstone-etcd-operator](https://github.com/tkestack/kstone-etcd-operator/blob/main/README.md) document page for more information.\n\n### [kstone-dashboard](https://github.com/tkestack/kstone-dashboard)\n\nThe web management system provided by kstone is as follows:\n\n![kstone-ui](docs/images/kstone-ui.png)\n\n\n## Installation\n\nPlease read [the detailed installation document](charts),\nYou can quickly install kstone through helm.\n\n## Documentation\n\nPlease refer to [document page](docs) for more information.\n\n## Developing\n\n### Build\n\n``` shell\nmkdir -p ~/tkestack\ncd ~/tkestack\ngit clone https://github.com/tkestack/kstone\ncd kstone\nmake\n```\n\n## Contact\n\nFor any question or support, feel free to contact us via:\n- Join [#Kstone Slack channel](https://join.slack.com/t/w1639233173-qqx590963/shared_invite/zt-109muo6i9-0kTUQphSVFlwOSW7CgtrGw)\n- Join WeChat Group Discussion (Join the group by adding kstone assistant WeChat and reply \"kstone\")\n\n<div align=\"center\">\n  <img src=\"docs/images/kstone_assistant.jpg\" width=20% title=\"Kstone_assistant WeChat\">\n</div>\n\n\n## Community\n\n* You are encouraged to communicate most things via GitHub [issues](https://github.com/tkestack/kstone/issues/new/choose) or [pull requests](https://github.com/tkestack/kstone/pulls).\n\n## Licensing\n\nKstone is licensed under the Apache License, Version 2.0. See [LICENSE](LICENSE) for the full license text.\n\n"
  },
  {
    "path": "README_CN.md",
    "content": "# Kstone\n\n<div align=center><img width=800 hight=300 src=\"docs/images/icon.png\" /></div>\n\n------\n\n[English](README.md)\n\nKstone 是一个针对 [etcd](https://github.com/etcd-io/etcd) 的全方位运维解决方案，提供集群管理（关联已有集群、创建新集群等)、监控、备份、巡检、数据迁移、数据可视化、智能诊断等一系列特性。\n\nKstone 将帮助你高效管理etcd集群，显著降低运维成本、及时发现潜在隐患、提升k8s etcd存储的稳定性和用户体验。\n\n------\n\n## 特性\n\nKstone 是一个 [etcd](https://github.com/etcd-io/etcd) 的治理平台，它有以下特点：\n\n* 轻量，安装方便\n* 支持导入已有集群、创建新etcd集群\n* 支持Prometheus监控，内置丰富的etcd Grafana面板图\n* 支持多种数据备份方式(分钟级备份到对象存储、部署Learner实时备份)\n* 支持多种巡检策略（数据一致性、健康度、写请求、资源对象数等)\n* 支持可视化查看etcd数据（特别支持Kubernetes资源对象数据的可视化查看）\n* 极大简化运维成本，在集群导入、创建完成时，即可自动开启监控、备份、巡检等特性\n\n## 核心架构\n\nKstone 由5个组件组成：\n- kstone-etcdcluster-controller\n- kstone-etcdinspection-controller\n- kstone-etcd-operator\n- kstone-api\n- kstone-dashboard\n\n![Architecture Of Kstone](docs/images/kstone-arch.png)\n\n## 组件\n\n### kstone-etcdcluster-controller\n\n* 关联已有集群，如已有的kubernetes集群etcd \n* 根据EtcdCluster资源所描述的集群元信息，调用ClusterProvider创建、更新、删除etcd集群\n* 根据EtcdCluster资源所描述的特性开关，开启或关闭监控、备份、巡检等特性(创建EtcdInspection资源)\n\n### kstone-etcdinspection-controller\n\n* 实时监听EtcdInspection资源，调用后端FeatureProvider执行巡检\n\n### [kstone-etcd-operator](https://github.com/tkestack/kstone-etcd-operator)\n\nkstone-etcd-operator提供丰富的etcd集群管理能力。\n更多信息请参考[kstone-etcd-operator](https://github.com/tkestack/kstone-etcd-operator/blob/main/README.md) 文档页面。\n\n### kstone-api\n\n* 提供了一系列etcd集群管理的api给web前端使用\n\n### [kstone-dashboard](https://github.com/tkestack/kstone-dashboard)\n\nKstone 提供的WEB管理系统如下：\n\n![kstone-ui](docs/images/kstone-ui.png)\n\n\n## 安装\n\n请阅读[部署文档](charts/README_CN.md)，\n你可通过Helm快速安装Kstone。\n\n## 文档\n\n更多文档信息，请阅读[文档](docs) \n\n## 开发\n\n### 构建\n```\nmkdir -p ~/tkestack\ncd ~/tkestack\ngit clone https://github.com/tkestack/kstone\ncd kstone\nmake\n```\n\n## 联系方式\n\n如果您有任何疑问或需要支持，请随时与我们联系：\n- [Slack](https://join.slack.com/t/w1639233173-qqx590963/shared_invite/zt-109muo6i9-0kTUQphSVFlwOSW7CgtrGw)\n- 微信群（添加kstone小助手微信，回复“kstone”入群）\n\n<div align=\"center\">\n  <img src=\"docs/images/kstone_assistant.jpg\" width=20% title=\"kstone_assistant WeChat\">\n</div>\n\n\n## 社区\n\n欢迎大家提交issue和pull request来一起完善、提升Kstone。\n\n## License\n\nKstone is licensed under the Apache License, Version 2.0. See [LICENSE](LICENSE) for the full license text.\n"
  },
  {
    "path": "build/docker/kstone-api/Dockerfile",
    "content": "# Tencent is pleased to support the open source community by making TKEStack\n# available.\n#\n# Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n# this file except in compliance with the License. You may obtain a copy of the\n# License at\n#\n# https://opensource.org/licenses/Apache-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, WITHOUT\n# WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations under the License.\n\nFROM BASE_IMAGE\n\nRUN echo \"hosts: files dns\" >> /etc/nsswitch.conf\n\nWORKDIR /app\nADD kstone-api /app/bin/\nENTRYPOINT [\"/app/bin/kstone-api\"]\n"
  },
  {
    "path": "build/docker/kstone-controller/Dockerfile",
    "content": "# Tencent is pleased to support the open source community by making TKEStack\n# available.\n#\n# Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n# this file except in compliance with the License. You may obtain a copy of the\n# License at\n#\n# https://opensource.org/licenses/Apache-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, WITHOUT\n# WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations under the License.\n\nFROM BASE_IMAGE\n\nRUN echo \"hosts: files dns\" >> /etc/nsswitch.conf\n\nWORKDIR /app\nADD kstone-controller /app/bin/\n\nENTRYPOINT [\"/app/bin/kstone-controller\"]\n"
  },
  {
    "path": "build/docker/tools/code-generator/Dockerfile",
    "content": "# Tencent is pleased to support the open source community by making TKEStack\n# available.\n#\n# Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n# this file except in compliance with the License. You may obtain a copy of the\n# License at\n#\n# https://opensource.org/licenses/Apache-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, WITHOUT\n# WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations under the License.\n\nFROM golang:1.16-alpine\n\nRUN apk add --update --no-cache autoconf automake libtool zlib-dev build-base curl git\n\n# Install the protobuf\nENV PROTOBUF_VERSION 3.17.3\nENV PROTOBUF_URL=https://github.com/protocolbuffers/protobuf/archive/v${PROTOBUF_VERSION}.tar.gz\nRUN curl -L ${PROTOBUF_URL} -o - | tar -xz -C /tmp\nRUN cd /tmp/protobuf-* && \\\n    ./autogen.sh && \\\n    ./configure --disable-shared --enable-static && \\\n    make --silent -j `nproc` install-strip\nRUN cd /tmp && rm -rf protobuf-$PROTOBUF_VERSION \\\n    && protoc --version\n\nENV GOPATH=/go\nENV GO111MODULE=off\n\n# Clone the kubernetes\nENV KUBERNETES_VERSION 1.21.3\nRUN mkdir -p $GOPATH/src/k8s.io \\\n  && git clone -b v$KUBERNETES_VERSION --single-branch https://github.com/kubernetes/kubernetes.git $GOPATH/src/k8s.io/kubernetes\nRUN apk add --update --no-cache rsync file patch\nRUN cd $GOPATH/src/k8s.io/kubernetes \\\n  && make WHAT=\"cmd/genswaggertypedocs vendor/k8s.io/code-generator/cmd/defaulter-gen vendor/k8s.io/code-generator/cmd/client-gen vendor/k8s.io/code-generator/cmd/lister-gen vendor/k8s.io/code-generator/cmd/informer-gen vendor/k8s.io/code-generator/cmd/deepcopy-gen vendor/k8s.io/code-generator/cmd/conversion-gen vendor/k8s.io/code-generator/cmd/go-to-protobuf vendor/k8s.io/code-generator/cmd/go-to-protobuf/protoc-gen-gogo\"\nRUN ln -s $GOPATH/src/k8s.io/kubernetes/vendor/k8s.io/apimachinery $GOPATH/src/k8s.io/apimachinery \\\n  && ln -s $GOPATH/src/k8s.io/kubernetes/vendor/k8s.io/api $GOPATH/src/k8s.io/api\n\n# work around 64MB tmpfs size in Docker 1.6\nENV TMPDIR /tmp.k8s\nRUN mkdir $TMPDIR \\\n  && chmod a+rwx $TMPDIR \\\n  && chmod o+t $TMPDIR\n\n# Get the code coverage tool and goimports\nRUN go get golang.org/x/tools/cmd/cover \\\n           golang.org/x/tools/cmd/goimports \\\n    && go clean -cache\n\nWORKDIR \"$GOPATH/src/k8s.io/kubernetes\"\nADD code.sh /root/\nADD openapi.sh /root/\nADD boilerplate.go.txt /root/\nRUN chmod +x /root/code.sh\nRUN chmod +x /root/openapi.sh\n"
  },
  {
    "path": "build/docker/tools/code-generator/Makefile",
    "content": "# Tencent is pleased to support the open source community by making TKEStack\n# available.\n#\n# Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n# this file except in compliance with the License. You may obtain a copy of the\n# License at\n#\n# https://opensource.org/licenses/Apache-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, WITHOUT\n# WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations under the License.\n\nVERSION = v1.21.3\nREGISTRY_PREFIX ?= tkestack\nIMAGE_NAME ?= code-generator\n\n.PHONY: all\nall: build push\n\n.PHONY: build\nbuild:\n\t@echo \"===========> Building $(IMAGE_NAME) $(VERSION) docker image\"\n\tdocker build --pull -t $(REGISTRY_PREFIX)/$(IMAGE_NAME):$(VERSION) -f ./Dockerfile .\n\n.PHONY: push\npush:\n\t@echo \"===========> Pushing $(IMAGE_NAME) $(VERSION) image to $(REGISTRY_PREFIX)\"\n\tdocker push $(REGISTRY_PREFIX)/$(IMAGE_NAME):$(VERSION)\n"
  },
  {
    "path": "build/docker/tools/code-generator/boilerplate.go.txt",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n"
  },
  {
    "path": "build/docker/tools/code-generator/code.sh",
    "content": "#!/usr/bin/env bash\n\n#\n# Tencent is pleased to support the open source community by making TKEStack\n# available.\n#\n# Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n# this file except in compliance with the License. You may obtain a copy of the\n# License at\n#\n# https://opensource.org/licenses/Apache-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, WITHOUT\n# WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations under the License.\n#\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\n# generate-groups generates everything for a project with external types only, e.g. a project based\n# on CustomResourceDefinitions.\n\nif [[ \"$#\" -lt 4 ]] || [[ \"${1}\" == \"--help\" ]]; then\n  cat <<EOF\nUsage: $(basename \"$0\") <generators> <output-package> <internal-apis-package> <extensiona-apis-package> <groups-versions> ...\n  <generators>        the generators comma separated to run (e.g. deepcopy-external,defaulter-external,client-external,\n                      lister-external,informer-external,deepcopy-internal,defaulter-internal,client-internal,\n                      lister-internal,informer-internal or all-external,all-internal,all).\n  <output-package>    the output package name (e.g. github.com/example/project/pkg/generated).\n  <int-apis-package>  the internal types dir (e.g. github.com/example/project/pkg/apis).\n  <ext-apis-package>  the external types dir (e.g. github.com/example/project/pkg/apis or githubcom/example/apis).\n  <groups-versions>   the groups and their versions in the format \"groupA:v1,v2 groupB:v1 groupC:v2\", relative\n                      to <api-package>.\n  ...                 arbitrary flags passed to all generator binaries.\nExamples:\n  $(basename \"$0\") all-external github.com/example/project/pkg/client github.com/example/project/pkg/apis github.com/example/project/apis \"foo:v1 bar:v1alpha1,v1beta1\"\n  $(basename \"$0\") deepcopy-external,client-external github.com/example/project/pkg/client github.com/example/project/pkg/apis github.com/example/project/apis \"foo:v1 bar:v1alpha1,v1beta1\"\n  $(basename \"$0\") all-internal github.com/example/project/pkg/client github.com/example/project/pkg/apis github.com/example/project/apis \"foo:v1 bar:v1alpha1,v1beta1\"\n  $(basename \"$0\") deepcopy-internal,defaulter-internal,conversion-internal github.com/example/project/pkg/client github.com/example/project/pkg/apis github.com/example/project/apis \"foo:v1 bar:v1alpha1,v1beta1\"\nEOF\n  exit 0\nfi\n\nGENS=\"$1\"\nOUTPUT_PKG=\"$2\"\nINT_APIS_PKG=\"$3\"\nEXT_APIS_PKG=\"$4\"\nGROUPS_WITH_VERSIONS=\"$5\"\nshift 5\n\nGOPATH=${GOPATH:-/go}\nK8S_ROOT=${K8S_ROOT:-/go/src/k8s.io/kubernetes}\nK8S_BIN=${K8S_ROOT}/_output/bin\nPATH=${K8S_BIN}:${PATH}\n\nfunction codegen_join() { local IFS=\"$1\"; shift; echo \"$*\"; }\n\n# enumerate group versions\nALL_FQ_APIS=(${ALL_FQ_APIS:-}) # e.g. k8s.io/kubernetes/pkg/apis/apps k8s.io/api/apps/v1\nINT_FQ_APIS=(${INT_FQ_APIS:-}) # e.g. k8s.io/kubernetes/pkg/apis/apps\nEXT_FQ_APIS=(${EXT_FQ_APIS:-}) # e.g. k8s.io/api/apps/v1\nEXT_PB_APIS=(${EXT_PB_APIS:-}) # e.g. k8s.io/api/apps/v1\n\nfor GVs in ${GROUPS_WITH_VERSIONS}; do\n  IFS=: read -r G Vs <<<\"${GVs}\"\n\n  if [[ -n \"${INT_APIS_PKG}\" ]]; then\n    ALL_FQ_APIS+=(\"${INT_APIS_PKG}/${G}\")\n    INT_FQ_APIS+=(\"${INT_APIS_PKG}/${G}\")\n  fi\n\n  # enumerate versions\n  for V in ${Vs//,/ }; do\n    ALL_FQ_APIS+=(\"${EXT_APIS_PKG}/${G}/${V}\")\n    EXT_FQ_APIS+=(\"${EXT_APIS_PKG}/${G}/${V}\")\n  done\ndone\n\nif [[ \"${GENS}\" = \"all\" ]] || [[ \"${GENS}\" = \"all-external\" ]] || grep -qw \"deepcopy-external\" <<<\"${GENS}\"; then\n  echo \"===========> Generating external deepcopy funcs\"\n  \"${K8S_BIN}\"/deepcopy-gen \\\n        --go-header-file /root/boilerplate.go.txt \\\n        --input-dirs \"$(codegen_join , \"${EXT_FQ_APIS[@]}\")\" \\\n        -O zz_generated.deepcopy \\\n        --bounding-dirs \"${EXT_APIS_PKG}\" \\\n        \"$@\"\nfi\n\nif [[ \"${GENS}\" = \"all\" ]] || [[ \"${GENS}\" = \"all-external\" ]] || grep -qw \"client-external\" <<<\"${GENS}\"; then\n  echo \"===========> Generating external clientset for ${GROUPS_WITH_VERSIONS} at ${OUTPUT_PKG}/clientset\"\n  \"${K8S_BIN}\"/client-gen \\\n        --go-header-file /root/boilerplate.go.txt \\\n        --clientset-name versioned \\\n        --input-base \"\" \\\n        --input \"$(codegen_join , \"${EXT_FQ_APIS[@]}\")\" \\\n        --output-package \"${OUTPUT_PKG}\"/clientset \\\n        \"$@\"\nfi\n\nif [[ \"${GENS}\" = \"all\" ]] || [[ \"${GENS}\" = \"all-external\" ]] || grep -qw \"lister-external\" <<<\"${GENS}\"; then\n  echo \"===========> Generating external listers for ${GROUPS_WITH_VERSIONS} at ${OUTPUT_PKG}/listers\"\n  \"${K8S_BIN}\"/lister-gen \\\n        --go-header-file /root/boilerplate.go.txt \\\n        --input-dirs \"$(codegen_join , \"${EXT_FQ_APIS[@]}\")\" \\\n        --output-package \"${OUTPUT_PKG}\"/listers \\\n        \"$@\"\nfi\n\nif [[ \"${GENS}\" = \"all\" ]] || [[ \"${GENS}\" = \"all-external\" ]] || grep -qw \"informer-external\" <<<\"${GENS}\"; then\n  echo \"===========> Generating external informers for ${GROUPS_WITH_VERSIONS} at ${OUTPUT_PKG}/informers\"\n  \"${K8S_BIN}\"/informer-gen \\\n        --go-header-file /root/boilerplate.go.txt \\\n        --input-dirs \"$(codegen_join , \"${EXT_FQ_APIS[@]}\")\" \\\n        --versioned-clientset-package \"${OUTPUT_PKG}\"/clientset/versioned \\\n        --listers-package \"${OUTPUT_PKG}\"/listers \\\n        --output-package \"${OUTPUT_PKG}\"/informers \\\n        \"$@\"\nfi\n\nif [[ \"${GENS}\" = \"all\" ]] || [[ \"${GENS}\" = \"all-external\" ]] || grep -qw \"defaulter-external\" <<<\"${GENS}\"; then\n  echo \"===========> Generating external defaulters\"\n  \"${K8S_BIN}\"/defaulter-gen \\\n        --go-header-file /root/boilerplate.go.txt \\\n        --input-dirs \"$(codegen_join , \"${EXT_FQ_APIS[@]}\")\" \\\n        -O zz_generated.defaults \\\n        \"$@\"\nfi\n\nif [[ \"${GENS}\" = \"all\" ]] || [[ \"${GENS}\" = \"all-external\" ]] || grep -qw \"conversion-external\" <<<\"${GENS}\"; then\n  echo \"===========> Generating external conversions\"\n  \"${K8S_BIN}\"/conversion-gen \\\n        --go-header-file /root/boilerplate.go.txt \\\n        --input-dirs \"$(codegen_join , \"${ALL_FQ_APIS[@]}\")\" \\\n        -O zz_generated.conversion \\\n        \"$@\"\nfi"
  },
  {
    "path": "build/docker/tools/code-generator/openapi.sh",
    "content": "#!/usr/bin/env bash\n\n#\n# Tencent is pleased to support the open source community by making TKEStack\n# available.\n#\n# Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n# this file except in compliance with the License. You may obtain a copy of the\n# License at\n#\n# https://opensource.org/licenses/Apache-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, WITHOUT\n# WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations under the License.\n#\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\n# generate-groups generates openapi for a project with external types only.\n\nif [[ \"$#\" -lt 2 ]]; then\n    cat <<EOF\nUsage: $(basename \"$0\") <output-package> <apis-package>\n  <output-package>    the output package name (e.g. github.com/example/project/pkg/openapi).\n  <apis-package>      the types dir (e.g. github.com/example/project/pkg/apis).\nExamples:\n  $(basename \"$0\") openapi github.com/example/project/pkg github.com/example/project/pkg/apis\nEOF\n  exit 0\nfi\n\nOUTPUT_PKG=\"$1\"\nAPIS_PKG=\"$2\"\n\nGOPATH=${GOPATH:-/go}\nK8S_ROOT=${K8S_ROOT:-/go/src/k8s.io/kubernetes}\nK8S_BIN=${K8S_ROOT}/_output/bin\nPATH=${K8S_BIN}:${PATH}\n\necho \"===========> Generating external openapi codes\"\n\"${K8S_BIN}\"/openapi-gen \\\n    -O zz_generated.openapi \\\n    --go-header-file \"/root/boilerplate.go.txt\" \\\n    --input-dirs \"${APIS_PKG}\" \\\n    --output-package \"${OUTPUT_PKG}\"\n"
  },
  {
    "path": "build/lib/common.mk",
    "content": "# Tencent is pleased to support the open source community by making TKEStack\n# available.\n#\n# Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n# this file except in compliance with the License. You may obtain a copy of the\n# License at\n#\n# https://opensource.org/licenses/Apache-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, WITHOUT\n# WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations under the License.\n\nSHELL := /bin/bash\n\n# include the common make file\nCOMMON_SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST)))\n\nifeq ($(origin ROOT_DIR),undefined)\nROOT_DIR := $(abspath $(shell cd $(COMMON_SELF_DIR)/../.. && pwd -P))\nendif\nifeq ($(origin OUTPUT_DIR),undefined)\nOUTPUT_DIR := $(ROOT_DIR)/_output\n$(shell mkdir -p $(OUTPUT_DIR))\nendif\nifeq ($(origin TOOLS_DIR),undefined)\nTOOLS_DIR := $(OUTPUT_DIR)/tools\n$(shell mkdir -p $(TOOLS_DIR))\nendif\nifeq ($(origin TMP_DIR),undefined)\nTMP_DIR := $(OUTPUT_DIR)/tmp\n$(shell mkdir -p $(TMP_DIR))\nendif\n\n# set the version number. you should not need to do this\n# for the majority of scenarios.\nifeq ($(origin VERSION), undefined)\nVERSION := $(shell git describe --dirty --always --tags | sed 's/-/./g')\nendif\n# Check if the tree is dirty.  default to dirty\nGIT_TREE_STATE:=\"dirty\"\nifeq (, $(shell git status --porcelain 2>/dev/null))\n\tGIT_TREE_STATE=\"clean\"\nendif\nGIT_COMMIT:=$(shell git rev-parse HEAD)\n\n# The OS must be linux when building docker images\nPLATFORMS ?= linux_amd64 linux_arm64\n# The OS can be linux/windows/darwin when building binaries\n# PLATFORMS ?= darwin_amd64 windows_amd64 linux_amd64 linux_arm64\n\n# Set a specific PLATFORM\nifeq ($(origin PLATFORM), undefined)\n\tifeq ($(origin GOOS), undefined)\n\t\tGOOS := $(shell go env GOOS)\n\tendif\n\tifeq ($(origin GOARCH), undefined)\n\t\tGOARCH := $(shell go env GOARCH)\n\tendif\n\tPLATFORM := $(GOOS)_$(GOARCH)\n\t# Use linux as the default OS when building images\n\tIMAGE_PLAT := linux_$(GOARCH)\nelse\n\tGOOS := $(word 1, $(subst _, ,$(PLATFORM)))\n\tGOARCH := $(word 2, $(subst _, ,$(PLATFORM)))\n\tIMAGE_PLAT := $(PLATFORM)\nendif\n\nCOMMA := ,\nSPACE :=\nSPACE +=\n\n\n\n\n"
  },
  {
    "path": "build/lib/create-manifest.sh",
    "content": "#!/usr/bin/env bash\n\n#\n# Tencent is pleased to support the open source community by making TKEStack\n# available.\n#\n# Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n# this file except in compliance with the License. You may obtain a copy of the\n# License at\n#\n# https://opensource.org/licenses/Apache-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, WITHOUT\n# WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations under the License.\n#\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nREGISTRY_PREFIX=${REGISTRY_PREFIX:-\"tkestack\"}\nPLATFORMS=${PLATFORMS:-\"linux_amd64 linux_arm64\"}\n\nif [ -z ${IMAGE} ]; then\n  echo \"Please provide IMAGE.\"\n  exit 1\nfi\n\nif [ -z ${VERSION} ]; then\n  echo \"Please provide VERSION.\"\n  exit 1\nfi\n\nrm -rf ${HOME}/.docker/manifests/docker.io_${REGISTRY_PREFIX}_${IMAGE}-${VERSION}\nDES_REGISTRY=${REGISTRY_PREFIX}/${IMAGE}\nfor platform in ${PLATFORMS}; do\n  os=${platform%_*}\n  arch=${platform#*_}\n  variant=\"\"\n  if [ ${arch} == \"arm64\" ]; then\n    variant=\"--variant v8\"\n  fi\n\n  docker manifest create --amend ${DES_REGISTRY}:${VERSION} \\\n    ${DES_REGISTRY}-${arch}:${VERSION}\n\n  docker manifest annotate ${DES_REGISTRY}:${VERSION} \\\n\t\t${DES_REGISTRY}-${arch}:${VERSION} \\\n\t\t--os ${os} --arch ${arch} ${variant}\ndone\ndocker manifest push --purge ${DES_REGISTRY}:${VERSION}\n"
  },
  {
    "path": "build/lib/docker-buildx.mk",
    "content": "# Tencent is pleased to support the open source community by making TKEStack\n# available.\n#\n# Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n# this file except in compliance with the License. You may obtain a copy of the\n# License at\n#\n# https://opensource.org/licenses/Apache-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, WITHOUT\n# WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations under the License.\n\n# ==============================================================================\n\n################################################\n## Makefile helper functions for docker buildx\n## Please set VERSION and WORK_DIR before use\n## Example: VERSION=$(VERSION) WORK_DIR=$(Dockerfile_DIR) make docker.buildx.linux_amd64.keepalived\n################################################\n\nDOCKER := docker\nDOCKER_SUPPORTED_API_VERSION ?= 1.40\nDOCKER_VERSION ?= 19.03\n\nREGISTRY_PREFIX ?= tkestack\n\nEXTRA_ARGS ?=\n_DOCKER_BUILD_EXTRA_ARGS :=\n\nifdef HTTP_PROXY\n_DOCKER_BUILD_EXTRA_ARGS += --build-arg HTTP_PROXY=${HTTP_PROXY}\nendif\n\nifneq ($(EXTRA_ARGS), )\n_DOCKER_BUILD_EXTRA_ARGS += $(EXTRA_ARGS)\nendif\n\n.PHONY: docker.verify\ndocker.verify:\n\t$(eval API_VERSION := $(shell $(DOCKER) version | grep -E 'API version: {6}[0-9]' | awk '{print $$3} END { if (NR==0) print 0}' ))\n\t$(eval PASS := $(shell echo \"$(API_VERSION) >= $(DOCKER_SUPPORTED_API_VERSION)\" | bc))\n\t@if [ $(PASS) -ne 1 ]; then \\\n\t\t$(DOCKER) -v ;\\\n\t\techo \"Unsupported docker version. Docker API version should be greater than $(DOCKER_SUPPORTED_API_VERSION) (Or docker version: $(DOCKER_VERSION))\"; \\\n\t\texit 1; \\\n\tfi\n\n.PHONY: docker.buildx.%\ndocker.buildx.%: docker.verify\n\t$(eval IMAGE := $(word 2,$(subst ., ,$*)))\n\t$(eval PLATFORM := $(word 1,$(subst ., ,$*)))\n\t$(eval OS := $(word 1,$(subst _, ,$(PLATFORM))))\n\t$(eval ARCH := $(word 2,$(subst _, ,$(PLATFORM))))\n\t$(eval IMAGE_PLAT := $(subst _,/,$(PLATFORM)))\n\t$(eval IMAGE_NAME := $(REGISTRY_PREFIX)/$(IMAGE)-$(ARCH):$(VERSION))\n\t@echo \"===========> Building docker image $(IMAGE) $(VERSION) for $(IMAGE_PLAT)\"\n\tDOCKER_CLI_EXPERIMENTAL=enabled $(DOCKER) buildx build --pull --platform $(IMAGE_PLAT) --load \\\n\t  -t $(IMAGE_NAME) $(_DOCKER_BUILD_EXTRA_ARGS) $(WORK_DIR)\n\n.PHONY: docker.build.%\ndocker.build.%:  docker.verify\n\t$(eval IMAGE := $(word 2,$(subst ., ,$*)))\n\t$(eval PLATFORM := $(word 1,$(subst ., ,$*)))\n\t$(eval OS := $(word 1,$(subst _, ,$(PLATFORM))))\n\t$(eval ARCH := $(word 2,$(subst _, ,$(PLATFORM))))\n\t$(eval IMAGE_PLAT := $(subst _,/,$(PLATFORM)))\n\t$(eval IMAGE_NAME := $(REGISTRY_PREFIX)/$(IMAGE)-$(ARCH):$(VERSION))\n\t@echo \"===========> Building docker image $(IMAGE) $(VERSION) for $(IMAGE_PLAT)\"\n\n\t$(eval BUILD_SUFFIX := $(_DOCKER_BUILD_EXTRA_ARGS) --pull -t $(REGISTRY_PREFIX)/$(IMAGE)-$(ARCH):$(VERSION) $(WORK_DIR))\n\t$(DOCKER) build --platform $(IMAGE_PLAT) $(BUILD_SUFFIX)\n\n.PHONY: docker.push.%\ndocker.push.%: docker.build.%\n\t@echo \"===========> Pushing image $(IMAGE_NAME)\"\n\t$(DOCKER) push $(IMAGE_NAME)\n\n.PHONY: docker.manifest.%\ndocker.manifest.%: export DOCKER_CLI_EXPERIMENTAL := enabled\ndocker.manifest.%: docker.push.% docker.manifest.remove.%\n\t$(eval MANIFEST_NAME := $(REGISTRY_PREFIX)/$(IMAGE):$(VERSION))\n\t@echo \"===========> Pushing manifest $(MANIFEST_NAME) and then remove the local manifest list\"\n\t@$(DOCKER) manifest create $(MANIFEST_NAME) \\\n\t  $(IMAGE_NAME)\n\t@$(DOCKER) manifest annotate $(MANIFEST_NAME) \\\n\t  $(IMAGE_NAME) \\\n\t  --os $(OS) --arch ${ARCH}\n\t@$(DOCKER) manifest push --purge $(MANIFEST_NAME)\n\n# Docker cli has a bug: https://github.com/docker/cli/issues/954\n# If you find your manifests were not updated,\n# Please manually delete them in $HOME/.docker/manifests/\n# and re-run.\n.PHONY: docker.manifest.remove.%\ndocker.manifest.remove.%:\n\t@rm -rf ${HOME}/.docker/manifests/docker.io_$(REGISTRY_PREFIX)_$(IMAGE)-$(VERSION)\n"
  },
  {
    "path": "build/lib/gen.mk",
    "content": "# Tencent is pleased to support the open source community by making TKEStack\n# available.\n#\n# Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n# this file except in compliance with the License. You may obtain a copy of the\n# License at\n#\n# https://opensource.org/licenses/Apache-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, WITHOUT\n# WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations under the License.\n\n# set the kubernetes apimachinery package dir\nK8S_APIMACHINERY_DIR = $(shell go list -f '{{ .Dir }}' -m k8s.io/apimachinery)\n# set the kubernetes api package dir\nK8S_API_DIR = $(shell go list -f '{{ .Dir }}' -m k8s.io/api)\n# set the gogo protobuf package dir\nGOGO_PROTOBUF_DIR = $(shell go list -f '{{ .Dir }}' -m github.com/gogo/protobuf)\nEXT_PB_APIS = \"k8s.io/api/core/v1 k8s.io/api/apps/v1\"\n# set the code generator image version\nCODE_GENERATOR_VERSION := v1.21.3\nCONTROLLER_GEN_VERSION := v0.6.2\n\n.PHONY: gen.run\ngen.run: gen.api gen.crd\n\n# ==============================================================================\n# Generator\n\n.PHONY: gen.api\ngen.api:\n\t@$(DOCKER) run -it --rm \\\n\t\t-v $(ROOT_DIR):/go/src/$(ROOT_PACKAGE) \\\n\t\t-e EXT_PB_APIS=$(EXT_PB_APIS)\\\n\t \t$(REGISTRY_PREFIX)/code-generator:$(CODE_GENERATOR_VERSION) \\\n\t \t/root/code.sh \\\n\t \tall \\\n\t \t$(ROOT_PACKAGE)/pkg/generated \\\n\t \t$(ROOT_PACKAGE)/pkg/apis \\\n\t \t$(ROOT_PACKAGE)/pkg/apis \\\n\t\t\"kstone:v1alpha1 kstone:v1alpha2\"\n\ngen.crd:\n\t@$(DOCKER) run -it --rm \\\n\t\t-v $(ROOT_DIR):/go/src/$(ROOT_PACKAGE) \\\n\t\t-w /go/src/$(ROOT_PACKAGE) \\\n\t\t$(REGISTRY_PREFIX)/controller-gen:$(CONTROLLER_GEN_VERSION) \\\n\t\tcontroller-gen \\\n\t\tcrd paths=/go/src/$(ROOT_PACKAGE)/pkg/apis/kstone/v1alpha2/... output:crd:dir=/go/src/$(ROOT_PACKAGE)/deploy/crds output:stdout\n"
  },
  {
    "path": "build/lib/golang.mk",
    "content": "# Tencent is pleased to support the open source community by making TKEStack\n# available.\n#\n# Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n# this file except in compliance with the License. You may obtain a copy of the\n# License at\n#\n# https://opensource.org/licenses/Apache-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, WITHOUT\n# WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations under the License.\n\n# ==============================================================================\n# Makefile helper functions for golang\n#\n\nGO := go\nGO_SUPPORTED_VERSIONS ?= 1.13|1.14|1.15|1.16|1.17|1.18\nGO_LDFLAGS += -X $(VERSION_PACKAGE).GitVersion=$(VERSION) \\\n\t-X $(VERSION_PACKAGE).GitCommit=$(GIT_COMMIT) \\\n\t-X $(VERSION_PACKAGE).GitTreeState=$(GIT_TREE_STATE) \\\n\t-X $(VERSION_PACKAGE).BuildDate=$(shell date -u +'%Y-%m-%dT%H:%M:%SZ') \\\n\nifeq ($(GOOS),windows)\n\tGO_OUT_EXT := .exe\nendif\n\nifeq ($(ROOT_PACKAGE),)\n\t$(error the variable ROOT_PACKAGE must be set prior to including golang.mk)\nendif\n\nGOPATH := $(shell go env GOPATH)\nifeq ($(origin GOBIN), undefined)\n\tGOBIN := $(GOPATH)/bin\nendif\n\nCOMMANDS ?= $(filter-out %.md, $(wildcard ${ROOT_DIR}/cmd/*))\nBINS ?= $(foreach cmd,${COMMANDS},$(notdir ${cmd}))\n\nifeq (${COMMANDS},)\n  $(error Could not determine COMMANDS, set ROOT_DIR or run in source dir)\nendif\nifeq (${BINS},)\n  $(error Could not determine BINS, set ROOT_DIR or run in source dir)\nendif\n\n.PHONY: go.build.verify\ngo.build.verify:\nifneq ($(shell $(GO) version | grep -q -E '\\bgo($(GO_SUPPORTED_VERSIONS))\\b' && echo 0 || echo 1), 0)\n\t$(error unsupported go version. Please make install one of the following supported version: '$(GO_SUPPORTED_VERSIONS)')\nendif\n\n.PHONY: go.build.%\ngo.build.%:\n\t$(eval COMMAND := $(word 2,$(subst ., ,$*)))\n\t$(eval PLATFORM := $(word 1,$(subst ., ,$*)))\n\t$(eval OS := $(word 1,$(subst _, ,$(PLATFORM))))\n\t$(eval ARCH := $(word 2,$(subst _, ,$(PLATFORM))))\n\t@echo \"===========> Building binary $(COMMAND) $(VERSION) for $(OS) $(ARCH)\"\n\t@mkdir -p $(OUTPUT_DIR)/$(OS)/$(ARCH)\n\t@CGO_ENABLED=0 GOOS=$(OS) GOARCH=$(ARCH) $(GO) build -o $(OUTPUT_DIR)/$(OS)/$(ARCH)/$(COMMAND)$(GO_OUT_EXT) -ldflags \"$(GO_LDFLAGS)\" $(ROOT_PACKAGE)/cmd/$(COMMAND)\n\n.PHONY: go.build\ngo.build: go.build.verify $(addprefix go.build., $(addprefix $(PLATFORM)., $(BINS)))\n\n.PHONY: go.build.multiarch\ngo.build.multiarch: go.build.verify $(foreach p,$(PLATFORMS),$(addprefix go.build., $(addprefix $(p)., $(BINS))))\n\n.PHONY: go.clean\ngo.clean:\n\t@echo \"===========> Cleaning all build output\"\n\t@rm -rf $(OUTPUT_DIR)\n\n.PHONY: go.lint.verify\ngo.lint.verify: go.build.verify\nifeq (,$(shell which golangci-lint))\n\t@echo \"===========> Installing golangci lint\"\n\t@GO111MODULE=off $(GO) get -u github.com/golangci/golangci-lint/cmd/golangci-lint\nendif\n\n.PHONY: go.lint\ngo.lint: go.lint.verify\n\t@echo \"===========> Run golangci to lint source codes\"\n\t@golangci-lint run $(ROOT_DIR)/...\n\n.PHONY: go.test.verify\ngo.test.verify: go.build.verify\nifeq ($(shell which go-junit-report), )\n\t@echo \"===========> Installing go-junit-report\"\n\t@GO111MODULE=off $(GO) get -u github.com/jstemmer/go-junit-report\nendif\n\n.PHONY: go.test\ngo.test: go.test.verify\n\t@echo \"===========> Run unit test\"\n\t$(GO) test -count=1 -timeout=10m -short -v `go list ./...|grep -v tkestack.io/kstone/test` 2>&1 | tee >(go-junit-report --set-exit-code >$(OUTPUT_DIR)/report.xml)\n\n.PHONY: go.e2e\ngo.e2e:\n\t@echo \"===========> Run e2e test\"\n\t$(GO) test -v tkestack.io/kstone/test/e2e/...\n"
  },
  {
    "path": "build/lib/image.mk",
    "content": "# Tencent is pleased to support the open source community by making TKEStack\n# available.\n#\n# Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n# this file except in compliance with the License. You may obtain a copy of the\n# License at\n#\n# https://opensource.org/licenses/Apache-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, WITHOUT\n# WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations under the License.\n\n# ==============================================================================\n# Makefile helper functions for docker image\n#\n\nDOCKER := docker\nDOCKER_SUPPORTED_API_VERSION ?= 1.32\n\nREGISTRY_PREFIX ?= tkestack\nBASE_IMAGE = alpine:3.14\n\nEXTRA_ARGS ?=\n_DOCKER_BUILD_EXTRA_ARGS :=\n\nifdef HTTP_PROXY\n_DOCKER_BUILD_EXTRA_ARGS += --build-arg HTTP_PROXY=${HTTP_PROXY}\nendif\n\nifneq ($(EXTRA_ARGS), )\n_DOCKER_BUILD_EXTRA_ARGS += $(EXTRA_ARGS)\nendif\n\n# Determine image files by looking into build/docker/*/Dockerfile\nIMAGES_DIR ?= $(wildcard ${ROOT_DIR}/build/docker/*)\n# Determine images names by stripping out the dir names\nIMAGES ?= $(filter-out tools,$(foreach image,${IMAGES_DIR},$(notdir ${image})))\n\nifeq (${IMAGES},)\n  $(error Could not determine IMAGES, set ROOT_DIR or run in source dir)\nendif\n\n.PHONY: image.verify\nimage.verify:\n\t$(eval API_VERSION := $(shell $(DOCKER) version | grep -E 'API version: {1,6}[0-9]' | head -n1 | awk '{print $$3} END { if (NR==0) print 0}' ))\n\t$(eval PASS := $(shell echo \"$(API_VERSION) > $(DOCKER_SUPPORTED_API_VERSION)\" | bc))\n\t@if [ $(PASS) -ne 1 ]; then \\\n\t\t$(DOCKER) -v ;\\\n\t\techo \"Unsupported docker version. Docker API version should be greater than $(DOCKER_SUPPORTED_API_VERSION)\"; \\\n\t\texit 1; \\\n\tfi\n\n.PHONY: image.daemon.verify\nimage.daemon.verify:\n\t$(eval PASS := $(shell $(DOCKER) version | grep -q -E 'Experimental: {1,5}true' && echo 1 || echo 0))\n\t@if [ $(PASS) -ne 1 ]; then \\\n\t\techo \"Experimental features of Docker daemon is not enabled. Please add \\\"experimental\\\": true in '/etc/docker/daemon.json' and then restart Docker daemon.\"; \\\n\t\texit 1; \\\n\tfi\n\n.PHONY: image.build\nimage.build: image.verify go.build.verify $(addprefix image.build., $(addprefix $(IMAGE_PLAT)., $(IMAGES)))\n\n.PHONY: image.build.multiarch\nimage.build.multiarch: image.verify go.build.verify $(foreach p,$(PLATFORMS),$(addprefix image.build., $(addprefix $(p)., $(IMAGES))))\n\n.PHONY: image.build.%\nimage.build.%: go.build.%\n\t$(eval IMAGE := $(COMMAND))\n\t$(eval IMAGE_PLAT := $(subst _,/,$(PLATFORM)))\n\t@echo \"===========> Building docker image $(IMAGE) $(VERSION) for $(IMAGE_PLAT)\"\n\t@mkdir -p $(TMP_DIR)/$(IMAGE)\n\t@cat $(ROOT_DIR)/build/docker/$(IMAGE)/Dockerfile\\\n\t\t| sed \"s#BASE_IMAGE#$(BASE_IMAGE)#g\" >$(TMP_DIR)/$(IMAGE)/Dockerfile\n\t@cp $(OUTPUT_DIR)/$(IMAGE_PLAT)/$(IMAGE) $(TMP_DIR)/$(IMAGE)/\n\t@DST_DIR=$(TMP_DIR)/$(IMAGE) $(ROOT_DIR)/build/docker/$(IMAGE)/build.sh 2>/dev/null || true\n\t$(eval BUILD_SUFFIX := $(_DOCKER_BUILD_EXTRA_ARGS) --pull -t $(REGISTRY_PREFIX)/$(IMAGE)-$(ARCH):$(VERSION) $(TMP_DIR)/$(IMAGE))\n\t#$(MAKE) image.daemon.verify\n\t$(DOCKER) build --platform $(IMAGE_PLAT) $(BUILD_SUFFIX)\n\t@rm -rf $(TMP_DIR)/$(IMAGE)\n\n.PHONY: image.push\nimage.push: image.verify go.build.verify $(addprefix image.push., $(addprefix $(IMAGE_PLAT)., $(IMAGES)))\n\n.PHONY: image.push.multiarch\nimage.push.multiarch: image.verify go.build.verify $(foreach p,$(PLATFORMS),$(addprefix image.push., $(addprefix $(p)., $(IMAGES)))) \n\n.PHONY: image.push.%\nimage.push.%: image.build.%\n\t@echo \"===========> Pushing image $(IMAGE) $(VERSION) to $(REGISTRY_PREFIX)\"\n\t$(DOCKER) push $(REGISTRY_PREFIX)/$(IMAGE)-$(ARCH):$(VERSION)\n\n.PHONY: image.manifest.push\nimage.manifest.push: export DOCKER_CLI_EXPERIMENTAL := enabled\nimage.manifest.push: image.verify go.build.verify \\\n$(addprefix image.manifest.push., $(addprefix $(IMAGE_PLAT)., $(IMAGES)))\n\n.PHONY: image.manifest.push.%\nimage.manifest.push.%: image.push.% image.manifest.remove.%\n\t@echo \"===========> Pushing manifest $(IMAGE) $(VERSION) to $(REGISTRY_PREFIX) and then remove the local manifest list\"\n\t@$(DOCKER) manifest create $(REGISTRY_PREFIX)/$(IMAGE):$(VERSION) \\\n\t\t$(REGISTRY_PREFIX)/$(IMAGE)-$(ARCH):$(VERSION)\n\t@$(DOCKER) manifest annotate $(REGISTRY_PREFIX)/$(IMAGE):$(VERSION) \\\n\t\t$(REGISTRY_PREFIX)/$(IMAGE)-$(ARCH):$(VERSION) \\\n\t\t--os $(OS) --arch ${ARCH}\n\t@$(DOCKER) manifest push --purge $(REGISTRY_PREFIX)/$(IMAGE):$(VERSION)\n\n# Docker cli has a bug: https://github.com/docker/cli/issues/954\n# If you find your manifests were not updated,\n# Please manually delete them in $HOME/.docker/manifests/\n# and re-run.\n.PHONY: image.manifest.remove.%\nimage.manifest.remove.%:\n\t@rm -rf ${HOME}/.docker/manifests/docker.io_$(REGISTRY_PREFIX)_$(IMAGE)-$(VERSION)\n\n.PHONY: image.manifest.push.multiarch\nimage.manifest.push.multiarch: image.push.multiarch $(addprefix image.manifest.push.multiarch., $(IMAGES))\n\n.PHONY: image.manifest.push.multiarch.%\nimage.manifest.push.multiarch.%:\n\t@echo \"===========> Pushing manifest $* $(VERSION) to $(REGISTRY_PREFIX) and then remove the local manifest list\"\n\tREGISTRY_PREFIX=$(REGISTRY_PREFIX) PLATFROMS=\"$(PLATFORMS)\" IMAGE=$* VERSION=$(VERSION) DOCKER_CLI_EXPERIMENTAL=enabled \\\n\t  $(ROOT_DIR)/build/lib/create-manifest.sh \n"
  },
  {
    "path": "build/script/openapi.sh",
    "content": "#!/usr/bin/env bash\n\n#\n# Tencent is pleased to support the open source community by making TKEStack\n# available.\n#\n# Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n# this file except in compliance with the License. You may obtain a copy of the\n# License at\n#\n# https://opensource.org/licenses/Apache-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, WITHOUT\n# WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations under the License.\n#\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nAPI_PACKAGE=\"tkestack.io/kstone/pkg/apis\"\n\nAPI_MACHINERY_DIR=$(go list -f '{{ .Dir }}' -m k8s.io/apimachinery)\nAPI_DIR=$(go list -f '{{ .Dir }}' -m k8s.io/api)\n\n# kubernetes api machinery\napi_machinery=$(\n  grep --color=never -rl '+k8s:openapi-gen=' \"${API_MACHINERY_DIR}\" | \\\n  xargs -n1 dirname | \\\n  sed \"s,^${API_MACHINERY_DIR}/,k8s.io/apimachinery/,\" | \\\n  sort -u\n)\n\n# kubernetes api\napi=$(\n  grep --color=never --exclude-dir=origin -rl '+k8s:openapi-gen=' \"${API_DIR}\" | \\\n  xargs -n1 dirname | \\\n  sed \"s,^${API_DIR}/,k8s.io/api/,\" | \\\n  sort -u\n)\n\ninput_dirs=(\n  ${api_machinery}\n  ${api}\n  \"${API_PACKAGE}\"/kstone/v1alpha2\n)\n\necho \"$(IFS=,; echo \"${input_dirs[*]}\")\"\n"
  },
  {
    "path": "charts/.gitignore",
    "content": "# File created using '.gitignore Generator' for Visual Studio Code: https://bit.ly/vscode-gig\n\n# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,macos,intellij+all\n# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,macos,intellij+all\n\n### Intellij+all ###\n# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider\n# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839\n\n# User-specific stuff\n.idea/**/workspace.xml\n.idea/**/tasks.xml\n.idea/**/usage.statistics.xml\n.idea/**/dictionaries\n.idea/**/shelf\n\n# Generated files\n.idea/**/contentModel.xml\n\n# Sensitive or high-churn files\n.idea/**/dataSources/\n.idea/**/dataSources.ids\n.idea/**/dataSources.local.xml\n.idea/**/sqlDataSources.xml\n.idea/**/dynamic.xml\n.idea/**/uiDesigner.xml\n.idea/**/dbnavigator.xml\n\n# Gradle\n.idea/**/gradle.xml\n.idea/**/libraries\n\n# Gradle and Maven with auto-import\n# When using Gradle or Maven with auto-import, you should exclude module files,\n# since they will be recreated, and may cause churn.  Uncomment if using\n# auto-import.\n# .idea/artifacts\n# .idea/compiler.xml\n# .idea/jarRepositories.xml\n# .idea/modules.xml\n# .idea/*.iml\n# .idea/modules\n# *.iml\n# *.ipr\n\n# CMake\ncmake-build-*/\n\n# Mongo Explorer plugin\n.idea/**/mongoSettings.xml\n\n# File-based project format\n*.iws\n\n# IntelliJ\nout/\n\n# mpeltonen/sbt-idea plugin\n.idea_modules/\n\n# JIRA plugin\natlassian-ide-plugin.xml\n\n# Cursive Clojure plugin\n.idea/replstate.xml\n\n# Crashlytics plugin (for Android Studio and IntelliJ)\ncom_crashlytics_export_strings.xml\ncrashlytics.properties\ncrashlytics-build.properties\nfabric.properties\n\n# Editor-based Rest Client\n.idea/httpRequests\n\n# Android studio 3.1+ serialized cache file\n.idea/caches/build_file_checksums.ser\n\n### Intellij+all Patch ###\n# Ignores the whole .idea folder and all .iml files\n# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360\n\n.idea/\n\n# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023\n\n*.iml\nmodules.xml\n.idea/misc.xml\n*.ipr\n\n# Sonarlint plugin\n.idea/sonarlint\n\n### macOS ###\n# General\n.DS_Store\n.AppleDouble\n.LSOverride\n\n# Icon must end with two \\r\nIcon\n\n\n# Thumbnails\n._*\n\n# Files that might appear in the root of a volume\n.DocumentRevisions-V100\n.fseventsd\n.Spotlight-V100\n.TemporaryItems\n.Trashes\n.VolumeIcon.icns\n.com.apple.timemachine.donotpresent\n\n# Directories potentially created on remote AFP share\n.AppleDB\n.AppleDesktop\nNetwork Trash Folder\nTemporary Items\n.apdisk\n\n### VisualStudioCode ###\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n*.code-workspace\n\n### VisualStudioCode Patch ###\n# Ignore all local history of files\n.history\n.ionide\n\n# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,macos,intellij+all\n\n# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option)\n\nhelmfile/config\n\n"
  },
  {
    "path": "charts/.helmignore",
    "content": "# Patterns to ignore when building packages.\n# This supports shell glob matching, relative path matching, and\n# negation (prefixed with !). Only one pattern per line.\n.DS_Store\n# Common VCS dirs\n.git/\n.gitignore\n.bzr/\n.bzrignore\n.hg/\n.hgignore\n.svn/\n# Common backup files\n*.swp\n*.bak\n*.tmp\n*.orig\n*~\n# Various IDEs\n.project\n.idea/\n*.tmproj\n.vscode/\n"
  },
  {
    "path": "charts/Chart.yaml",
    "content": "apiVersion: v2\nname: kstone\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.1.0\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\"\n"
  },
  {
    "path": "charts/README.md",
    "content": "# Kstone Installation\n\n[中文](README_CN.md)\n\n## 1 Preparation\n\n- Prerequisites\n  - Kubernetes version is between 1.14 and 1.20.\n  - The version of Prometheus Operator is v0.49.0.\n- Apply for a cluster from [TKE](https://cloud.tencent.com/product/tke) or install [Minikube](https://minikube.sigs.k8s.io/docs/start/).\n  - Kstone supports deploy in various cloud vendors and bare k8s cluster environments\n  - In the environments mentioned above, only the corresponding ingress rules need to be configured.\n- Requirements：\n  - For production environment (recommended): Worker >= 4 vCPU 8 GB of Memory.\n  - For test environment (minimum): Worker >= 2 vCPU 2 GB of Memory.\n  - Can access the managed etcd.\n  \n## 2 Install on TKE\n\n[Kstone installation on TKE](../docs/installation/tke.md)\n\n## 3 Install on Minikube\n\n[Kstone installation on Minikube(Mac OS X)](../docs/installation/minikube-macos.md)\n\n[Kstone installation on Minikube(Linux amd64)](../docs/installation/minikube-amd64.md)\n\n## 4 Install on the cluster created by kubeadm\n\n[Kstone installation on the cluster created by kubeadm](../docs/installation/kubeadm_en.md)"
  },
  {
    "path": "charts/README_CN.md",
    "content": "# 安装Kstone\n\n[英文](./)\n\n## 1 资源准备\n\n- 前置条件\n  - Kubernetes集群版本在1.14和1.20之间。\n  - Prometheus-Operator版本为v0.49.0。\n- 申请 [TKE](https://cloud.tencent.com/product/tke) 集群或搭建 [minikube](https://minikube.sigs.k8s.io/docs/start/) 集群。\n  - Kstone 支持部署在多云或原生 K8s 集群中\n  - 只需要安装并配置相对应的 Ingress 转发规则即可\n- 环境要求：\n  - 生产环境配置要求（推荐）：Worker 4C8G以上配置。\n  - 体验环境配置要求（最低）：Worker 2C2G以上配置。\n  - 可访问待管理的目标etcd。\n\n## 2 在 TKE 集群安装 Kstone\n\n[Kstone installation on TKE](../docs/installation/tke.md)\n\n## 3 在 Minikube 集群安装 Kstone\n\n[Kstone installation on Minikube(Mac OS X)](../docs/installation/minikube-macos.md)\n\n[Kstone installation on Minikube(Linux amd64)](../docs/installation/minikube-amd64.md)\n\n## 4 在 kubeadm 集群安装 Kstone\n\n[Kstone installation on the cluster created by kubeadm](../docs/installation/kubeadm_en.md)\n"
  },
  {
    "path": "charts/charts/backup-operator/.helmignore",
    "content": "# Patterns to ignore when building packages.\n# This supports shell glob matching, relative path matching, and\n# negation (prefixed with !). Only one pattern per line.\n.DS_Store\n# Common VCS dirs\n.git/\n.gitignore\n.bzr/\n.bzrignore\n.hg/\n.hgignore\n.svn/\n# Common backup files\n*.swp\n*.bak\n*.tmp\n*.orig\n*~\n# Various IDEs\n.project\n.idea/\n*.tmproj\n.vscode/\n"
  },
  {
    "path": "charts/charts/backup-operator/Chart.yaml",
    "content": "apiVersion: v2\nname: backup-operator\ndescription: A Helm chart for etcd backup operator of kstone\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: 1.0.4\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: \"v1.0.4\"\n"
  },
  {
    "path": "charts/charts/backup-operator/templates/_helpers.tpl",
    "content": "{{/*\nExpand the name of the chart.\n*/}}\n{{- define \"backup-operator.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 \"backup-operator.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 \"backup-operator.chart\" -}}\n{{- printf \"%s-%s\" .Chart.Name .Chart.Version | replace \"+\" \"_\" | trunc 63 | trimSuffix \"-\" }}\n{{- end }}\n\n{{/*\nCommon labels\n*/}}\n{{- define \"backup-operator.labels\" -}}\nhelm.sh/chart: {{ include \"backup-operator.chart\" . }}\n{{ include \"backup-operator.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 \"backup-operator.selectorLabels\" -}}\napp.kubernetes.io/name: {{ include \"backup-operator.name\" . }}\napp.kubernetes.io/instance: {{ .Release.Name }}\n{{- end }}"
  },
  {
    "path": "charts/charts/backup-operator/templates/deployment.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: {{ include \"backup-operator.fullname\" . }}\n  labels:\n    {{- include \"backup-operator.labels\" . | nindent 4 }}\nspec:\n  replicas: {{ .Values.replicaCount }}\n  selector:\n    matchLabels:\n      {{- include \"backup-operator.selectorLabels\" . | nindent 6 }}\n  template:\n    metadata:\n      {{- with .Values.podAnnotations }}\n      annotations:\n        {{- toYaml . | nindent 8 }}\n      {{- end }}\n      labels:\n        {{- include \"backup-operator.selectorLabels\" . | nindent 8 }}\n    spec:\n      {{- with .Values.imagePullSecrets }}\n      imagePullSecrets:\n        {{- toYaml . | nindent 8 }}\n      {{- end }}\n      serviceAccountName: {{ .Values.serviceAccountName }}\n      securityContext:\n        {{- toYaml .Values.podSecurityContext | nindent 8 }}\n      containers:\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          command:\n            - etcd-backup-operator\n          args:\n            - --etcd-client-cert-file=client.pem\n            - --etcd-client-key-file=client-key.pem\n            - --etcd-client-ca-file=ca.pem\n          env:\n            - name: MY_POD_NAMESPACE\n              valueFrom:\n                fieldRef:\n                  apiVersion: v1\n                  fieldPath: metadata.namespace\n            - name: MY_POD_NAME\n              valueFrom:\n                fieldRef:\n                  apiVersion: v1\n                  fieldPath: metadata.name\n          resources:\n            {{- if eq .Values.global.env \"production\" }}\n            {{- toYaml .Values.prodResources | nindent 12 }}\n            {{- else }}\n            {{- toYaml .Values.testResources | nindent 12 }}\n            {{- end }}\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"
  },
  {
    "path": "charts/charts/backup-operator/values.yaml",
    "content": "# Default values for backup-operator.\n# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\n\nreplicaCount: 1\n\nimage:\n  repository: tkestack/etcd-backup-operator\n  pullPolicy: IfNotPresent\n  # Overrides the image tag whose default is the chart appVersion.\n  tag: \"v1.0.6-infra.2\"\n\nimagePullSecrets: []\nnameOverride: \"\"\nfullnameOverride: \"\"\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\nprodResources:\n  limits:\n    cpu: 2\n    memory: 4G\n  requests:\n    cpu: 500m\n    memory: 512Mi\n\ntestResources:\n  limits:\n    cpu: 1\n    memory: 2G\n  requests:\n    cpu: 100m\n    memory: 50Mi\n\nnodeSelector: {}\n\ntolerations: []\n\naffinity: {}\n\nserviceAccountName: kstone"
  },
  {
    "path": "charts/charts/dashboard/.helmignore",
    "content": "# Patterns to ignore when building packages.\n# This supports shell glob matching, relative path matching, and\n# negation (prefixed with !). Only one pattern per line.\n.DS_Store\n# Common VCS dirs\n.git/\n.gitignore\n.bzr/\n.bzrignore\n.hg/\n.hgignore\n.svn/\n# Common backup files\n*.swp\n*.bak\n*.tmp\n*.orig\n*~\n# Various IDEs\n.project\n.idea/\n*.tmproj\n.vscode/\n"
  },
  {
    "path": "charts/charts/dashboard/Chart.yaml",
    "content": "apiVersion: v2\nname: dashboard\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.1.0\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\"\n"
  },
  {
    "path": "charts/charts/dashboard/templates/_helpers.tpl",
    "content": "{{/*\nExpand the name of the chart.\n*/}}\n{{- define \"dashboard.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 \"dashboard.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 \"dashboard.chart\" -}}\n{{- printf \"%s-%s\" .Chart.Name .Chart.Version | replace \"+\" \"_\" | trunc 63 | trimSuffix \"-\" }}\n{{- end }}\n\n{{/*\nCommon labels\n*/}}\n{{- define \"dashboard.labels\" -}}\nhelm.sh/chart: {{ include \"dashboard.chart\" . }}\n{{ include \"dashboard.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 \"dashboard.selectorLabels\" -}}\napp.kubernetes.io/name: {{ include \"dashboard.name\" . }}\napp.kubernetes.io/instance: {{ .Release.Name }}\n{{- end }}"
  },
  {
    "path": "charts/charts/dashboard/templates/deployment.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: {{ include \"dashboard.fullname\" . }}\n  labels:\n    {{- include \"dashboard.labels\" . | nindent 4 }}\nspec:\n  replicas: {{ .Values.replicaCount }}\n  selector:\n    matchLabels:\n      {{- include \"dashboard.selectorLabels\" . | nindent 6 }}\n  template:\n    metadata:\n      {{- with .Values.podAnnotations }}\n      annotations:\n        {{- toYaml . | nindent 8 }}\n      {{- end }}\n      labels:\n        {{- include \"dashboard.selectorLabels\" . | nindent 8 }}\n    spec:\n      {{- with .Values.imagePullSecrets }}\n      imagePullSecrets:\n        {{- toYaml . | nindent 8 }}\n      {{- end }}\n      securityContext:\n        {{- toYaml .Values.podSecurityContext | nindent 8 }}\n      containers:\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          ports:\n            - name: http\n              containerPort: 80\n              protocol: TCP\n          resources:\n            {{- if eq .Values.global.env \"production\" }}\n            {{- toYaml .Values.prodResources | nindent 12 }}\n            {{- else }}\n            {{- toYaml .Values.testResources | nindent 12 }}\n            {{- end }}\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"
  },
  {
    "path": "charts/charts/dashboard/templates/service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  name: {{ include \"dashboard.fullname\" . }}\n  labels:\n    {{- include \"dashboard.labels\" . | nindent 4 }}\nspec:\n  type: {{ .Values.service.type }}\n  ports:\n    - port: {{ .Values.service.port }}\n      targetPort: http\n      protocol: TCP\n      name: http\n  selector:\n    {{- include \"dashboard.selectorLabels\" . | nindent 4 }}\n"
  },
  {
    "path": "charts/charts/dashboard/values.yaml",
    "content": "# Default values for dashboard.\n# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\n\nreplicaCount: 1\n\nimage:\n  repository: tkestack/kstone-dashboard\n  pullPolicy: IfNotPresent\n  # Overrides the image tag whose default is the chart appVersion.\n  tag: \"v0.2.0-beta.1\"\n\nimagePullSecrets: []\nnameOverride: \"\"\nfullnameOverride: \"\"\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\nservice:\n  type: NodePort\n  port: 80\n\nprodResources:\n  limits:\n    cpu: 2\n    memory: 4G\n  requests:\n    cpu: 500m\n    memory: 512Mi\n\ntestResources:\n  limits:\n    cpu: 1\n    memory: 2G\n  requests:\n    cpu: 100m\n    memory: 50Mi\n\nnodeSelector: {}\n\ntolerations: []\n\naffinity: {}\n"
  },
  {
    "path": "charts/charts/dashboard-api/.helmignore",
    "content": "# Patterns to ignore when building packages.\n# This supports shell glob matching, relative path matching, and\n# negation (prefixed with !). Only one pattern per line.\n.DS_Store\n# Common VCS dirs\n.git/\n.gitignore\n.bzr/\n.bzrignore\n.hg/\n.hgignore\n.svn/\n# Common backup files\n*.swp\n*.bak\n*.tmp\n*.orig\n*~\n# Various IDEs\n.project\n.idea/\n*.tmproj\n.vscode/\n"
  },
  {
    "path": "charts/charts/dashboard-api/Chart.yaml",
    "content": "apiVersion: v2\nname: dashboard-api\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.1.0\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\"\n"
  },
  {
    "path": "charts/charts/dashboard-api/templates/_helpers.tpl",
    "content": "{{/*\nExpand the name of the chart.\n*/}}\n{{- define \"dashboard-api.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 \"dashboard-api.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 \"dashboard-api.chart\" -}}\n{{- printf \"%s-%s\" .Chart.Name .Chart.Version | replace \"+\" \"_\" | trunc 63 | trimSuffix \"-\" }}\n{{- end }}\n\n{{/*\nCommon labels\n*/}}\n{{- define \"dashboard-api.labels\" -}}\nhelm.sh/chart: {{ include \"dashboard-api.chart\" . }}\n{{ include \"dashboard-api.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 \"dashboard-api.selectorLabels\" -}}\napp.kubernetes.io/name: {{ include \"dashboard-api.name\" . }}\napp.kubernetes.io/instance: {{ .Release.Name }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/dashboard-api/templates/configmap.yaml",
    "content": "apiVersion: v1\ndata:\n  admin: $2y$10$dgolimSP5PywT3yMaRqppeA5GflVmyf/cWaL6bfmXVk6Rsjlmp0ui\nkind: ConfigMap\nmetadata:\n  name: kstone-api-user"
  },
  {
    "path": "charts/charts/dashboard-api/templates/deployment.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: {{ include \"dashboard-api.fullname\" . }}\n  labels:\n    {{- include \"dashboard-api.labels\" . | nindent 4 }}\nspec:\n  replicas: {{ .Values.replicaCount }}\n  selector:\n    matchLabels:\n      {{- include \"dashboard-api.selectorLabels\" . | nindent 6 }}\n  template:\n    metadata:\n      {{- with .Values.podAnnotations }}\n      annotations:\n        {{- toYaml . | nindent 8 }}\n      {{- end }}\n      labels:\n        {{- include \"dashboard-api.selectorLabels\" . | nindent 8 }}\n    spec:\n      {{- with .Values.imagePullSecrets }}\n      imagePullSecrets:\n        {{- toYaml . | nindent 8 }}\n      {{- end }}\n      serviceAccountName: {{ .Values.serviceAccountName }}\n      securityContext:\n        {{- toYaml .Values.podSecurityContext | nindent 8 }}\n      containers:\n        - env:\n            - name: KUBE_TARGET\n              value: {{ .Values.kube.target }}\n            - name: KUBE_TOKEN\n              value: {{ .Values.kube.token }}\n          name: {{ .Chart.Name }}\n          securityContext:\n            {{- toYaml .Values.securityContext | nindent 12 }}\n          {{- if .Values.global.kstone.tag }}\n          image: \"{{ .Values.image.repository }}:{{ .Values.global.kstone.tag }}\"\n          {{- else }}\n          image: \"{{ .Values.image.repository }}:{{ .Values.image.tag }}\"\n          {{- end }}\n          imagePullPolicy: {{ .Values.image.pullPolicy }}\n          ports:\n            - name: http\n              containerPort: 8080\n              protocol: TCP\n          resources:\n            {{- if eq .Values.global.env \"production\" }}\n            {{- toYaml .Values.prodResources | nindent 12 }}\n            {{- else }}\n            {{- toYaml .Values.testResources | nindent 12 }}\n            {{- end }}\n          volumeMounts:\n            - mountPath: /app/certs/\n              name: certs\n              readOnly: true\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: certs\n          secret:\n            defaultMode: 420\n            secretName: {{ include \"dashboard-api.fullname\" . }}-key"
  },
  {
    "path": "charts/charts/dashboard-api/templates/secret.yaml",
    "content": "apiVersion: v1\ndata:\n  private.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBeURuTHlyS0t4d1lhQVF1VDhSRVZ0bWR1VDYyV0xYTGIvUEs4bStJZG8yd3U1L1oxCmpCTVBIcWFzMjdabGlaeXF5bFVWZ3FsSUxNZUxPYlFtY0JvTUdGNkxuemVreHdEYVdmNTBRYW5JeTNSdFR4UVYKaEdIMnc0ZS8yQnI2NXlucUh6N0NZSy9VUHhWSWRTYWZaZ08vM0VGTWZVZVZRV0RWRWJCaTZWSW5hZzdsQjlRUQo2Q2tPTFM2ZFl5YXJnWWcrWWJZUkliVkVCNmNRTzNvcXJVTzR4OTlpZ3l3Z0Q3dlRReHdOMXB5eHVNbmlRYW5HCkREakludndTdUMxYTlUREdWc0ZXMzU5OUVoeGFuc3FUaUhvMm04YjJwNzdsWFFGYy9Qc1UwNTB6dDgxN1czTVEKbGlQRU5ycUhQTUpTNXhFQkhjdEdzb3Rtc3J6NmNIUklrclFLblFJREFRQUJBb0lCQVFDSDg0NW5aRkdNajUwSwpocVQrTXo2TjZxN2hGUmw2Wkpud3A1VGZOMm91YzU5cHkxUEhONDIxbnpDUndzZ3c1eHFrWlo5RVo5TGs3TnlnCjRxeVN3MnpoQXhsRWs1Q2p1dldIMDVsMm1HVUptRlU4TTRQa3JtdlNHaE51RmV1MUdDV3E3MzhtRFYxTk5CTk4KMEZxODl1RElHZUpvMGprSytrZlNTZlR2UGVRYlF5d3BPdVg3Wmp1RCtLOE9qRzlhWnpNOTYyUERoREJ2VlBCZQpKeXNqV0VqU0d5YWc3NjMza3Y0dWtPeDhycVBRLzJUdStIcElyQTljVXBnVDh6V0UycThxcHdVZzBHY0NuZ21mCnFsZjU1a1lzL1RhMW9iUjNxYVg2bWpKL2dFNlZyUzFpSTc1em5lbkh3Tmp6WExpaE5JL3ZkMXh1QnREV2JLTVUKK0M3bnpPZlZBb0dCQU9vaTNZM2luOGgrTjczYVdyWnIxQ29FNzBFWHg2dFZwdnBTUHJyMmZhUG5UVDBOR1RpUgpsTFJlOEp3WU9nNlgzQjU4SEwxVUtnZ05pT285TS9FSUlMblU0RzdHbDZSTG52NUNBODVtYWJ4Q3JkMTJXeWlpCmVnMy80ODRselFpdDliQ0lFV3VaekcySnBYb2Jzc3FjT0szNjNKKzBtUk1JUDhLTWVVbFlwYVo3QW9HQkFOcnMKU1R6aXhwWm0yYUYrUzNYV0l0TmRjakhMRW1BU1orcVZ6TXRRcHFLUjRlSXlodDNtczRGWmdCSFpxTVMzWTlDLwppdUFQNWJMMTA4NGdtWWJmMjhpRjNyakdhbGdHUkRpaDh6REgyR2pMVitrbE1PUm1GaFRPeDF5SHhTVWVaOEpjCmZ3aG42Y3RxcVRQaE5mQmw0SUV1eklEalZueDdUL09IMkhybDFaUEhBb0dCQU5aeW5LNnFGV05UaDhhU1NtZXYKRjZKczVwNmVJem1ndDlHcXB0NGppaXduWEsxQVpBdFYrL2ZBeFd5VEhBbmx1YTBLVEdCMHlCS2NJdjA0bFd4OAozMHlWMkFKZVR1SWlpVHVrUjB3eXJVSExhT2ZnMGRuRUJ6cnZWejJuamNZWFgyTVRIYkdLS3AxaFoza1NDWTVkCnkrUStVdmpNTnpBaGJCVExDUVBPOTlvbEFvR0FQanhrQ2FvU2VKbGVqemwvTEUybTh0Mmk1Q0x0NDEvNEtNbFQKUWcxNGdjamxKVS9sNVZsN2VHOUFLRkx2VnBVb0RDVVh6dURXRlEwcm5ITEtFbnk3VjRNdk1Pby9PeXowNGdDdwpTUkxYSTl1QzcyWENRM3YrRlFZL3lMOVVQVndxZFNla2VYaEpENm9QMWc3VkxiVllvSUQwWkVPOHg0Q3Exdm1zCmdpdXFqdXNDZ1lFQXI0WVhUWWZQUk9YQXRmN01ETUs5bmVRcHZNUytiMit5RGNhdFM0YitNT0kxY3ViNFFsdDEKMDdWV2RnWnNybTc2bkZ2TDF4SWptREhPZnJPbU1Zd2Y3VGRhYWVIbG1Qa1BvOHc2ZG1lbkdGaHV2Q1lZa3YyagpsS3o2VWhtYzlCNkc4VVlQNzdvWTR5RkhoQU9mVXpTQVF4bEpEV0hzeVA0SmRtZTlYZnNURUU0PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=\nkind: Secret\nmetadata:\n  name: {{ include \"dashboard-api.fullname\" . }}-key\ntype: Opaque"
  },
  {
    "path": "charts/charts/dashboard-api/templates/service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  name: {{ include \"dashboard-api.fullname\" . }}\n  labels:\n    {{- include \"dashboard-api.labels\" . | nindent 4 }}\nspec:\n  type: {{ .Values.service.type }}\n  ports:\n    - port: {{ .Values.service.port }}\n      targetPort: http\n      protocol: TCP\n      name: http\n  selector:\n    {{- include \"dashboard-api.selectorLabels\" . | nindent 4 }}\n"
  },
  {
    "path": "charts/charts/dashboard-api/values.yaml",
    "content": "# Default values for dashboard-api.\n# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\n\nreplicaCount: 1\n\nimage:\n  repository: tkestack/kstone-api-amd64\n  pullPolicy: IfNotPresent\n\nimagePullSecrets: []\nnameOverride: \"\"\nfullnameOverride: \"\"\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\nservice:\n  type: NodePort\n  port: 80\n\nprodResources:\n  limits:\n    cpu: 2\n    memory: 4G\n  requests:\n    cpu: 500m\n    memory: 512Mi\n\ntestResources:\n  limits:\n    cpu: 1\n    memory: 2G\n  requests:\n    cpu: 100m\n    memory: 50Mi\n\nnodeSelector: {}\n\ntolerations: []\n\naffinity: {}\n\nkube:\n  # need to fill\n  token: ${token}\n  target: kubernetes.default.svc.cluster.local:443\n\nserviceAccountName: kstone"
  },
  {
    "path": "charts/charts/etcd-controller/.helmignore",
    "content": "# Patterns to ignore when building packages.\n# This supports shell glob matching, relative path matching, and\n# negation (prefixed with !). Only one pattern per line.\n.DS_Store\n# Common VCS dirs\n.git/\n.gitignore\n.bzr/\n.bzrignore\n.hg/\n.hgignore\n.svn/\n# Common backup files\n*.swp\n*.bak\n*.tmp\n*.orig\n*~\n# Various IDEs\n.project\n.idea/\n*.tmproj\n.vscode/\n"
  },
  {
    "path": "charts/charts/etcd-controller/Chart.yaml",
    "content": "apiVersion: v2\nname: etcd-controller\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.1.0\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\"\n"
  },
  {
    "path": "charts/charts/etcd-controller/templates/_helpers.tpl",
    "content": "{{/*\nExpand the name of the chart.\n*/}}\n{{- define \"etcd-controller.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 \"etcd-controller.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 \"etcd-controller.chart\" -}}\n{{- printf \"%s-%s\" .Chart.Name .Chart.Version | replace \"+\" \"_\" | trunc 63 | trimSuffix \"-\" }}\n{{- end }}\n\n{{/*\nCommon labels\n*/}}\n{{- define \"etcd-controller.labels\" -}}\nhelm.sh/chart: {{ include \"etcd-controller.chart\" . }}\n{{ include \"etcd-controller.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 \"etcd-controller.selectorLabels\" -}}\napp.kubernetes.io/name: {{ include \"etcd-controller.name\" . }}\napp.kubernetes.io/instance: {{ .Release.Name }}\n{{- end }}"
  },
  {
    "path": "charts/charts/etcd-controller/templates/deployment.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: {{ include \"etcd-controller.fullname\" . }}\n  labels:\n    {{- include \"etcd-controller.labels\" . | nindent 4 }}\nspec:\n  replicas: {{ .Values.replicaCount }}\n  selector:\n    matchLabels:\n      {{- include \"etcd-controller.selectorLabels\" . | nindent 6 }}\n  template:\n    metadata:\n      {{- with .Values.podAnnotations }}\n      annotations:\n        {{- toYaml . | nindent 8 }}\n      {{- end }}\n      labels:\n        {{- include \"etcd-controller.selectorLabels\" . | nindent 8 }}\n    spec:\n      {{- with .Values.imagePullSecrets }}\n      imagePullSecrets:\n        {{- toYaml . | nindent 8 }}\n      {{- end }}\n      serviceAccountName: {{ .Values.serviceAccountName }}\n      securityContext:\n        {{- toYaml .Values.podSecurityContext | nindent 8 }}\n      containers:\n        - args:\n            - etcdcluster\n          command:\n            - /app/bin/kstone-controller\n          env:\n            - name: PROM_NAMESPACE\n              value: {{ .Values.promNamespace }}\n          name: {{ .Chart.Name }}\n          securityContext:\n            {{- toYaml .Values.securityContext | nindent 12 }}\n          {{- if .Values.global.kstone.tag }}\n          image: \"{{ .Values.image.repository }}:{{ .Values.global.kstone.tag }}\"\n          {{- else }}\n          image: \"{{ .Values.image.repository }}:{{ .Values.image.tag }}\"\n          {{- end }}\n          imagePullPolicy: {{ .Values.image.pullPolicy }}\n          resources:\n            {{- if eq .Values.global.env \"production\" }}\n            {{- toYaml .Values.prodResources | nindent 12 }}\n            {{- else }}\n            {{- toYaml .Values.testResources | nindent 12 }}\n            {{- end }}\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"
  },
  {
    "path": "charts/charts/etcd-controller/values.yaml",
    "content": "# Default values for etcd-controller.\n# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\n\nreplicaCount: 1\n\nimage:\n  repository: tkestack/kstone-controller-amd64\n  pullPolicy: IfNotPresent\n\nimagePullSecrets: []\nnameOverride: \"\"\nfullnameOverride: \"\"\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\nprodResources:\n  limits:\n    cpu: 2\n    memory: 4G\n  requests:\n    cpu: 500m\n    memory: 512Mi\n\ntestResources:\n  limits:\n    cpu: 1\n    memory: 2G\n  requests:\n    cpu: 100m\n    memory: 50Mi\n\nnodeSelector: {}\n\ntolerations: []\n\naffinity: {}\n\nserviceAccountName: kstone\n\npromNamespace: kstone\n"
  },
  {
    "path": "charts/charts/etcd-operator/.helmignore",
    "content": "# Patterns to ignore when building packages.\n# This supports shell glob matching, relative path matching, and\n# negation (prefixed with !). Only one pattern per line.\n.DS_Store\n# Common VCS dirs\n.git/\n.gitignore\n.bzr/\n.bzrignore\n.hg/\n.hgignore\n.svn/\n# Common backup files\n*.swp\n*.bak\n*.tmp\n*.orig\n*~\n# Various IDEs\n.project\n.idea/\n*.tmproj\n.vscode/\n"
  },
  {
    "path": "charts/charts/etcd-operator/Chart.yaml",
    "content": "apiVersion: v2\nname: etcd-operator\ndescription: A Helm chart for etcd backup operator of kstone\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: 1.0.4\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: \"v1.0.4\"\n"
  },
  {
    "path": "charts/charts/etcd-operator/templates/_helpers.tpl",
    "content": "{{/*\nExpand the name of the chart.\n*/}}\n{{- define \"etcd-operator.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 \"etcd-operator.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 \"etcd-operator.chart\" -}}\n{{- printf \"%s-%s\" .Chart.Name .Chart.Version | replace \"+\" \"_\" | trunc 63 | trimSuffix \"-\" }}\n{{- end }}\n\n{{/*\nCommon labels\n*/}}\n{{- define \"etcd-operator.labels\" -}}\nhelm.sh/chart: {{ include \"etcd-operator.chart\" . }}\n{{ include \"etcd-operator.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 \"etcd-operator.selectorLabels\" -}}\napp.kubernetes.io/name: {{ include \"etcd-operator.name\" . }}\napp.kubernetes.io/instance: {{ .Release.Name }}\n{{- end }}"
  },
  {
    "path": "charts/charts/etcd-operator/templates/configmap.yaml",
    "content": "apiVersion: v1\ndata:\n  3.4.9: |\n    image: ccr.ccs.tencentyun.com/ccs-dev/etcd:v3.4.9\n  3.4.13: |\n    image: ccr.ccs.tencentyun.com/ccs-dev/etcd:v3.4.13\nkind: ConfigMap\nmetadata:\n  labels:\n    cloud.tencent.com/kstone-config-name: etcd-version-global-config\n    cloud.tencent.com/kstone-config-version: 0.0.1\n  name: etcd-version-global-config\n  namespace: {{ .Release.Namespace }}\n---\napiVersion: v1\ndata:\n  tls.crt: |\n    -----BEGIN CERTIFICATE-----\n    MIIDSTCCAjGgAwIBAgIUQxapCztxSiDvusPIrujEiA+k4q0wDQYJKoZIhvcNAQEL\n    BQAwUTELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkdEMQswCQYDVQQHDAJTWjEPMA0G\n    A1UECgwGS3N0b25lMRcwFQYDVQQDDA5Lc3RvbmUgUm9vdCBDQTAeFw0yMjA0MTUx\n    MDIwMjBaFw0zMjA0MTIxMDIwMjBaME8xCzAJBgNVBAYTAkNOMQswCQYDVQQIDAJH\n    RDELMAkGA1UEBwwCU1oxDzANBgNVBAoMBktzdG9uZTEVMBMGA1UEAwwMKi5rc3Rv\n    bmUuc3ZjMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2zOVN79sFHPh\n    Uu9E1g4h212pujyAcVEKsJ59mUSsj54CTrCZJBgP4U2w9DxAYPwB8sE4SY7mCNJ4\n    MLwGJwUW9rmHovLDQHIqhD1uhT7HEwY64l5AuLgOtGtiwB2ybaOsPtJyPbYLz4kY\n    UG1CAvwziPfn+TntcFzbRsJ2YE3BooHIzjSB3tnbZGyCPHjfw9YpnFV0jdnapY2M\n    yhhIfHtqiM9XjvE8A+bkJ1mukBtPbQUGPqz5k3/pZkIFjeGJaGp1Hj+Gun8A8ubt\n    vi4ZDjXrjVSZKRkQL/M9n2WyF8IJ5aqvXgcy5xAyFL5BXxF4lpvNJZ00pyblb5/d\n    m3t61G8KYQIDAQABoxswGTAXBgNVHREEEDAOggwqLmtzdG9uZS5zdmMwDQYJKoZI\n    hvcNAQELBQADggEBAE1KRq6fSEHoYUvbuL0UffGEdi00l5+f6auYB+57YImAnibS\n    /J2I+Kjg5yzjpDXrNivXHiKv8ei83Me0dOcsrfR8k3VeQCMd9ucqa0Z88lDTnrGe\n    srjClYS0eGfsQslFEyESVolgLpf6RQJhMk9PIp+60KqUhiC9RjsHyWRwMMGHmGuC\n    Z/hJ/ljI+G2Kr8Z+OrE3gJxXqXyjRoaqhW+dZESiqiuzx0Yzqze88zX4ftelqTH5\n    uJNVmhWC2kFr/FKjfP6GCfEeI/lnbTCOMfueiISZbRK2J2tWWOhgc37uPcX8N+XB\n    eWJO40lJb/TDtIqsOWW04hqJx4m5tLQK+YRnf0k=\n    -----END CERTIFICATE-----\n  tls.key: |\n    -----BEGIN PRIVATE KEY-----\n    MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDbM5U3v2wUc+FS\n    70TWDiHbXam6PIBxUQqwnn2ZRKyPngJOsJkkGA/hTbD0PEBg/AHywThJjuYI0ngw\n    vAYnBRb2uYei8sNAciqEPW6FPscTBjriXkC4uA60a2LAHbJto6w+0nI9tgvPiRhQ\n    bUIC/DOI9+f5Oe1wXNtGwnZgTcGigcjONIHe2dtkbII8eN/D1imcVXSN2dqljYzK\n    GEh8e2qIz1eO8TwD5uQnWa6QG09tBQY+rPmTf+lmQgWN4YloanUeP4a6fwDy5u2+\n    LhkONeuNVJkpGRAv8z2fZbIXwgnlqq9eBzLnEDIUvkFfEXiWm80lnTSnJuVvn92b\n    e3rUbwphAgMBAAECggEBAL/MYsRkui0rN/1ZXuHte7J2Qgyy47BDORdRlpSFgngn\n    yd0QqO7sHvkFAdCy56H037+JUbcLUjxl7MS3wKpjybQYopXx1OaO/qS3G/168LW0\n    vdFUp0z5v+QeEkoHshg9HnnZqhxVLgBp9NxqvVffVTiDsnZgOWIX3cYMYYfigYuu\n    ZUuN6VdtnIB+zZC84qy8zHBgre5DokFbUmzV4l/qyZYaURinkiBr6FSBvVPoieSl\n    fKIEFyVqpY6GaG7zQQ+hdnc+sfBStdLaF03WDvDnEgBU/z8/6vI36EPF5gSMd+Dv\n    m0tcKeIqw7xPVHfrh/AJTkBGY/Vq+zZL2LdOj3fJAAECgYEA8+Ke3Gp5XVwLjPNq\n    HEODJu1yiurYD/jZ2etpMPzz8Xyz1jMAXRgSa7fC1xbsVauo4ISIZndf8Gb48PU4\n    m7tqbUvfnRoCB/OLPlTeNXedL6ygPgzb6TLrd3LMg+snkUSuJQxKWYmIdcAf2Jfo\n    ww5AyQLlcM1kRL+fduSTWH4uDP0CgYEA5hcR+0mz+YqK5TdL9nVTnMRmNLaAAPAk\n    Low34YsvSZ1gL/0d0pmNkwFmwxdM17JKkfq2CKOLo1A7aBKJSRdq3EhsTNh3qNRu\n    EYTS50V/k/zQ7eCHP+hNp+hkbCCp6m0YjqCiCjrd2if2VZpNR/sivPMydd6M+2Vm\n    DGoo9gXb4jUCgYBnXST3Rikp6Fj85C2UzQhI91oUhnQMUOwD8EIlARBiyPdvUS5W\n    Rl2ISdnKT2za4mYwwfsNcoq22O2pMkVLu6Lfr8iWTO+PbykUweNrxcZY7lD7+3c4\n    3tvtRDpprsCWUQV9rjfUuvWa8lKM+dUs1l2e1BtqM6LLgGuVeEr6tn/OAQKBgFGj\n    O+ESHIZczr1Xal9u75S+5pirbC1pBx1w6N7guI2BBkDgqTUxAFd5dtGfsccSXnz/\n    HJliFciDTiC1+vnxEhxIogx9/a7seIVEwGQId6S1XhgYw0Q8k1kRDpiC2mbwAHeS\n    rQu+KTsfVLq4vdTdWUz7aRsDNLh6GMQs4o2wNH1FAoGALN8PNIR/Sl+XoCEyGFmj\n    vhZONbogmL8e4V66bJhs6gRb4df/Fb64HWJnrr+TLoMIFyueR+OcUzD0bcIhaHem\n    5fztFZw2tHDASXvvFBX8q8plRD8pm+0BQfw3Rb088xdounD0TpkRFX8dIWLjpFVx\n    YHRIG5x6bCuy2MPLoeASJzc=\n    -----END PRIVATE KEY-----\nkind: ConfigMap\nmetadata:\n  name: kstone-etcd-operator-cert\n  namespace: {{ .Release.Namespace }}"
  },
  {
    "path": "charts/charts/etcd-operator/templates/crd.yaml",
    "content": "\n---\napiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.6.2\n  creationTimestamp: null\n  name: etcdclusters.etcd.tkestack.io\nspec:\n  group: etcd.tkestack.io\n  names:\n    kind: EtcdCluster\n    listKind: EtcdClusterList\n    plural: etcdclusters\n    shortNames:\n      - etcd\n    singular: etcdcluster\n  scope: Namespaced\n  versions:\n    - additionalPrinterColumns:\n        - jsonPath: .spec.size\n          name: SIZE\n          type: string\n        - jsonPath: .status.phase\n          name: STATUS\n          type: string\n        - jsonPath: .metadata.creationTimestamp\n          name: AGE\n          type: date\n      name: v1alpha1\n      schema:\n        openAPIV3Schema:\n          description: EtcdCluster is a specification for a EtcdCluster resource\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: Specification of the desired behavior of the EtcdCluster.\n              properties:\n                clientPort:\n                  description: ClientPort is the client port which using to access an\n                    etcd cluster\n                  format: int32\n                  type: integer\n                learners:\n                  description: Learners contains the sequence number of the etcd node\n                    which will be created as a learner node. You can remove the corresponding\n                    sequence number when you want to promote learner to member\n                  items:\n                    type: string\n                  type: array\n                provider:\n                  description: You can choose different Provider as the carrier for\n                    etcd to run\n                  type: string\n                repository:\n                  description: Repository is the name of the repository that hosts etcd\n                    container images. By default, it is `quay.io/coreos/etcd`.\n                  type: string\n                secure:\n                  description: Secure contains the etcd cluster's tls and authentication\n                    configuration\n                  properties:\n                    auth:\n                      description: etcd authorization configuration\n                      properties:\n                        credentialSecret:\n                          description: CredentialSecretRef is a secret reference which\n                            contains username and password\n                          properties:\n                            name:\n                              description: Name is unique within a namespace to reference\n                                a secret resource.\n                              type: string\n                            namespace:\n                              description: Namespace defines the space within which\n                                the secret name must be unique.\n                              type: string\n                          type: object\n                      type: object\n                    tls:\n                      description: TLS represents the etcd whether to use https protocol\n                        to serve\n                      properties:\n                        autoTLSCert:\n                          description: AutoTLSCert contains the cert generating option\n                            of etcd operator\n                          properties:\n                            autoGenerateClientCert:\n                              type: boolean\n                            autoGeneratePeerCert:\n                              type: boolean\n                            autoGenerateServerCert:\n                              type: boolean\n                            externalCASecret:\n                              description: you can use ExternalCASecret to signing the\n                                cert which etcd use, if empty, etcd operator will generate\n                                a self-signed certificate\n                              type: string\n                            extraServerCertSANs:\n                              description: ExtraServerCertSANs sets extra Subject Alternative\n                                Names for the etcd server signing cert.\n                              items:\n                                type: string\n                              type: array\n                          type: object\n                        externalCerts:\n                          description: ExternalCerts means using an extra cert\n                          properties:\n                            clientSecret:\n                              description: ClientSecret contains the certificate and\n                                key which etcd use, including ca.pem, client.crt, client.key\n                              type: string\n                            peerSecret:\n                              description: PeerSecret contains the certificate and key\n                                which etcd use, including ca.pem, peer.crt, peer.key\n                              type: string\n                            serverSecret:\n                              description: ServerSecret contains the certificate and\n                                key which etcd use, including ca.pem, server.crt, server.key\n                              type: string\n                          required:\n                            - clientSecret\n                            - peerSecret\n                            - serverSecret\n                          type: object\n                      type: object\n                  type: object\n                size:\n                  description: Size is the etcd cluster's node count, contains voter\n                    member and learner\n                  format: int32\n                  type: integer\n                template:\n                  description: Template is the etcd cluster's deployment template\n                  properties:\n                    affinity:\n                      description: If specified, the etcd node scheduling constraints\n                      properties:\n                        nodeAffinity:\n                          description: Describes node affinity scheduling rules for\n                            the pod.\n                          properties:\n                            preferredDuringSchedulingIgnoredDuringExecution:\n                              description: The scheduler will prefer to schedule pods\n                                to nodes that satisfy the affinity expressions specified\n                                by this field, but it may choose a node that violates\n                                one or more of the expressions. The node that is most\n                                preferred is the one with the greatest sum of weights,\n                                i.e. for each node that meets all of the scheduling\n                                requirements (resource request, requiredDuringScheduling\n                                affinity expressions, etc.), compute a sum by iterating\n                                through the elements of this field and adding \"weight\"\n                                to the sum if the node matches the corresponding matchExpressions;\n                                the node(s) with the highest sum are the most preferred.\n                              items:\n                                description: An empty preferred scheduling term matches\n                                  all objects with implicit weight 0 (i.e. it's a no-op).\n                                  A null preferred scheduling term matches no objects\n                                  (i.e. is also a no-op).\n                                properties:\n                                  preference:\n                                    description: A node selector term, associated with\n                                      the corresponding weight.\n                                    properties:\n                                      matchExpressions:\n                                        description: A list of node selector requirements\n                                          by node's labels.\n                                        items:\n                                          description: A node selector requirement is\n                                            a selector that contains values, a key,\n                                            and an operator that relates the key and\n                                            values.\n                                          properties:\n                                            key:\n                                              description: The label key that the selector\n                                                applies to.\n                                              type: string\n                                            operator:\n                                              description: Represents a key's relationship\n                                                to a set of values. Valid operators\n                                                are In, NotIn, Exists, DoesNotExist.\n                                                Gt, and Lt.\n                                              type: string\n                                            values:\n                                              description: An array of string values.\n                                                If the operator is In or NotIn, the\n                                                values array must be non-empty. If the\n                                                operator is Exists or DoesNotExist,\n                                                the values array must be empty. If the\n                                                operator is Gt or Lt, the values array\n                                                must have a single element, which will\n                                                be interpreted as an integer. This array\n                                                is replaced during a strategic merge\n                                                patch.\n                                              items:\n                                                type: string\n                                              type: array\n                                          required:\n                                            - key\n                                            - operator\n                                          type: object\n                                        type: array\n                                      matchFields:\n                                        description: A list of node selector requirements\n                                          by node's fields.\n                                        items:\n                                          description: A node selector requirement is\n                                            a selector that contains values, a key,\n                                            and an operator that relates the key and\n                                            values.\n                                          properties:\n                                            key:\n                                              description: The label key that the selector\n                                                applies to.\n                                              type: string\n                                            operator:\n                                              description: Represents a key's relationship\n                                                to a set of values. Valid operators\n                                                are In, NotIn, Exists, DoesNotExist.\n                                                Gt, and Lt.\n                                              type: string\n                                            values:\n                                              description: An array of string values.\n                                                If the operator is In or NotIn, the\n                                                values array must be non-empty. If the\n                                                operator is Exists or DoesNotExist,\n                                                the values array must be empty. If the\n                                                operator is Gt or Lt, the values array\n                                                must have a single element, which will\n                                                be interpreted as an integer. This array\n                                                is replaced during a strategic merge\n                                                patch.\n                                              items:\n                                                type: string\n                                              type: array\n                                          required:\n                                            - key\n                                            - operator\n                                          type: object\n                                        type: array\n                                    type: object\n                                  weight:\n                                    description: Weight associated with matching the\n                                      corresponding nodeSelectorTerm, in the range 1-100.\n                                    format: int32\n                                    type: integer\n                                required:\n                                  - preference\n                                  - weight\n                                type: object\n                              type: array\n                            requiredDuringSchedulingIgnoredDuringExecution:\n                              description: If the affinity requirements specified by\n                                this field are not met at scheduling time, the pod will\n                                not be scheduled onto the node. If the affinity requirements\n                                specified by this field cease to be met at some point\n                                during pod execution (e.g. due to an update), the system\n                                may or may not try to eventually evict the pod from\n                                its node.\n                              properties:\n                                nodeSelectorTerms:\n                                  description: Required. A list of node selector terms.\n                                    The terms are ORed.\n                                  items:\n                                    description: A null or empty node selector term\n                                      matches no objects. The requirements of them are\n                                      ANDed. The TopologySelectorTerm type implements\n                                      a subset of the NodeSelectorTerm.\n                                    properties:\n                                      matchExpressions:\n                                        description: A list of node selector requirements\n                                          by node's labels.\n                                        items:\n                                          description: A node selector requirement is\n                                            a selector that contains values, a key,\n                                            and an operator that relates the key and\n                                            values.\n                                          properties:\n                                            key:\n                                              description: The label key that the selector\n                                                applies to.\n                                              type: string\n                                            operator:\n                                              description: Represents a key's relationship\n                                                to a set of values. Valid operators\n                                                are In, NotIn, Exists, DoesNotExist.\n                                                Gt, and Lt.\n                                              type: string\n                                            values:\n                                              description: An array of string values.\n                                                If the operator is In or NotIn, the\n                                                values array must be non-empty. If the\n                                                operator is Exists or DoesNotExist,\n                                                the values array must be empty. If the\n                                                operator is Gt or Lt, the values array\n                                                must have a single element, which will\n                                                be interpreted as an integer. This array\n                                                is replaced during a strategic merge\n                                                patch.\n                                              items:\n                                                type: string\n                                              type: array\n                                          required:\n                                            - key\n                                            - operator\n                                          type: object\n                                        type: array\n                                      matchFields:\n                                        description: A list of node selector requirements\n                                          by node's fields.\n                                        items:\n                                          description: A node selector requirement is\n                                            a selector that contains values, a key,\n                                            and an operator that relates the key and\n                                            values.\n                                          properties:\n                                            key:\n                                              description: The label key that the selector\n                                                applies to.\n                                              type: string\n                                            operator:\n                                              description: Represents a key's relationship\n                                                to a set of values. Valid operators\n                                                are In, NotIn, Exists, DoesNotExist.\n                                                Gt, and Lt.\n                                              type: string\n                                            values:\n                                              description: An array of string values.\n                                                If the operator is In or NotIn, the\n                                                values array must be non-empty. If the\n                                                operator is Exists or DoesNotExist,\n                                                the values array must be empty. If the\n                                                operator is Gt or Lt, the values array\n                                                must have a single element, which will\n                                                be interpreted as an integer. This array\n                                                is replaced during a strategic merge\n                                                patch.\n                                              items:\n                                                type: string\n                                              type: array\n                                          required:\n                                            - key\n                                            - operator\n                                          type: object\n                                        type: array\n                                    type: object\n                                  type: array\n                              required:\n                                - nodeSelectorTerms\n                              type: object\n                          type: object\n                        podAffinity:\n                          description: Describes pod affinity scheduling rules (e.g.\n                            co-locate this pod in the same node, zone, etc. as some\n                            other pod(s)).\n                          properties:\n                            preferredDuringSchedulingIgnoredDuringExecution:\n                              description: The scheduler will prefer to schedule pods\n                                to nodes that satisfy the affinity expressions specified\n                                by this field, but it may choose a node that violates\n                                one or more of the expressions. The node that is most\n                                preferred is the one with the greatest sum of weights,\n                                i.e. for each node that meets all of the scheduling\n                                requirements (resource request, requiredDuringScheduling\n                                affinity expressions, etc.), compute a sum by iterating\n                                through the elements of this field and adding \"weight\"\n                                to the sum if the node has pods which matches the corresponding\n                                podAffinityTerm; the node(s) with the highest sum are\n                                the most preferred.\n                              items:\n                                description: The weights of all of the matched WeightedPodAffinityTerm\n                                  fields are added per-node to find the most preferred\n                                  node(s)\n                                properties:\n                                  podAffinityTerm:\n                                    description: Required. A pod affinity term, associated\n                                      with the corresponding weight.\n                                    properties:\n                                      labelSelector:\n                                        description: A label query over a set of resources,\n                                          in this case pods.\n                                        properties:\n                                          matchExpressions:\n                                            description: matchExpressions is a list\n                                              of label selector requirements. The requirements\n                                              are ANDed.\n                                            items:\n                                              description: A label selector requirement\n                                                is a selector that contains values,\n                                                a key, and an operator that relates\n                                                the key and values.\n                                              properties:\n                                                key:\n                                                  description: key is the label key\n                                                    that the selector applies to.\n                                                  type: string\n                                                operator:\n                                                  description: operator represents a\n                                                    key's relationship to a set of values.\n                                                    Valid operators are In, NotIn, Exists\n                                                    and DoesNotExist.\n                                                  type: string\n                                                values:\n                                                  description: values is an array of\n                                                    string values. If the operator is\n                                                    In or NotIn, the values array must\n                                                    be non-empty. If the operator is\n                                                    Exists or DoesNotExist, the values\n                                                    array must be empty. This array\n                                                    is replaced during a strategic merge\n                                                    patch.\n                                                  items:\n                                                    type: string\n                                                  type: array\n                                              required:\n                                                - key\n                                                - operator\n                                              type: object\n                                            type: array\n                                          matchLabels:\n                                            additionalProperties:\n                                              type: string\n                                            description: matchLabels is a map of {key,value}\n                                              pairs. A single {key,value} in the matchLabels\n                                              map is equivalent to an element of matchExpressions,\n                                              whose key field is \"key\", the operator\n                                              is \"In\", and the values array contains\n                                              only \"value\". The requirements are ANDed.\n                                            type: object\n                                        type: object\n                                      namespaceSelector:\n                                        description: A label query over the set of namespaces\n                                          that the term applies to. The term is applied\n                                          to the union of the namespaces selected by\n                                          this field and the ones listed in the namespaces\n                                          field. null selector and null or empty namespaces\n                                          list means \"this pod's namespace\". An empty\n                                          selector ({}) matches all namespaces. This\n                                          field is alpha-level and is only honored when\n                                          PodAffinityNamespaceSelector feature is enabled.\n                                        properties:\n                                          matchExpressions:\n                                            description: matchExpressions is a list\n                                              of label selector requirements. The requirements\n                                              are ANDed.\n                                            items:\n                                              description: A label selector requirement\n                                                is a selector that contains values,\n                                                a key, and an operator that relates\n                                                the key and values.\n                                              properties:\n                                                key:\n                                                  description: key is the label key\n                                                    that the selector applies to.\n                                                  type: string\n                                                operator:\n                                                  description: operator represents a\n                                                    key's relationship to a set of values.\n                                                    Valid operators are In, NotIn, Exists\n                                                    and DoesNotExist.\n                                                  type: string\n                                                values:\n                                                  description: values is an array of\n                                                    string values. If the operator is\n                                                    In or NotIn, the values array must\n                                                    be non-empty. If the operator is\n                                                    Exists or DoesNotExist, the values\n                                                    array must be empty. This array\n                                                    is replaced during a strategic merge\n                                                    patch.\n                                                  items:\n                                                    type: string\n                                                  type: array\n                                              required:\n                                                - key\n                                                - operator\n                                              type: object\n                                            type: array\n                                          matchLabels:\n                                            additionalProperties:\n                                              type: string\n                                            description: matchLabels is a map of {key,value}\n                                              pairs. A single {key,value} in the matchLabels\n                                              map is equivalent to an element of matchExpressions,\n                                              whose key field is \"key\", the operator\n                                              is \"In\", and the values array contains\n                                              only \"value\". The requirements are ANDed.\n                                            type: object\n                                        type: object\n                                      namespaces:\n                                        description: namespaces specifies a static list\n                                          of namespace names that the term applies to.\n                                          The term is applied to the union of the namespaces\n                                          listed in this field and the ones selected\n                                          by namespaceSelector. null or empty namespaces\n                                          list and null namespaceSelector means \"this\n                                          pod's namespace\"\n                                        items:\n                                          type: string\n                                        type: array\n                                      topologyKey:\n                                        description: This pod should be co-located (affinity)\n                                          or not co-located (anti-affinity) with the\n                                          pods matching the labelSelector in the specified\n                                          namespaces, where co-located is defined as\n                                          running on a node whose value of the label\n                                          with key topologyKey matches that of any node\n                                          on which any of the selected pods is running.\n                                          Empty topologyKey is not allowed.\n                                        type: string\n                                    required:\n                                      - topologyKey\n                                    type: object\n                                  weight:\n                                    description: weight associated with matching the\n                                      corresponding podAffinityTerm, in the range 1-100.\n                                    format: int32\n                                    type: integer\n                                required:\n                                  - podAffinityTerm\n                                  - weight\n                                type: object\n                              type: array\n                            requiredDuringSchedulingIgnoredDuringExecution:\n                              description: If the affinity requirements specified by\n                                this field are not met at scheduling time, the pod will\n                                not be scheduled onto the node. If the affinity requirements\n                                specified by this field cease to be met at some point\n                                during pod execution (e.g. due to a pod label update),\n                                the system may or may not try to eventually evict the\n                                pod from its node. When there are multiple elements,\n                                the lists of nodes corresponding to each podAffinityTerm\n                                are intersected, i.e. all terms must be satisfied.\n                              items:\n                                description: Defines a set of pods (namely those matching\n                                  the labelSelector relative to the given namespace(s))\n                                  that this pod should be co-located (affinity) or not\n                                  co-located (anti-affinity) with, where co-located\n                                  is defined as running on a node whose value of the\n                                  label with key <topologyKey> matches that of any node\n                                  on which a pod of the set of pods is running\n                                properties:\n                                  labelSelector:\n                                    description: A label query over a set of resources,\n                                      in this case pods.\n                                    properties:\n                                      matchExpressions:\n                                        description: matchExpressions is a list of label\n                                          selector requirements. The requirements are\n                                          ANDed.\n                                        items:\n                                          description: A label selector requirement\n                                            is a selector that contains values, a key,\n                                            and an operator that relates the key and\n                                            values.\n                                          properties:\n                                            key:\n                                              description: key is the label key that\n                                                the selector applies to.\n                                              type: string\n                                            operator:\n                                              description: operator represents a key's\n                                                relationship to a set of values. Valid\n                                                operators are In, NotIn, Exists and\n                                                DoesNotExist.\n                                              type: string\n                                            values:\n                                              description: values is an array of string\n                                                values. If the operator is In or NotIn,\n                                                the values array must be non-empty.\n                                                If the operator is Exists or DoesNotExist,\n                                                the values array must be empty. This\n                                                array is replaced during a strategic\n                                                merge patch.\n                                              items:\n                                                type: string\n                                              type: array\n                                          required:\n                                            - key\n                                            - operator\n                                          type: object\n                                        type: array\n                                      matchLabels:\n                                        additionalProperties:\n                                          type: string\n                                        description: matchLabels is a map of {key,value}\n                                          pairs. A single {key,value} in the matchLabels\n                                          map is equivalent to an element of matchExpressions,\n                                          whose key field is \"key\", the operator is\n                                          \"In\", and the values array contains only \"value\".\n                                          The requirements are ANDed.\n                                        type: object\n                                    type: object\n                                  namespaceSelector:\n                                    description: A label query over the set of namespaces\n                                      that the term applies to. The term is applied\n                                      to the union of the namespaces selected by this\n                                      field and the ones listed in the namespaces field.\n                                      null selector and null or empty namespaces list\n                                      means \"this pod's namespace\". An empty selector\n                                      ({}) matches all namespaces. This field is alpha-level\n                                      and is only honored when PodAffinityNamespaceSelector\n                                      feature is enabled.\n                                    properties:\n                                      matchExpressions:\n                                        description: matchExpressions is a list of label\n                                          selector requirements. The requirements are\n                                          ANDed.\n                                        items:\n                                          description: A label selector requirement\n                                            is a selector that contains values, a key,\n                                            and an operator that relates the key and\n                                            values.\n                                          properties:\n                                            key:\n                                              description: key is the label key that\n                                                the selector applies to.\n                                              type: string\n                                            operator:\n                                              description: operator represents a key's\n                                                relationship to a set of values. Valid\n                                                operators are In, NotIn, Exists and\n                                                DoesNotExist.\n                                              type: string\n                                            values:\n                                              description: values is an array of string\n                                                values. If the operator is In or NotIn,\n                                                the values array must be non-empty.\n                                                If the operator is Exists or DoesNotExist,\n                                                the values array must be empty. This\n                                                array is replaced during a strategic\n                                                merge patch.\n                                              items:\n                                                type: string\n                                              type: array\n                                          required:\n                                            - key\n                                            - operator\n                                          type: object\n                                        type: array\n                                      matchLabels:\n                                        additionalProperties:\n                                          type: string\n                                        description: matchLabels is a map of {key,value}\n                                          pairs. A single {key,value} in the matchLabels\n                                          map is equivalent to an element of matchExpressions,\n                                          whose key field is \"key\", the operator is\n                                          \"In\", and the values array contains only \"value\".\n                                          The requirements are ANDed.\n                                        type: object\n                                    type: object\n                                  namespaces:\n                                    description: namespaces specifies a static list\n                                      of namespace names that the term applies to. The\n                                      term is applied to the union of the namespaces\n                                      listed in this field and the ones selected by\n                                      namespaceSelector. null or empty namespaces list\n                                      and null namespaceSelector means \"this pod's namespace\"\n                                    items:\n                                      type: string\n                                    type: array\n                                  topologyKey:\n                                    description: This pod should be co-located (affinity)\n                                      or not co-located (anti-affinity) with the pods\n                                      matching the labelSelector in the specified namespaces,\n                                      where co-located is defined as running on a node\n                                      whose value of the label with key topologyKey\n                                      matches that of any node on which any of the selected\n                                      pods is running. Empty topologyKey is not allowed.\n                                    type: string\n                                required:\n                                  - topologyKey\n                                type: object\n                              type: array\n                          type: object\n                        podAntiAffinity:\n                          description: Describes pod anti-affinity scheduling rules\n                            (e.g. avoid putting this pod in the same node, zone, etc.\n                            as some other pod(s)).\n                          properties:\n                            preferredDuringSchedulingIgnoredDuringExecution:\n                              description: The scheduler will prefer to schedule pods\n                                to nodes that satisfy the anti-affinity expressions\n                                specified by this field, but it may choose a node that\n                                violates one or more of the expressions. The node that\n                                is most preferred is the one with the greatest sum of\n                                weights, i.e. for each node that meets all of the scheduling\n                                requirements (resource request, requiredDuringScheduling\n                                anti-affinity expressions, etc.), compute a sum by iterating\n                                through the elements of this field and adding \"weight\"\n                                to the sum if the node has pods which matches the corresponding\n                                podAffinityTerm; the node(s) with the highest sum are\n                                the most preferred.\n                              items:\n                                description: The weights of all of the matched WeightedPodAffinityTerm\n                                  fields are added per-node to find the most preferred\n                                  node(s)\n                                properties:\n                                  podAffinityTerm:\n                                    description: Required. A pod affinity term, associated\n                                      with the corresponding weight.\n                                    properties:\n                                      labelSelector:\n                                        description: A label query over a set of resources,\n                                          in this case pods.\n                                        properties:\n                                          matchExpressions:\n                                            description: matchExpressions is a list\n                                              of label selector requirements. The requirements\n                                              are ANDed.\n                                            items:\n                                              description: A label selector requirement\n                                                is a selector that contains values,\n                                                a key, and an operator that relates\n                                                the key and values.\n                                              properties:\n                                                key:\n                                                  description: key is the label key\n                                                    that the selector applies to.\n                                                  type: string\n                                                operator:\n                                                  description: operator represents a\n                                                    key's relationship to a set of values.\n                                                    Valid operators are In, NotIn, Exists\n                                                    and DoesNotExist.\n                                                  type: string\n                                                values:\n                                                  description: values is an array of\n                                                    string values. If the operator is\n                                                    In or NotIn, the values array must\n                                                    be non-empty. If the operator is\n                                                    Exists or DoesNotExist, the values\n                                                    array must be empty. This array\n                                                    is replaced during a strategic merge\n                                                    patch.\n                                                  items:\n                                                    type: string\n                                                  type: array\n                                              required:\n                                                - key\n                                                - operator\n                                              type: object\n                                            type: array\n                                          matchLabels:\n                                            additionalProperties:\n                                              type: string\n                                            description: matchLabels is a map of {key,value}\n                                              pairs. A single {key,value} in the matchLabels\n                                              map is equivalent to an element of matchExpressions,\n                                              whose key field is \"key\", the operator\n                                              is \"In\", and the values array contains\n                                              only \"value\". The requirements are ANDed.\n                                            type: object\n                                        type: object\n                                      namespaceSelector:\n                                        description: A label query over the set of namespaces\n                                          that the term applies to. The term is applied\n                                          to the union of the namespaces selected by\n                                          this field and the ones listed in the namespaces\n                                          field. null selector and null or empty namespaces\n                                          list means \"this pod's namespace\". An empty\n                                          selector ({}) matches all namespaces. This\n                                          field is alpha-level and is only honored when\n                                          PodAffinityNamespaceSelector feature is enabled.\n                                        properties:\n                                          matchExpressions:\n                                            description: matchExpressions is a list\n                                              of label selector requirements. The requirements\n                                              are ANDed.\n                                            items:\n                                              description: A label selector requirement\n                                                is a selector that contains values,\n                                                a key, and an operator that relates\n                                                the key and values.\n                                              properties:\n                                                key:\n                                                  description: key is the label key\n                                                    that the selector applies to.\n                                                  type: string\n                                                operator:\n                                                  description: operator represents a\n                                                    key's relationship to a set of values.\n                                                    Valid operators are In, NotIn, Exists\n                                                    and DoesNotExist.\n                                                  type: string\n                                                values:\n                                                  description: values is an array of\n                                                    string values. If the operator is\n                                                    In or NotIn, the values array must\n                                                    be non-empty. If the operator is\n                                                    Exists or DoesNotExist, the values\n                                                    array must be empty. This array\n                                                    is replaced during a strategic merge\n                                                    patch.\n                                                  items:\n                                                    type: string\n                                                  type: array\n                                              required:\n                                                - key\n                                                - operator\n                                              type: object\n                                            type: array\n                                          matchLabels:\n                                            additionalProperties:\n                                              type: string\n                                            description: matchLabels is a map of {key,value}\n                                              pairs. A single {key,value} in the matchLabels\n                                              map is equivalent to an element of matchExpressions,\n                                              whose key field is \"key\", the operator\n                                              is \"In\", and the values array contains\n                                              only \"value\". The requirements are ANDed.\n                                            type: object\n                                        type: object\n                                      namespaces:\n                                        description: namespaces specifies a static list\n                                          of namespace names that the term applies to.\n                                          The term is applied to the union of the namespaces\n                                          listed in this field and the ones selected\n                                          by namespaceSelector. null or empty namespaces\n                                          list and null namespaceSelector means \"this\n                                          pod's namespace\"\n                                        items:\n                                          type: string\n                                        type: array\n                                      topologyKey:\n                                        description: This pod should be co-located (affinity)\n                                          or not co-located (anti-affinity) with the\n                                          pods matching the labelSelector in the specified\n                                          namespaces, where co-located is defined as\n                                          running on a node whose value of the label\n                                          with key topologyKey matches that of any node\n                                          on which any of the selected pods is running.\n                                          Empty topologyKey is not allowed.\n                                        type: string\n                                    required:\n                                      - topologyKey\n                                    type: object\n                                  weight:\n                                    description: weight associated with matching the\n                                      corresponding podAffinityTerm, in the range 1-100.\n                                    format: int32\n                                    type: integer\n                                required:\n                                  - podAffinityTerm\n                                  - weight\n                                type: object\n                              type: array\n                            requiredDuringSchedulingIgnoredDuringExecution:\n                              description: If the anti-affinity requirements specified\n                                by this field are not met at scheduling time, the pod\n                                will not be scheduled onto the node. If the anti-affinity\n                                requirements specified by this field cease to be met\n                                at some point during pod execution (e.g. due to a pod\n                                label update), the system may or may not try to eventually\n                                evict the pod from its node. When there are multiple\n                                elements, the lists of nodes corresponding to each podAffinityTerm\n                                are intersected, i.e. all terms must be satisfied.\n                              items:\n                                description: Defines a set of pods (namely those matching\n                                  the labelSelector relative to the given namespace(s))\n                                  that this pod should be co-located (affinity) or not\n                                  co-located (anti-affinity) with, where co-located\n                                  is defined as running on a node whose value of the\n                                  label with key <topologyKey> matches that of any node\n                                  on which a pod of the set of pods is running\n                                properties:\n                                  labelSelector:\n                                    description: A label query over a set of resources,\n                                      in this case pods.\n                                    properties:\n                                      matchExpressions:\n                                        description: matchExpressions is a list of label\n                                          selector requirements. The requirements are\n                                          ANDed.\n                                        items:\n                                          description: A label selector requirement\n                                            is a selector that contains values, a key,\n                                            and an operator that relates the key and\n                                            values.\n                                          properties:\n                                            key:\n                                              description: key is the label key that\n                                                the selector applies to.\n                                              type: string\n                                            operator:\n                                              description: operator represents a key's\n                                                relationship to a set of values. Valid\n                                                operators are In, NotIn, Exists and\n                                                DoesNotExist.\n                                              type: string\n                                            values:\n                                              description: values is an array of string\n                                                values. If the operator is In or NotIn,\n                                                the values array must be non-empty.\n                                                If the operator is Exists or DoesNotExist,\n                                                the values array must be empty. This\n                                                array is replaced during a strategic\n                                                merge patch.\n                                              items:\n                                                type: string\n                                              type: array\n                                          required:\n                                            - key\n                                            - operator\n                                          type: object\n                                        type: array\n                                      matchLabels:\n                                        additionalProperties:\n                                          type: string\n                                        description: matchLabels is a map of {key,value}\n                                          pairs. A single {key,value} in the matchLabels\n                                          map is equivalent to an element of matchExpressions,\n                                          whose key field is \"key\", the operator is\n                                          \"In\", and the values array contains only \"value\".\n                                          The requirements are ANDed.\n                                        type: object\n                                    type: object\n                                  namespaceSelector:\n                                    description: A label query over the set of namespaces\n                                      that the term applies to. The term is applied\n                                      to the union of the namespaces selected by this\n                                      field and the ones listed in the namespaces field.\n                                      null selector and null or empty namespaces list\n                                      means \"this pod's namespace\". An empty selector\n                                      ({}) matches all namespaces. This field is alpha-level\n                                      and is only honored when PodAffinityNamespaceSelector\n                                      feature is enabled.\n                                    properties:\n                                      matchExpressions:\n                                        description: matchExpressions is a list of label\n                                          selector requirements. The requirements are\n                                          ANDed.\n                                        items:\n                                          description: A label selector requirement\n                                            is a selector that contains values, a key,\n                                            and an operator that relates the key and\n                                            values.\n                                          properties:\n                                            key:\n                                              description: key is the label key that\n                                                the selector applies to.\n                                              type: string\n                                            operator:\n                                              description: operator represents a key's\n                                                relationship to a set of values. Valid\n                                                operators are In, NotIn, Exists and\n                                                DoesNotExist.\n                                              type: string\n                                            values:\n                                              description: values is an array of string\n                                                values. If the operator is In or NotIn,\n                                                the values array must be non-empty.\n                                                If the operator is Exists or DoesNotExist,\n                                                the values array must be empty. This\n                                                array is replaced during a strategic\n                                                merge patch.\n                                              items:\n                                                type: string\n                                              type: array\n                                          required:\n                                            - key\n                                            - operator\n                                          type: object\n                                        type: array\n                                      matchLabels:\n                                        additionalProperties:\n                                          type: string\n                                        description: matchLabels is a map of {key,value}\n                                          pairs. A single {key,value} in the matchLabels\n                                          map is equivalent to an element of matchExpressions,\n                                          whose key field is \"key\", the operator is\n                                          \"In\", and the values array contains only \"value\".\n                                          The requirements are ANDed.\n                                        type: object\n                                    type: object\n                                  namespaces:\n                                    description: namespaces specifies a static list\n                                      of namespace names that the term applies to. The\n                                      term is applied to the union of the namespaces\n                                      listed in this field and the ones selected by\n                                      namespaceSelector. null or empty namespaces list\n                                      and null namespaceSelector means \"this pod's namespace\"\n                                    items:\n                                      type: string\n                                    type: array\n                                  topologyKey:\n                                    description: This pod should be co-located (affinity)\n                                      or not co-located (anti-affinity) with the pods\n                                      matching the labelSelector in the specified namespaces,\n                                      where co-located is defined as running on a node\n                                      whose value of the label with key topologyKey\n                                      matches that of any node on which any of the selected\n                                      pods is running. Empty topologyKey is not allowed.\n                                    type: string\n                                required:\n                                  - topologyKey\n                                type: object\n                              type: array\n                          type: object\n                      type: object\n                    annotations:\n                      additionalProperties:\n                        type: string\n                      description: 'Annotations is an unstructured key value map stored\n                      with a resource that may be set by external tools to store and\n                      retrieve arbitrary metadata. They are not queryable and should\n                      be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations'\n                      type: object\n                    env:\n                      description: List of environment variables to set in the container.\n                        Cannot be updated.\n                      items:\n                        description: EnvVar represents an environment variable present\n                          in a Container.\n                        properties:\n                          name:\n                            description: Name of the environment variable. Must be a\n                              C_IDENTIFIER.\n                            type: string\n                          value:\n                            description: 'Variable references $(VAR_NAME) are expanded\n                            using the previous defined environment variables in the\n                            container and any service environment variables. If a\n                            variable cannot be resolved, the reference in the input\n                            string will be unchanged. The $(VAR_NAME) syntax can be\n                            escaped with a double $$, ie: $$(VAR_NAME). Escaped references\n                            will never be expanded, regardless of whether the variable\n                            exists or not. Defaults to \"\".'\n                            type: string\n                          valueFrom:\n                            description: Source for the environment variable's value.\n                              Cannot be used if value is not empty.\n                            properties:\n                              configMapKeyRef:\n                                description: Selects a key of a ConfigMap.\n                                properties:\n                                  key:\n                                    description: The key to select.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                    TODO: Add other useful fields. apiVersion, kind,\n                                    uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the ConfigMap or its\n                                      key must be defined\n                                    type: boolean\n                                required:\n                                  - key\n                                type: object\n                              fieldRef:\n                                description: 'Selects a field of the pod: supports metadata.name,\n                                metadata.namespace, `metadata.labels[''<KEY>'']`,\n                                `metadata.annotations[''<KEY>'']`, spec.nodeName,\n                                spec.serviceAccountName, status.hostIP, status.podIP,\n                                status.podIPs.'\n                                properties:\n                                  apiVersion:\n                                    description: Version of the schema the FieldPath\n                                      is written in terms of, defaults to \"v1\".\n                                    type: string\n                                  fieldPath:\n                                    description: Path of the field to select in the\n                                      specified API version.\n                                    type: string\n                                required:\n                                  - fieldPath\n                                type: object\n                              resourceFieldRef:\n                                description: 'Selects a resource of the container: only\n                                resources limits and requests (limits.cpu, limits.memory,\n                                limits.ephemeral-storage, requests.cpu, requests.memory\n                                and requests.ephemeral-storage) are currently supported.'\n                                properties:\n                                  containerName:\n                                    description: 'Container name: required for volumes,\n                                    optional for env vars'\n                                    type: string\n                                  divisor:\n                                    anyOf:\n                                      - type: integer\n                                      - type: string\n                                    description: Specifies the output format of the\n                                      exposed resources, defaults to \"1\"\n                                    pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                    x-kubernetes-int-or-string: true\n                                  resource:\n                                    description: 'Required: resource to select'\n                                    type: string\n                                required:\n                                  - resource\n                                type: object\n                              secretKeyRef:\n                                description: Selects a key of a secret in the pod's\n                                  namespace\n                                properties:\n                                  key:\n                                    description: The key of the secret to select from.  Must\n                                      be a valid secret key.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                    TODO: Add other useful fields. apiVersion, kind,\n                                    uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the Secret or its key\n                                      must be defined\n                                    type: boolean\n                                required:\n                                  - key\n                                type: object\n                            type: object\n                        required:\n                          - name\n                        type: object\n                      type: array\n                    extraArgs:\n                      description: ExtraArgs will be directly used as extra parameters\n                        to start etcd\n                      items:\n                        type: string\n                      type: array\n                    labels:\n                      additionalProperties:\n                        type: string\n                      description: 'Map of string keys and values that can be used to\n                      organize and categorize (scope and select) objects. May match\n                      selectors of replication controllers and services. More info:\n                      http://kubernetes.io/docs/user-guide/labels'\n                      type: object\n                    persistentVolumeClaimSpec:\n                      description: PersistentVolumeClaimSpec is a list of claims that\n                        pods are allowed to reference.\n                      properties:\n                        accessModes:\n                          description: 'AccessModes contains the desired access modes\n                          the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'\n                          items:\n                            type: string\n                          type: array\n                        dataSource:\n                          description: 'This field can be used to specify either: *\n                          An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot)\n                          * An existing PVC (PersistentVolumeClaim) * An existing\n                          custom resource that implements data population (Alpha)\n                          In order to use custom resource types that implement data\n                          population, the AnyVolumeDataSource feature gate must be\n                          enabled. If the provisioner or an external controller can\n                          support the specified data source, it will create a new\n                          volume based on the contents of the specified data source.'\n                          properties:\n                            apiGroup:\n                              description: APIGroup is the group for the resource being\n                                referenced. If APIGroup is not specified, the specified\n                                Kind must be in the core API group. For any other third-party\n                                types, APIGroup is required.\n                              type: string\n                            kind:\n                              description: Kind is the type of resource being referenced\n                              type: string\n                            name:\n                              description: Name is the name of resource being referenced\n                              type: string\n                          required:\n                            - kind\n                            - name\n                          type: object\n                        resources:\n                          description: 'Resources represents the minimum resources the\n                          volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources'\n                          properties:\n                            limits:\n                              additionalProperties:\n                                anyOf:\n                                  - type: integer\n                                  - type: string\n                                pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                x-kubernetes-int-or-string: true\n                              description: 'Limits describes the maximum amount of compute\n                              resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'\n                              type: object\n                            requests:\n                              additionalProperties:\n                                anyOf:\n                                  - type: integer\n                                  - type: string\n                                pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                x-kubernetes-int-or-string: true\n                              description: 'Requests describes the minimum amount of\n                              compute resources required. If Requests is omitted for\n                              a container, it defaults to Limits if that is explicitly\n                              specified, otherwise to an implementation-defined value.\n                              More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'\n                              type: object\n                          type: object\n                        selector:\n                          description: A label query over volumes to consider for binding.\n                          properties:\n                            matchExpressions:\n                              description: matchExpressions is a list of label selector\n                                requirements. The requirements are ANDed.\n                              items:\n                                description: A label selector requirement is a selector\n                                  that contains values, a key, and an operator that\n                                  relates the key and values.\n                                properties:\n                                  key:\n                                    description: key is the label key that the selector\n                                      applies to.\n                                    type: string\n                                  operator:\n                                    description: operator represents a key's relationship\n                                      to a set of values. Valid operators are In, NotIn,\n                                      Exists and DoesNotExist.\n                                    type: string\n                                  values:\n                                    description: values is an array of string values.\n                                      If the operator is In or NotIn, the values array\n                                      must be non-empty. If the operator is Exists or\n                                      DoesNotExist, the values array must be empty.\n                                      This array is replaced during a strategic merge\n                                      patch.\n                                    items:\n                                      type: string\n                                    type: array\n                                required:\n                                  - key\n                                  - operator\n                                type: object\n                              type: array\n                            matchLabels:\n                              additionalProperties:\n                                type: string\n                              description: matchLabels is a map of {key,value} pairs.\n                                A single {key,value} in the matchLabels map is equivalent\n                                to an element of matchExpressions, whose key field is\n                                \"key\", the operator is \"In\", and the values array contains\n                                only \"value\". The requirements are ANDed.\n                              type: object\n                          type: object\n                        storageClassName:\n                          description: 'Name of the StorageClass required by the claim.\n                          More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1'\n                          type: string\n                        volumeMode:\n                          description: volumeMode defines what type of volume is required\n                            by the claim. Value of Filesystem is implied when not included\n                            in claim spec.\n                          type: string\n                        volumeName:\n                          description: VolumeName is the binding reference to the PersistentVolume\n                            backing this claim.\n                          type: string\n                      type: object\n                    resources:\n                      description: Compute Resources required by each etcd node.\n                      properties:\n                        limits:\n                          additionalProperties:\n                            anyOf:\n                              - type: integer\n                              - type: string\n                            pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                            x-kubernetes-int-or-string: true\n                          description: 'Limits describes the maximum amount of compute\n                          resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'\n                          type: object\n                        requests:\n                          additionalProperties:\n                            anyOf:\n                              - type: integer\n                              - type: string\n                            pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                            x-kubernetes-int-or-string: true\n                          description: 'Requests describes the minimum amount of compute\n                          resources required. If Requests is omitted for a container,\n                          it defaults to Limits if that is explicitly specified, otherwise\n                          to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'\n                          type: object\n                      type: object\n                    tolerations:\n                      description: If specified, the pod's tolerations.\n                      items:\n                        description: The pod this Toleration is attached to tolerates\n                          any taint that matches the triple <key,value,effect> using\n                          the matching operator <operator>.\n                        properties:\n                          effect:\n                            description: Effect indicates the taint effect to match.\n                              Empty means match all taint effects. When specified, allowed\n                              values are NoSchedule, PreferNoSchedule and NoExecute.\n                            type: string\n                          key:\n                            description: Key is the taint key that the toleration applies\n                              to. Empty means match all taint keys. If the key is empty,\n                              operator must be Exists; this combination means to match\n                              all values and all keys.\n                            type: string\n                          operator:\n                            description: Operator represents a key's relationship to\n                              the value. Valid operators are Exists and Equal. Defaults\n                              to Equal. Exists is equivalent to wildcard for value,\n                              so that a pod can tolerate all taints of a particular\n                              category.\n                            type: string\n                          tolerationSeconds:\n                            description: TolerationSeconds represents the period of\n                              time the toleration (which must be of effect NoExecute,\n                              otherwise this field is ignored) tolerates the taint.\n                              By default, it is not set, which means tolerate the taint\n                              forever (do not evict). Zero and negative values will\n                              be treated as 0 (evict immediately) by the system.\n                            format: int64\n                            type: integer\n                          value:\n                            description: Value is the taint value the toleration matches\n                              to. If the operator is Exists, the value should be empty,\n                              otherwise just a regular string.\n                            type: string\n                        type: object\n                      type: array\n                    topologySpreadConstraints:\n                      description: TopologySpreadConstraints describes how a group of\n                        pods ought to spread across topology domains. Scheduler will\n                        schedule pods in a way which abides by the constraints. This\n                        field is only honored by clusters that enable the EvenPodsSpread\n                        feature. All topologySpreadConstraints are ANDed.\n                      items:\n                        description: TopologySpreadConstraint specifies how to spread\n                          matching pods among the given topology.\n                        properties:\n                          labelSelector:\n                            description: LabelSelector is used to find matching pods.\n                              Pods that match this label selector are counted to determine\n                              the number of pods in their corresponding topology domain.\n                            properties:\n                              matchExpressions:\n                                description: matchExpressions is a list of label selector\n                                  requirements. The requirements are ANDed.\n                                items:\n                                  description: A label selector requirement is a selector\n                                    that contains values, a key, and an operator that\n                                    relates the key and values.\n                                  properties:\n                                    key:\n                                      description: key is the label key that the selector\n                                        applies to.\n                                      type: string\n                                    operator:\n                                      description: operator represents a key's relationship\n                                        to a set of values. Valid operators are In,\n                                        NotIn, Exists and DoesNotExist.\n                                      type: string\n                                    values:\n                                      description: values is an array of string values.\n                                        If the operator is In or NotIn, the values array\n                                        must be non-empty. If the operator is Exists\n                                        or DoesNotExist, the values array must be empty.\n                                        This array is replaced during a strategic merge\n                                        patch.\n                                      items:\n                                        type: string\n                                      type: array\n                                  required:\n                                    - key\n                                    - operator\n                                  type: object\n                                type: array\n                              matchLabels:\n                                additionalProperties:\n                                  type: string\n                                description: matchLabels is a map of {key,value} pairs.\n                                  A single {key,value} in the matchLabels map is equivalent\n                                  to an element of matchExpressions, whose key field\n                                  is \"key\", the operator is \"In\", and the values array\n                                  contains only \"value\". The requirements are ANDed.\n                                type: object\n                            type: object\n                          maxSkew:\n                            description: 'MaxSkew describes the degree to which pods\n                            may be unevenly distributed. When `whenUnsatisfiable=DoNotSchedule`,\n                            it is the maximum permitted difference between the number\n                            of matching pods in the target topology and the global\n                            minimum. For example, in a 3-zone cluster, MaxSkew is\n                            set to 1, and pods with the same labelSelector spread\n                            as 1/1/0: | zone1 | zone2 | zone3 | |   P   |   P   |       |\n                            - if MaxSkew is 1, incoming pod can only be scheduled\n                            to zone3 to become 1/1/1; scheduling it onto zone1(zone2)\n                            would make the ActualSkew(2-0) on zone1(zone2) violate\n                            MaxSkew(1). - if MaxSkew is 2, incoming pod can be scheduled\n                            onto any zone. When `whenUnsatisfiable=ScheduleAnyway`,\n                            it is used to give higher precedence to topologies that\n                            satisfy it. It''s a required field. Default value is 1\n                            and 0 is not allowed.'\n                            format: int32\n                            type: integer\n                          topologyKey:\n                            description: TopologyKey is the key of node labels. Nodes\n                              that have a label with this key and identical values are\n                              considered to be in the same topology. We consider each\n                              <key, value> as a \"bucket\", and try to put balanced number\n                              of pods into each bucket. It's a required field.\n                            type: string\n                          whenUnsatisfiable:\n                            description: 'WhenUnsatisfiable indicates how to deal with\n                            a pod if it doesn''t satisfy the spread constraint. -\n                            DoNotSchedule (default) tells the scheduler not to schedule\n                            it. - ScheduleAnyway tells the scheduler to schedule the\n                            pod in any location,   but giving higher precedence to\n                            topologies that would help reduce the   skew. A constraint\n                            is considered \"Unsatisfiable\" for an incoming pod if and\n                            only if every possible node assigment for that pod would\n                            violate \"MaxSkew\" on some topology. For example, in a\n                            3-zone cluster, MaxSkew is set to 1, and pods with the\n                            same labelSelector spread as 3/1/1: | zone1 | zone2 |\n                            zone3 | | P P P |   P   |   P   | If WhenUnsatisfiable\n                            is set to DoNotSchedule, incoming pod can only be scheduled\n                            to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1)\n                            on zone2(zone3) satisfies MaxSkew(1). In other words,\n                            the cluster can still be imbalanced, but scheduler won''t\n                            make it *more* imbalanced. It''s a required field.'\n                            type: string\n                        required:\n                          - maxSkew\n                          - topologyKey\n                          - whenUnsatisfiable\n                        type: object\n                      type: array\n                      x-kubernetes-list-map-keys:\n                        - topologyKey\n                        - whenUnsatisfiable\n                      x-kubernetes-list-type: map\n                  type: object\n                version:\n                  description: Version is the etcd cluster version, which follow the\n                    semantic versioning specification, like v3.4.13\n                  type: string\n              required:\n                - size\n                - version\n              type: object\n            status:\n              description: Most recently observed status of the EtcdCluster.\n              properties:\n                clientCertSecretName:\n                  type: string\n                conditions:\n                  items:\n                    description: EtcdClusterCondition contains details for the current\n                      condition of this etcdcluster.\n                    properties:\n                      lastHeartbeatTime:\n                        description: Last time we got an update on a given condition.\n                        format: date-time\n                        type: string\n                      lastTransitionTime:\n                        description: Last time the condition transit from one status\n                          to another.\n                        format: date-time\n                        type: string\n                      message:\n                        description: Human readable message indicating details about\n                          last transition.\n                        type: string\n                      reason:\n                        description: (brief) reason for the condition's last transition.\n                        type: string\n                      status:\n                        description: Status of the condition, one of True, False, Unknown.\n                        type: string\n                      type:\n                        description: Type of etcdcluster condition.\n                        type: string\n                    required:\n                      - status\n                      - type\n                    type: object\n                  type: array\n                controlPaused:\n                  type: boolean\n                loadBalancer:\n                  description: LoadBalancerStatus represents the status of a load-balancer.\n                  properties:\n                    ingress:\n                      description: Ingress is a list containing ingress points for the\n                        load-balancer. Traffic intended for the service should be sent\n                        to these ingress points.\n                      items:\n                        description: 'LoadBalancerIngress represents the status of a\n                        load-balancer ingress point: traffic intended for the service\n                        should be sent to an ingress point.'\n                        properties:\n                          hostname:\n                            description: Hostname is set for load-balancer ingress points\n                              that are DNS based (typically AWS load-balancers)\n                            type: string\n                          ip:\n                            description: IP is set for load-balancer ingress points\n                              that are IP based (typically GCE or OpenStack load-balancers)\n                            type: string\n                          ports:\n                            description: Ports is a list of records of service ports\n                              If used, every port defined in the service should have\n                              an entry in it\n                            items:\n                              properties:\n                                error:\n                                  description: 'Error is to record the problem with\n                                  the service port The format of the error shall comply\n                                  with the following rules: - built-in error values\n                                  shall be specified in this file and those shall\n                                  use   CamelCase names - cloud provider specific\n                                  error values must have names that comply with the   format\n                                  foo.example.com/CamelCase. --- The regex it matches\n                                  is (dns1123SubdomainFmt/)?(qualifiedNameFmt)'\n                                  maxLength: 316\n                                  pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$\n                                  type: string\n                                port:\n                                  description: Port is the port number of the service\n                                    port of which status is recorded here\n                                  format: int32\n                                  type: integer\n                                protocol:\n                                  default: TCP\n                                  description: 'Protocol is the protocol of the service\n                                  port of which status is recorded here The supported\n                                  values are: \"TCP\", \"UDP\", \"SCTP\"'\n                                  type: string\n                              required:\n                                - port\n                                - protocol\n                              type: object\n                            type: array\n                            x-kubernetes-list-type: atomic\n                        type: object\n                      type: array\n                  type: object\n                members:\n                  items:\n                    description: EtcdMember describe the status of an etcd cluster member\n                      node\n                    properties:\n                      clientURLs:\n                        items:\n                          type: string\n                        type: array\n                      endpoint:\n                        type: string\n                      id:\n                        format: uint64\n                        type: number\n                      name:\n                        type: string\n                      role:\n                        description: EtcdMemberRole define the role type of etcd node\n                        type: string\n                      status:\n                        description: EtcdMemberStatus define the status of an etcd cluster\n                          member\n                        type: string\n                      version:\n                        type: string\n                    required:\n                      - id\n                    type: object\n                  type: array\n                phase:\n                  description: EtcdClusterPhase is a label for the condition of an etcd\n                    cluster at the current time.\n                  type: string\n              type: object\n          type: object\n      served: true\n      storage: true\n      subresources:\n        status: {}\nstatus:\n  acceptedNames:\n    kind: \"\"\n    plural: \"\"\n  conditions: []\n  storedVersions: []"
  },
  {
    "path": "charts/charts/etcd-operator/templates/deployment.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: {{ include \"etcd-operator.fullname\" . }}\n  labels:\n    {{- include \"etcd-operator.labels\" . | nindent 4 }}\n  namespace: {{ .Release.Namespace }}\nspec:\n  replicas: {{ .Values.replicaCount }}\n  selector:\n    matchLabels:\n      {{- include \"etcd-operator.selectorLabels\" . | nindent 6 }}\n  template:\n    metadata:\n      {{- with .Values.podAnnotations }}\n      annotations:\n        {{- toYaml . | nindent 8 }}\n      {{- end }}\n      labels:\n        {{- include \"etcd-operator.selectorLabels\" . | nindent 8 }}\n    spec:\n      {{- with .Values.imagePullSecrets }}\n      imagePullSecrets:\n        {{- toYaml . | nindent 8 }}\n      {{- end }}\n      serviceAccountName: {{ .Values.serviceAccountName }}\n      securityContext:\n        {{- toYaml .Values.podSecurityContext | nindent 8 }}\n      containers:\n        - name: {{ .Chart.Name }}\n          command:\n            - /app/bin/kstone-etcd-operator\n          args:\n            - --leader-elect-resource-namespace\n            - {{ .Release.Namespace }}\n            - --tls-cert-file\n            - \"/etc/certs/tls.crt\"\n            - --tls-private-key-file\n            - \"/etc/certs/tls.key\"\n            - --v\n            - \"3\"\n          env:\n            - name: WATCH_NAMESPACE\n              value: {{ .Release.Namespace }}\n            - name: POD_NAME\n              valueFrom:\n                fieldRef:\n                  apiVersion: v1\n                  fieldPath: metadata.name\n            - name: OPERATOR_NAME\n              value: {{ include \"etcd-operator.fullname\" . }}\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/certs\n              name: kstone-etcd-operator-cert\n          resources:\n            {{- if eq .Values.global.env \"production\" }}\n            {{- toYaml .Values.prodResources | nindent 12 }}\n            {{- else }}\n            {{- toYaml .Values.testResources | nindent 12 }}\n            {{- end }}\n      volumes:\n        - configMap:\n            defaultMode: 420\n            name: kstone-etcd-operator-cert\n          name: kstone-etcd-operator-cert\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"
  },
  {
    "path": "charts/charts/etcd-operator/templates/service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  name: {{ include \"etcd-operator.fullname\" . }}\n  labels:\n    {{- include \"etcd-operator.labels\" . | nindent 4 }}\nspec:\n  type: {{ .Values.service.type }}\n  ports:\n    - port: {{ .Values.service.port }}\n      targetPort: {{ .Values.service.port }}\n      protocol: TCP\n      name: tcp\n  selector:\n    {{- include \"etcd-operator.selectorLabels\" . | nindent 4 }}\n"
  },
  {
    "path": "charts/charts/etcd-operator/templates/webhook.yaml",
    "content": "apiVersion: admissionregistration.k8s.io/v1\nkind: MutatingWebhookConfiguration\nmetadata:\n  name: kstone-etcd-operator-mutating-admission\nwebhooks:\n  - clientConfig:\n      caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURnekNDQW11Z0F3SUJBZ0lVRTFRcmYwYmZvZU9pdnFSL2w4ZldsTVI1cmdBd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1VURUxNQWtHQTFVRUJoTUNRMDR4Q3pBSkJnTlZCQWdNQWtkRU1Rc3dDUVlEVlFRSERBSlRXakVQTUEwRwpBMVVFQ2d3R1MzTjBiMjVsTVJjd0ZRWURWUVFEREE1TGMzUnZibVVnVW05dmRDQkRRVEFlRncweU1qQTBNVFV4Ck1ESXdNRFphRncwek1qQTBNVEl4TURJd01EWmFNRkV4Q3pBSkJnTlZCQVlUQWtOT01Rc3dDUVlEVlFRSURBSkgKUkRFTE1Ba0dBMVVFQnd3Q1Uxb3hEekFOQmdOVkJBb01Ca3R6ZEc5dVpURVhNQlVHQTFVRUF3d09TM04wYjI1bApJRkp2YjNRZ1EwRXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDNEpMTzhDaGxvClMwMWpudGNrenJhR1NYZTlVSE1FR3M3SEJPU0xvT3VQd3FsRmFoUGRiR1ZTU0t5a2pLUFJRLzQ4UHVUUHp1VmkKNi9GNytSY2VWMHdUUUdNdkxBdE90TUQrclhZRTlsNGtEN041aWxvMTJFRTdnNDhpZDFqbHFIUWY0RWh4QkhqUwp5TWFaSHltZEp0N0t6NWhFQW5IY3o4RWhMZ3RpNWxqY1ROak9Sd2h4M1MwWU9FTjdWSExKeUUwRGdpYWdhZnh3CjhBakE4MWM1MGdUYmxDeWszUEdCQm5FNHg0Y2JqNmt3SVlwNXY2RE9GUHE0RGd2Tm5jR1FVS3NHWWE5aFp0MDYKSHA1TDgyUUhZRlM2UjlEVGR0QzJtM0x4dzZ0V3hBSmIxOEV2QkVrMXducHdWdEc2WVBFOHFBMnI1ZmV5UDZlegoyakpWc095MSs5L2hBZ01CQUFHalV6QlJNQjBHQTFVZERnUVdCQlRVUy9nbWRKcnNYeVZRQ1NwTTk5QU05Rm9oCmtUQWZCZ05WSFNNRUdEQVdnQlRVUy9nbWRKcnNYeVZRQ1NwTTk5QU05Rm9oa1RBUEJnTlZIUk1CQWY4RUJUQUQKQVFIL01BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQTEybVkzMTdSSnZ0R3FrcC9zUHdvdjZzYVNVbThSRndNWQpHdTk1VUsyMkRCOHIrNC9zcWtteERKTHNDbHB0ZUZBY3Y1QkszdzhRcXpKQlR1cDVWMUdnMWZkZk04bkFlUDZWCllXa0tJZGk1RXF0bWJsTlZSNkYzWEFxODUvcnltaW5MdlV0VEhpcUdhbTZ0dk1sWHZPOHc0Z3hwNS9Kdmt5bkYKZFVGMloyaEVmSGw3T3gzWGhrOVBoNEI3MEIrTUVBU0dHd1RBaXduQThVN3RBZEgzeHc0NGlTZGt2NXBMbGtZQgoxTDZCVzNWbVg2RjJiNkRlSWoyVmVGT0FEVndLa2hPVkRFVTVSQm9zTVYrem0vMTRabnVIOVprR0dtSXBDVTFXCmZWdFZxbnVXUE1hSWJ3UlY3ZVg1WlFaaVBFRFJPZzg2cVJQdit6Z1g3WExITHp0VEpCQWYKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ==\n      service:\n        name: kstone-etcd-operator\n        namespace: {{ .Release.Namespace }}\n        path: \"/mutating-etcd\"\n    failurePolicy: Fail\n    name: {{ include \"etcd-operator.fullname\" . }}.{{ .Release.Namespace }}.svc\n    admissionReviewVersions: [\"v1\"]\n    sideEffects: NoneOnDryRun\n    rules:\n      - apiGroups: [ \"etcd.tkestack.io\" ]\n        apiVersions: [ \"v1alpha1\" ]\n        operations: [ \"CREATE\", \"UPDATE\" ]\n        resources: [ \"etcdclusters\" ]\n---\napiVersion: admissionregistration.k8s.io/v1\nkind: ValidatingWebhookConfiguration\nmetadata:\n  name: kstone-etcd-operator-validating-admission\nwebhooks:\n  - clientConfig:\n      caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURnekNDQW11Z0F3SUJBZ0lVRTFRcmYwYmZvZU9pdnFSL2w4ZldsTVI1cmdBd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1VURUxNQWtHQTFVRUJoTUNRMDR4Q3pBSkJnTlZCQWdNQWtkRU1Rc3dDUVlEVlFRSERBSlRXakVQTUEwRwpBMVVFQ2d3R1MzTjBiMjVsTVJjd0ZRWURWUVFEREE1TGMzUnZibVVnVW05dmRDQkRRVEFlRncweU1qQTBNVFV4Ck1ESXdNRFphRncwek1qQTBNVEl4TURJd01EWmFNRkV4Q3pBSkJnTlZCQVlUQWtOT01Rc3dDUVlEVlFRSURBSkgKUkRFTE1Ba0dBMVVFQnd3Q1Uxb3hEekFOQmdOVkJBb01Ca3R6ZEc5dVpURVhNQlVHQTFVRUF3d09TM04wYjI1bApJRkp2YjNRZ1EwRXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDNEpMTzhDaGxvClMwMWpudGNrenJhR1NYZTlVSE1FR3M3SEJPU0xvT3VQd3FsRmFoUGRiR1ZTU0t5a2pLUFJRLzQ4UHVUUHp1VmkKNi9GNytSY2VWMHdUUUdNdkxBdE90TUQrclhZRTlsNGtEN041aWxvMTJFRTdnNDhpZDFqbHFIUWY0RWh4QkhqUwp5TWFaSHltZEp0N0t6NWhFQW5IY3o4RWhMZ3RpNWxqY1ROak9Sd2h4M1MwWU9FTjdWSExKeUUwRGdpYWdhZnh3CjhBakE4MWM1MGdUYmxDeWszUEdCQm5FNHg0Y2JqNmt3SVlwNXY2RE9GUHE0RGd2Tm5jR1FVS3NHWWE5aFp0MDYKSHA1TDgyUUhZRlM2UjlEVGR0QzJtM0x4dzZ0V3hBSmIxOEV2QkVrMXducHdWdEc2WVBFOHFBMnI1ZmV5UDZlegoyakpWc095MSs5L2hBZ01CQUFHalV6QlJNQjBHQTFVZERnUVdCQlRVUy9nbWRKcnNYeVZRQ1NwTTk5QU05Rm9oCmtUQWZCZ05WSFNNRUdEQVdnQlRVUy9nbWRKcnNYeVZRQ1NwTTk5QU05Rm9oa1RBUEJnTlZIUk1CQWY4RUJUQUQKQVFIL01BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQTEybVkzMTdSSnZ0R3FrcC9zUHdvdjZzYVNVbThSRndNWQpHdTk1VUsyMkRCOHIrNC9zcWtteERKTHNDbHB0ZUZBY3Y1QkszdzhRcXpKQlR1cDVWMUdnMWZkZk04bkFlUDZWCllXa0tJZGk1RXF0bWJsTlZSNkYzWEFxODUvcnltaW5MdlV0VEhpcUdhbTZ0dk1sWHZPOHc0Z3hwNS9Kdmt5bkYKZFVGMloyaEVmSGw3T3gzWGhrOVBoNEI3MEIrTUVBU0dHd1RBaXduQThVN3RBZEgzeHc0NGlTZGt2NXBMbGtZQgoxTDZCVzNWbVg2RjJiNkRlSWoyVmVGT0FEVndLa2hPVkRFVTVSQm9zTVYrem0vMTRabnVIOVprR0dtSXBDVTFXCmZWdFZxbnVXUE1hSWJ3UlY3ZVg1WlFaaVBFRFJPZzg2cVJQdit6Z1g3WExITHp0VEpCQWYKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ==\n      service:\n        name: kstone-etcd-operator\n        namespace: {{ .Release.Namespace }}\n        path: \"/validating-etcd\"\n    failurePolicy: Fail\n    name: {{ include \"etcd-operator.fullname\" . }}.{{ .Release.Namespace }}.svc\n    admissionReviewVersions: [\"v1\"]\n    sideEffects: NoneOnDryRun\n    rules:\n      - apiGroups: [ \"etcd.tkestack.io\" ]\n        apiVersions: [ \"v1alpha1\" ]\n        operations: [ \"CREATE\", \"UPDATE\" ]\n        resources: [ \"etcdclusters\" ]"
  },
  {
    "path": "charts/charts/etcd-operator/values.yaml",
    "content": "# Default values for etcd-operator.\n# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\n\nreplicaCount: 1\n\nimage:\n  repository: tkestack/kstone-etcd-operator-amd64\n  pullPolicy: IfNotPresent\n  # Overrides the image tag whose default is the chart appVersion.\n  tag: \"v0.0.1-alpha.3\"\n\nimagePullSecrets: []\nnameOverride: \"\"\nfullnameOverride: \"\"\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\nprodResources:\n  limits:\n    cpu: 2\n    memory: 4G\n  requests:\n    cpu: 500m\n    memory: 512Mi\n\ntestResources:\n  limits:\n    cpu: 1\n    memory: 2G\n  requests:\n    cpu: 100m\n    memory: 50Mi\n\nnodeSelector: {}\n\ntolerations: []\n\naffinity: {}\n\nserviceAccountName: kstone\n\nservice:\n  type: ClusterIP\n  port: 443"
  },
  {
    "path": "charts/charts/grafana/.helmignore",
    "content": "# Patterns to ignore when building packages.\n# This supports shell glob matching, relative path matching, and\n# negation (prefixed with !). Only one pattern per line.\n.DS_Store\n# Common VCS dirs\n.git/\n.gitignore\n.bzr/\n.bzrignore\n.hg/\n.hgignore\n.svn/\n# Common backup files\n*.swp\n*.bak\n*.tmp\n*.orig\n*~\n# Various IDEs\n.project\n.idea/\n*.tmproj\n.vscode/\n"
  },
  {
    "path": "charts/charts/grafana/Chart.yaml",
    "content": "apiVersion: v2\nname: grafana\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.1.0\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\"\n"
  },
  {
    "path": "charts/charts/grafana/dashboards/0.json",
    "content": "{\n  \"annotations\": {\n    \"list\": [\n      {\n        \"builtIn\": 1,\n        \"datasource\": \"-- Grafana --\",\n        \"enable\": true,\n        \"hide\": true,\n        \"iconColor\": \"rgba(0, 211, 255, 1)\",\n        \"name\": \"Annotations & Alerts\",\n        \"type\": \"dashboard\"\n      }\n    ]\n  },\n  \"description\": \"Etcd Dashboard for Prometheus metrics scraper\",\n  \"editable\": true,\n  \"gnetId\": 3070,\n  \"graphTooltip\": 0,\n  \"id\": 1,\n  \"iteration\": 1652444252935,\n  \"links\": [],\n  \"panels\": [\n    {\n      \"collapsed\": false,\n      \"datasource\": null,\n      \"gridPos\": {\n        \"h\": 1,\n        \"w\": 24,\n        \"x\": 0,\n        \"y\": 0\n      },\n      \"id\": 80,\n      \"panels\": [],\n      \"title\": \"etcd\",\n      \"type\": \"row\"\n    },\n    {\n      \"cacheTimeout\": null,\n      \"datasource\": \"$datasource\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"mappings\": [\n            {\n              \"options\": {\n                \"0\": {\n                  \"text\": \"NO\"\n                },\n                \"1\": {\n                  \"text\": \"YES\"\n                }\n              },\n              \"type\": \"value\"\n            }\n          ],\n          \"thresholds\": {\n            \"mode\": \"absolute\",\n            \"steps\": [\n              {\n                \"color\": \"rgba(245, 54, 54, 0.9)\",\n                \"value\": null\n              },\n              {\n                \"color\": \"rgba(237, 129, 40, 0.89)\",\n                \"value\": 1\n              },\n              {\n                \"color\": \"rgba(50, 172, 45, 0.97)\",\n                \"value\": 0\n              }\n            ]\n          },\n          \"unit\": \"none\"\n        },\n        \"overrides\": []\n      },\n      \"gridPos\": {\n        \"h\": 7,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 1\n      },\n      \"id\": 44,\n      \"interval\": null,\n      \"links\": [],\n      \"maxDataPoints\": 100,\n      \"options\": {\n        \"colorMode\": \"value\",\n        \"graphMode\": \"area\",\n        \"justifyMode\": \"auto\",\n        \"orientation\": \"horizontal\",\n        \"reduceOptions\": {\n          \"calcs\": [\n            \"mean\"\n          ],\n          \"fields\": \"\",\n          \"values\": false\n        },\n        \"text\": {},\n        \"textMode\": \"auto\"\n      },\n      \"pluginVersion\": \"8.0.3\",\n      \"targets\": [\n        {\n          \"expr\": \"max(etcd_server_has_leader{job=\\\"$job\\\"})\",\n          \"format\": \"time_series\",\n          \"interval\": \"\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"\",\n          \"refId\": \"A\",\n          \"step\": 600\n        }\n      ],\n      \"title\": \"Etcd has a leader?\",\n      \"type\": \"stat\"\n    },\n    {\n      \"cacheTimeout\": null,\n      \"datasource\": \"$datasource\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"mappings\": [\n            {\n              \"options\": {\n                \"match\": \"null\",\n                \"result\": {\n                  \"text\": \"N/A\"\n                }\n              },\n              \"type\": \"special\"\n            }\n          ],\n          \"thresholds\": {\n            \"mode\": \"absolute\",\n            \"steps\": [\n              {\n                \"color\": \"green\",\n                \"value\": null\n              },\n              {\n                \"color\": \"red\",\n                \"value\": 80\n              }\n            ]\n          },\n          \"unit\": \"none\"\n        },\n        \"overrides\": []\n      },\n      \"gridPos\": {\n        \"h\": 7,\n        \"w\": 12,\n        \"x\": 12,\n        \"y\": 1\n      },\n      \"id\": 42,\n      \"interval\": null,\n      \"links\": [],\n      \"maxDataPoints\": 100,\n      \"options\": {\n        \"colorMode\": \"value\",\n        \"graphMode\": \"area\",\n        \"justifyMode\": \"auto\",\n        \"orientation\": \"horizontal\",\n        \"reduceOptions\": {\n          \"calcs\": [\n            \"mean\"\n          ],\n          \"fields\": \"\",\n          \"values\": false\n        },\n        \"text\": {},\n        \"textMode\": \"auto\"\n      },\n      \"pluginVersion\": \"8.0.3\",\n      \"targets\": [\n        {\n          \"expr\": \"max(etcd_server_leader_changes_seen_total{job=\\\"$job\\\"})\",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 2,\n          \"refId\": \"A\",\n          \"step\": 600\n        }\n      ],\n      \"title\": \"The number of leader changes seen\",\n      \"type\": \"stat\"\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"editable\": true,\n      \"error\": false,\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 0,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 8\n      },\n      \"hiddenSeries\": false,\n      \"id\": 23,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"show\": true,\n        \"sort\": \"current\",\n        \"sortDesc\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 2,\n      \"links\": [],\n      \"nullPointMode\": \"connected\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"sum(rate(grpc_server_handled_total{job=\\\"$job\\\"}[5m])) by (job, endpoint, grpc_method, instance) > 0\",\n          \"format\": \"time_series\",\n          \"interval\": \"\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}_{{grpc_method}} \",\n          \"metric\": \"grpc_server_started_total\",\n          \"refId\": \"A\",\n          \"step\": 60\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"RPC Rate\",\n      \"tooltip\": {\n        \"msResolution\": false,\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"ops\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"editable\": true,\n      \"error\": false,\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 0,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 12,\n        \"y\": 8\n      },\n      \"hiddenSeries\": false,\n      \"id\": 72,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"show\": true,\n        \"sort\": \"current\",\n        \"sortDesc\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 2,\n      \"links\": [],\n      \"nullPointMode\": \"connected\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"sum(increase(grpc_server_handled_total{job=\\\"$job\\\"}[2m])) by (job, endpoint, grpc_method, instance) \",\n          \"format\": \"time_series\",\n          \"interval\": \"\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}_{{grpc_method}} \",\n          \"metric\": \"grpc_server_started_total\",\n          \"refId\": \"A\",\n          \"step\": 60\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"RPC Increase\",\n      \"tooltip\": {\n        \"msResolution\": false,\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"cpm\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"decimals\": null,\n      \"editable\": true,\n      \"error\": false,\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 0,\n      \"fillGradient\": 0,\n      \"grid\": {},\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 17\n      },\n      \"hiddenSeries\": false,\n      \"id\": 1,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"show\": true,\n        \"sort\": \"current\",\n        \"sortDesc\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 2,\n      \"links\": [],\n      \"nullPointMode\": \"connected\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"etcd_debugging_mvcc_db_total_size_in_bytes{job=\\\"$job\\\"}\",\n          \"format\": \"time_series\",\n          \"hide\": false,\n          \"interval\": \"\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}\",\n          \"metric\": \"\",\n          \"refId\": \"A\",\n          \"step\": 120\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"DB Size\",\n      \"tooltip\": {\n        \"msResolution\": false,\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"cumulative\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"bytes\",\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": false\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"decimals\": null,\n      \"editable\": true,\n      \"error\": false,\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 0,\n      \"fillGradient\": 0,\n      \"grid\": {},\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 12,\n        \"y\": 17\n      },\n      \"hiddenSeries\": false,\n      \"id\": 82,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"show\": true,\n        \"sort\": \"current\",\n        \"sortDesc\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 2,\n      \"links\": [],\n      \"nullPointMode\": \"connected\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"exemplar\": true,\n          \"expr\": \"etcd_debugging_mvcc_db_total_size_in_bytes{job=\\\"$job\\\"}/etcd_server_quota_backend_bytes{job=\\\"$job\\\"}\",\n          \"format\": \"time_series\",\n          \"hide\": false,\n          \"instant\": false,\n          \"interval\": \"\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}\",\n          \"metric\": \"\",\n          \"refId\": \"A\",\n          \"step\": 120\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"DB Usage Rate\",\n      \"tooltip\": {\n        \"msResolution\": false,\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"cumulative\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"$$hashKey\": \"object:192\",\n          \"format\": \"percentunit\",\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"$$hashKey\": \"object:193\",\n          \"format\": \"short\",\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": false\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"editable\": true,\n      \"error\": false,\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 0,\n      \"fillGradient\": 0,\n      \"grid\": {},\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 26\n      },\n      \"hiddenSeries\": false,\n      \"id\": 3,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"show\": true,\n        \"sort\": null,\n        \"sortDesc\": null,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 2,\n      \"links\": [],\n      \"nullPointMode\": \"connected\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 1,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": true,\n      \"targets\": [\n        {\n          \"exemplar\": true,\n          \"expr\": \"histogram_quantile(1, sum(rate(etcd_disk_wal_fsync_duration_seconds_bucket{job=\\\"$job\\\"}[5m])) by (job,instance,endpoint,le))\",\n          \"format\": \"time_series\",\n          \"hide\": false,\n          \"interval\": \"\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}} WAL fsync\",\n          \"metric\": \"etcd_disk_wal_fsync_duration_seconds_bucket\",\n          \"refId\": \"A\",\n          \"step\": 120\n        },\n        {\n          \"expr\": \"histogram_quantile(1, sum(rate(etcd_disk_backend_commit_duration_seconds_bucket{job=\\\"$job\\\"}[5m])) by (job, instance,endpoint,le))\",\n          \"format\": \"time_series\",\n          \"interval\": \"\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}  DB fsync\",\n          \"metric\": \"etcd_disk_backend_commit_duration_seconds_bucket\",\n          \"refId\": \"B\",\n          \"step\": 120\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"Disk Sync Duration\",\n      \"tooltip\": {\n        \"msResolution\": false,\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"cumulative\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"s\",\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": false\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"editable\": true,\n      \"error\": false,\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 0,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 12,\n        \"y\": 26\n      },\n      \"hiddenSeries\": false,\n      \"id\": 41,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"show\": true,\n        \"sort\": \"current\",\n        \"sortDesc\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 2,\n      \"links\": [],\n      \"nullPointMode\": \"connected\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": true,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"etcd_debugging_mvcc_watcher_total{job=\\\"$job\\\"}\",\n          \"format\": \"time_series\",\n          \"interval\": \"\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}_mvcc_watcher_total\",\n          \"metric\": \"grpc_server_handled_total\",\n          \"refId\": \"A\",\n          \"step\": 60\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"The total number of wathcher\",\n      \"tooltip\": {\n        \"msResolution\": false,\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": \"\",\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 8,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 35\n      },\n      \"hiddenSeries\": false,\n      \"id\": 76,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"rightSide\": false,\n        \"show\": true,\n        \"sort\": \"current\",\n        \"sortDesc\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"links\": [],\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 2,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"histogram_quantile(0.99, sum(rate(etcd_debugging_disk_backend_commit_spill_duration_seconds_bucket{job=\\\"$job\\\"}[5m]) > 0) by (remark,instance,le,grpc_method,endpoint))\",\n          \"format\": \"time_series\",\n          \"interval\": \"\",\n          \"intervalFactor\": 1,\n          \"legendFormat\": \"commit_spil_{{remark}}_{{instance}}_{{endpoint}}_{{grpc_method}}\",\n          \"refId\": \"A\"\n        },\n        {\n          \"expr\": \"histogram_quantile(0.99, sum(rate(etcd_debugging_disk_backend_commit_rebalance_duration_seconds_bucket{job=\\\"$job\\\"}[5m]) > 0) by (remark,instance,le,grpc_method,endpoint))\",\n          \"interval\": \"\",\n          \"legendFormat\": \"commit_rebalance_{{remark}}_{{instance}}_{{endpoint}}_{{grpc_method}}\",\n          \"refId\": \"B\"\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"Disk Commit Latency\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"s\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 8,\n        \"w\": 12,\n        \"x\": 12,\n        \"y\": 35\n      },\n      \"hiddenSeries\": false,\n      \"id\": 67,\n      \"legend\": {\n        \"avg\": false,\n        \"current\": false,\n        \"max\": false,\n        \"min\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": false\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 2,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"etcd_debugging_mvcc_pending_events_total{job=\\\"$job\\\"}\",\n          \"interval\": \"\",\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}\",\n          \"refId\": \"A\"\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"The total number of pending events\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"editable\": true,\n      \"error\": false,\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 5,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 8,\n        \"w\": 6,\n        \"x\": 0,\n        \"y\": 43\n      },\n      \"hiddenSeries\": false,\n      \"id\": 22,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 2,\n      \"links\": [],\n      \"nullPointMode\": \"connected\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": true,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"rate(etcd_network_client_grpc_received_bytes_total{job=\\\"$job\\\"}[5m])\",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}\",\n          \"metric\": \"etcd_network_client_grpc_received_bytes_total\",\n          \"refId\": \"A\",\n          \"step\": 120\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"Client Traffic In\",\n      \"tooltip\": {\n        \"msResolution\": false,\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"Bps\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"editable\": true,\n      \"error\": false,\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 5,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 8,\n        \"w\": 6,\n        \"x\": 6,\n        \"y\": 43\n      },\n      \"hiddenSeries\": false,\n      \"id\": 21,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"show\": true,\n        \"sort\": \"current\",\n        \"sortDesc\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 2,\n      \"links\": [],\n      \"nullPointMode\": \"connected\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": true,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"rate(etcd_network_client_grpc_sent_bytes_total{job=\\\"$job\\\"}[1m])\",\n          \"format\": \"time_series\",\n          \"interval\": \"\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}\",\n          \"metric\": \"etcd_network_client_grpc_sent_bytes_total\",\n          \"refId\": \"A\",\n          \"step\": 120\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"Client Traffic Out\",\n      \"tooltip\": {\n        \"msResolution\": false,\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"Bps\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"editable\": true,\n      \"error\": false,\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 0,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 8,\n        \"w\": 12,\n        \"x\": 12,\n        \"y\": 43\n      },\n      \"hiddenSeries\": false,\n      \"id\": 29,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"show\": true,\n        \"sort\": \"current\",\n        \"sortDesc\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 2,\n      \"links\": [],\n      \"nullPointMode\": \"connected\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"process_resident_memory_bytes{job=\\\"$job\\\"}\",\n          \"format\": \"time_series\",\n          \"interval\": \"\",\n          \"intervalFactor\": 1,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}\",\n          \"refId\": \"A\"\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"Memory\",\n      \"tooltip\": {\n        \"msResolution\": false,\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"bytes\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"description\": \"etcd_debugging_mvcc_keys_total\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 8,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 51\n      },\n      \"hiddenSeries\": false,\n      \"id\": 61,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"links\": [],\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 2,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"etcd_debugging_mvcc_keys_total{job=\\\"$job\\\"}\",\n          \"format\": \"time_series\",\n          \"interval\": \"\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}\",\n          \"refId\": \"A\"\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"The total number of key\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"editable\": true,\n      \"error\": false,\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 0,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 8,\n        \"w\": 6,\n        \"x\": 12,\n        \"y\": 51\n      },\n      \"hiddenSeries\": false,\n      \"id\": 20,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 2,\n      \"links\": [],\n      \"nullPointMode\": \"connected\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"sum(rate(etcd_network_peer_received_bytes_total{job=\\\"$job\\\"}[5m])) by (job,instance)\",\n          \"format\": \"time_series\",\n          \"interval\": \"\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}\",\n          \"metric\": \"etcd_network_peer_received_bytes_total\",\n          \"refId\": \"A\",\n          \"step\": 120\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"Peer Traffic In\",\n      \"tooltip\": {\n        \"msResolution\": false,\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"Bps\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"decimals\": null,\n      \"editable\": true,\n      \"error\": false,\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 0,\n      \"fillGradient\": 0,\n      \"grid\": {},\n      \"gridPos\": {\n        \"h\": 8,\n        \"w\": 6,\n        \"x\": 18,\n        \"y\": 51\n      },\n      \"hiddenSeries\": false,\n      \"id\": 16,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 2,\n      \"links\": [],\n      \"nullPointMode\": \"connected\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"sum(rate(etcd_network_peer_sent_bytes_total{job=\\\"$job\\\"}[5m])) by (job,instance)\",\n          \"format\": \"time_series\",\n          \"hide\": false,\n          \"interval\": \"\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}\",\n          \"metric\": \"etcd_network_peer_sent_bytes_total\",\n          \"refId\": \"A\",\n          \"step\": 120\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"Peer Traffic Out\",\n      \"tooltip\": {\n        \"msResolution\": false,\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"cumulative\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"Bps\",\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"editable\": true,\n      \"error\": false,\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 0,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 8,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 59\n      },\n      \"hiddenSeries\": false,\n      \"id\": 40,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"show\": true,\n        \"sort\": \"current\",\n        \"sortDesc\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 2,\n      \"links\": [],\n      \"nullPointMode\": \"connected\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"sum(rate(etcd_server_proposals_failed_total{job=\\\"$job\\\"}[5m])) by (job,instance)\",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}} Proposal Failed Total\",\n          \"metric\": \"etcd_server_proposals_failed_total\",\n          \"refId\": \"A\",\n          \"step\": 60\n        },\n        {\n          \"expr\": \"sum(etcd_server_proposals_pending{job=\\\"$job\\\"}) by (job,instance)\",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}  Proposal Pending Total\",\n          \"metric\": \"etcd_server_proposals_pending\",\n          \"refId\": \"B\",\n          \"step\": 60\n        },\n        {\n          \"expr\": \"sum(rate(etcd_server_proposals_committed_total{job=\\\"$job\\\"}[5m])) by (job,instance)\",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}  Proposal Commit Rate\",\n          \"metric\": \"etcd_server_proposals_committed_total\",\n          \"refId\": \"C\",\n          \"step\": 60\n        },\n        {\n          \"expr\": \"sum(rate(etcd_server_proposals_applied_total{job=\\\"$job\\\"}[5m])) by (job,instance)\",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}  Proposal Apply Rate\",\n          \"refId\": \"D\",\n          \"step\": 60\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"Raft Proposals\",\n      \"tooltip\": {\n        \"msResolution\": false,\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": \"\",\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"decimals\": 0,\n      \"editable\": true,\n      \"error\": false,\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 0,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 8,\n        \"w\": 12,\n        \"x\": 12,\n        \"y\": 59\n      },\n      \"hiddenSeries\": false,\n      \"id\": 19,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"rightSide\": false,\n        \"show\": true,\n        \"sort\": \"current\",\n        \"sortDesc\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 2,\n      \"links\": [],\n      \"nullPointMode\": \"connected\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"changes(etcd_server_leader_changes_seen_total{job=\\\"$job\\\"}[6h]) \",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}\",\n          \"metric\": \"etcd_server_leader_changes_seen_total\",\n          \"refId\": \"A\",\n          \"step\": 60\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"Total Leader Elections Per Day\",\n      \"tooltip\": {\n        \"msResolution\": false,\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 67\n      },\n      \"hiddenSeries\": false,\n      \"id\": 46,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"show\": true,\n        \"sort\": \"current\",\n        \"sortDesc\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"links\": [],\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 2,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"histogram_quantile(0.99, sum(rate(grpc_server_handling_seconds_bucket{job=\\\"$job\\\", grpc_method=~\\\"Range|Txn\\\"}[5m]) > 0) by (remark,instance,le,grpc_method,endpoint))\",\n          \"format\": \"time_series\",\n          \"interval\": \"\",\n          \"intervalFactor\": 1,\n          \"legendFormat\": \"{{remark}}_{{instance}}_{{endpoint}}_{{grpc_method}}\",\n          \"refId\": \"A\"\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"etcd GRPC Latency\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"s\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"description\": \"indicates how many proposals are queued to commit. Rising pending proposals suggests there is a high client load or the member cannot commit proposals.\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 12,\n        \"y\": 67\n      },\n      \"hiddenSeries\": false,\n      \"id\": 5,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"show\": true,\n        \"sort\": \"max\",\n        \"sortDesc\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"links\": [],\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"sum(etcd_server_proposals_pending{job=\\\"$job\\\"}) by (job,instance)\",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}} Proposals pending\",\n          \"refId\": \"A\",\n          \"step\": 60\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"Proposals Pending\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"description\": \"proposals_committed_total records the total number of consensus proposals committed. This gauge should increase over time if the cluster is healthy. Several healthy members of an etcd cluster may have different total committed proposals at once. This discrepancy may be due to recovering from peers after starting, lagging behind the leader, or being the leader and therefore having the most commits. It is important to monitor this metric across all the members in the cluster; a consistently large lag between a single member and its leader indicates that member is slow or unhealthy.\\n\\nproposals_applied_total records the total number of consensus proposals applied. The etcd server applies every committed proposal asynchronously. The difference between proposals_committed_total and proposals_applied_total should usually be small (within a few thousands even under high load). If the difference between them continues to rise, it indicates that the etcd server is overloaded. This might happen when applying expensive queries like heavy range queries or large txn operations.\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 76\n      },\n      \"hiddenSeries\": false,\n      \"id\": 2,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": true,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"rightSide\": false,\n        \"show\": true,\n        \"sort\": \"current\",\n        \"sortDesc\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"links\": [],\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"sum(rate(etcd_server_proposals_committed_total{job=\\\"$job\\\"}[5m])) by (job,instance)\",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}} total number of consensus proposals committed\",\n          \"metric\": \"\",\n          \"refId\": \"A\",\n          \"step\": 60\n        },\n        {\n          \"expr\": \"sum(rate(etcd_server_proposals_applied_total{job=\\\"$job\\\"}[5m])) by (job,instance)\",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}   total number of consensus proposals applied\",\n          \"metric\": \"\",\n          \"refId\": \"B\",\n          \"step\": 60\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"The total number of consensus proposals committed\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": \"\",\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 12,\n        \"y\": 76\n      },\n      \"hiddenSeries\": false,\n      \"id\": 71,\n      \"legend\": {\n        \"avg\": false,\n        \"current\": false,\n        \"max\": false,\n        \"min\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": false\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 2,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"exemplar\": true,\n          \"expr\": \"etcd_server_slow_apply_total{job=\\\"$job\\\"}\",\n          \"interval\": \"\",\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}\",\n          \"refId\": \"A\"\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"The total number of slow apply\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 85\n      },\n      \"hiddenSeries\": false,\n      \"id\": 65,\n      \"legend\": {\n        \"avg\": false,\n        \"current\": false,\n        \"max\": false,\n        \"min\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": false\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 2,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"exemplar\": true,\n          \"expr\": \"go_goroutines{job=\\\"$job\\\"}\",\n          \"interval\": \"\",\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}\",\n          \"refId\": \"A\"\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"Goroutines\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 12,\n        \"y\": 85\n      },\n      \"hiddenSeries\": false,\n      \"id\": 69,\n      \"legend\": {\n        \"avg\": false,\n        \"current\": false,\n        \"max\": false,\n        \"min\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": false\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 2,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"etcd_debugging_mvcc_slow_watcher_total{job=\\\"$job\\\"}\",\n          \"interval\": \"\",\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}\",\n          \"refId\": \"A\"\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"The total number of slow watcher\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 94\n      },\n      \"hiddenSeries\": false,\n      \"id\": 7,\n      \"legend\": {\n        \"avg\": false,\n        \"current\": false,\n        \"max\": false,\n        \"min\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": false\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"links\": [],\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"sum(rate(etcd_disk_wal_fsync_duration_seconds_sum{job=\\\"$job\\\"}[1m]))  by (job) \",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}\\tThe latency distributions of fsync called by wal\",\n          \"refId\": \"A\",\n          \"step\": 30\n        },\n        {\n          \"expr\": \"sum(rate(etcd_disk_backend_commit_duration_seconds_sum{job=\\\"$job\\\"}[1m]))  by (job) \",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}} The latency distributions of commit called by backend\",\n          \"refId\": \"B\",\n          \"step\": 30\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"Disks Operations\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"description\": \"auth revision increase\",\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 12,\n        \"y\": 94\n      },\n      \"hiddenSeries\": false,\n      \"id\": 75,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"rightSide\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 2,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"increase(etcd_debugging_auth_revision{job=\\\"$job\\\"}[5m])\",\n          \"interval\": \"\",\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}\",\n          \"refId\": \"A\"\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"Auth Revison Increase\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"count/5m\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"description\": \"Auth Revision\",\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 103\n      },\n      \"hiddenSeries\": false,\n      \"id\": 74,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"rightSide\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 2,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"etcd_debugging_auth_revision{job=\\\"$job\\\"}\",\n          \"interval\": \"\",\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}\",\n          \"refId\": \"A\"\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"Auth Revison\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"description\": \"Abnormally high snapshot duration (snapshot_save_total_duration_seconds) indicates disk issues and might cause the cluster to be unstable.\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 12,\n        \"y\": 103\n      },\n      \"hiddenSeries\": false,\n      \"id\": 9,\n      \"legend\": {\n        \"avg\": false,\n        \"current\": false,\n        \"max\": false,\n        \"min\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": false\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"links\": [],\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"sum(rate(etcd_debugging_snap_save_total_duration_seconds_sum{job=\\\"$job\\\"}[1m])) by (job)\",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}} The total latency distributions of save called by snapshot\",\n          \"refId\": \"A\",\n          \"step\": 30\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"Snapshot Duration\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"description\": \"\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 112\n      },\n      \"hiddenSeries\": false,\n      \"id\": 86,\n      \"legend\": {\n        \"avg\": false,\n        \"current\": false,\n        \"max\": false,\n        \"min\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": false\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"links\": [],\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"exemplar\": true,\n          \"expr\": \"etcd_debugging_lease_granted_total{job=\\\"$job\\\"} - etcd_debugging_lease_revoked_total{job=\\\"$job\\\"}\",\n          \"format\": \"time_series\",\n          \"interval\": \"\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}\",\n          \"refId\": \"A\",\n          \"step\": 30\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"current lease count\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"$$hashKey\": \"object:231\",\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"$$hashKey\": \"object:232\",\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"description\": \"\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 12,\n        \"y\": 112\n      },\n      \"hiddenSeries\": false,\n      \"id\": 87,\n      \"legend\": {\n        \"avg\": false,\n        \"current\": false,\n        \"max\": false,\n        \"min\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": false\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"links\": [],\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"exemplar\": true,\n          \"expr\": \"histogram_quantile(0.99, sum(rate(etcd_debugging_mvcc_db_compaction_pause_duration_milliseconds_bucket{job=\\\"$job\\\"}[5m])) by (job,instance,endpoint,le))\",\n          \"format\": \"time_series\",\n          \"interval\": \"\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}\",\n          \"refId\": \"A\",\n          \"step\": 30\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"compaction_pause_duration P99\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"$$hashKey\": \"object:231\",\n          \"format\": \"ms\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"$$hashKey\": \"object:232\",\n          \"format\": \"ms\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"description\": \"\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 121\n      },\n      \"hiddenSeries\": false,\n      \"id\": 88,\n      \"legend\": {\n        \"avg\": false,\n        \"current\": false,\n        \"max\": false,\n        \"min\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": false\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"links\": [],\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"exemplar\": true,\n          \"expr\": \"histogram_quantile(0.99, sum(rate(etcd_debugging_mvcc_index_compaction_pause_duration_milliseconds_bucket{job=\\\"$job\\\"}[5m])) by (job,instance,endpoint,le))\",\n          \"format\": \"time_series\",\n          \"interval\": \"\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}\",\n          \"refId\": \"A\",\n          \"step\": 30\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"mvcc_index_compaction_pause_duration P99\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"$$hashKey\": \"object:231\",\n          \"format\": \"ms\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"$$hashKey\": \"object:232\",\n          \"format\": \"ms\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 12,\n        \"y\": 121\n      },\n      \"hiddenSeries\": false,\n      \"id\": 8,\n      \"legend\": {\n        \"avg\": false,\n        \"current\": false,\n        \"max\": false,\n        \"min\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": false\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"links\": [],\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"sum(rate(etcd_network_client_grpc_received_bytes_total{job=\\\"$job\\\"}[1m]))  by (job) \",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}  The total number of bytes received by grpc clients\",\n          \"refId\": \"A\",\n          \"step\": 30\n        },\n        {\n          \"expr\": \"sum(rate(etcd_network_client_grpc_sent_bytes_total{job=\\\"$job\\\"}[1m]))  by (job) \",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 2,\n          \"legendFormat\": \"{{job}}  The total number of bytes sent to grpc clients\",\n          \"refId\": \"B\",\n          \"step\": 30\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"Network\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 130\n      },\n      \"hiddenSeries\": false,\n      \"id\": 50,\n      \"legend\": {\n        \"avg\": false,\n        \"current\": false,\n        \"max\": false,\n        \"min\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": false\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"links\": [],\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 2,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"sum(rate(etcd_http_received_total{job=\\\"$job\\\"}[5m])) by (method,instance,job)\",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 1,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}_{{method}}\",\n          \"refId\": \"A\"\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"ETCD V2 HTTP QPS\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 12,\n        \"y\": 130\n      },\n      \"hiddenSeries\": false,\n      \"id\": 52,\n      \"legend\": {\n        \"avg\": false,\n        \"current\": false,\n        \"max\": false,\n        \"min\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": false\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"links\": [],\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 2,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"histogram_quantile(0.99, sum(rate(etcd_http_successful_duration_seconds_bucket{job=\\\"$job\\\"}[5m]) ) by (job,instance,method,le))\",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 1,\n          \"legendFormat\": \"{{job}}_{{instance}}_{{endpoint}}_{{method}}\",\n          \"refId\": \"A\"\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"ETCD V2 HTTP Latency\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"s\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"collapsed\": false,\n      \"datasource\": null,\n      \"gridPos\": {\n        \"h\": 1,\n        \"w\": 24,\n        \"x\": 0,\n        \"y\": 139\n      },\n      \"id\": 78,\n      \"panels\": [],\n      \"title\": \"Kstone Inspection\",\n      \"type\": \"row\"\n    },\n    {\n      \"cacheTimeout\": null,\n      \"datasource\": \"$datasource\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"color\": {\n            \"mode\": \"palette-classic\"\n          },\n          \"custom\": {\n            \"hideFrom\": {\n              \"legend\": false,\n              \"tooltip\": false,\n              \"viz\": false\n            }\n          },\n          \"mappings\": [],\n          \"noValue\": \"0\"\n        },\n        \"overrides\": [\n          {\n            \"__systemRef\": \"hideSeriesFrom\",\n            \"matcher\": {\n              \"id\": \"byNames\",\n              \"options\": {\n                \"mode\": \"exclude\",\n                \"names\": [\n                  \"Healthy\",\n                  \"Unhealthy_demo-etcd.kstone.svc.cluster.local\",\n                  \"Unhealthy\"\n                ],\n                \"prefix\": \"All except:\",\n                \"readOnly\": true\n              }\n            },\n            \"properties\": [\n              {\n                \"id\": \"custom.hideFrom\",\n                \"value\": {\n                  \"legend\": false,\n                  \"tooltip\": false,\n                  \"viz\": true\n                }\n              }\n            ]\n          },\n          {\n            \"matcher\": {\n              \"id\": \"byName\",\n              \"options\": \"Healthy\"\n            },\n            \"properties\": [\n              {\n                \"id\": \"mappings\",\n                \"value\": [\n                  {\n                    \"options\": {\n                      \"from\": 0,\n                      \"result\": {\n                        \"color\": \"green\",\n                        \"index\": 0\n                      },\n                      \"to\": 100\n                    },\n                    \"type\": \"range\"\n                  }\n                ]\n              }\n            ]\n          },\n          {\n            \"matcher\": {\n              \"id\": \"byRegexp\",\n              \"options\": \"Unhealthy.*\"\n            },\n            \"properties\": [\n              {\n                \"id\": \"mappings\",\n                \"value\": [\n                  {\n                    \"options\": {\n                      \"from\": 0,\n                      \"result\": {\n                        \"color\": \"red\",\n                        \"index\": 0\n                      },\n                      \"to\": 100\n                    },\n                    \"type\": \"range\"\n                  }\n                ]\n              }\n            ]\n          }\n        ]\n      },\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 140\n      },\n      \"id\": 63,\n      \"interval\": null,\n      \"links\": [],\n      \"maxDataPoints\": 1,\n      \"options\": {\n        \"displayLabels\": [],\n        \"legend\": {\n          \"displayMode\": \"table\",\n          \"placement\": \"right\",\n          \"values\": [\n            \"value\"\n          ]\n        },\n        \"pieType\": \"pie\",\n        \"reduceOptions\": {\n          \"calcs\": [\n            \"lastNotNull\"\n          ],\n          \"fields\": \"\",\n          \"values\": false\n        },\n        \"tooltip\": {\n          \"mode\": \"single\"\n        }\n      },\n      \"pluginVersion\": \"7.0.3\",\n      \"targets\": [\n        {\n          \"expr\": \"sum(kstone_inspection_etcd_endpoint_healthy{clusterName=\\\"$job\\\"})\",\n          \"interval\": \"\",\n          \"legendFormat\": \"Healthy\",\n          \"refId\": \"A\"\n        },\n        {\n          \"exemplar\": true,\n          \"expr\": \"count(kstone_inspection_etcd_endpoint_healthy{clusterName=\\\"$job\\\"} == 0)\",\n          \"interval\": \"\",\n          \"legendFormat\": \"Unhealthy\",\n          \"refId\": \"B\"\n        }\n      ],\n      \"timeFrom\": null,\n      \"timeShift\": null,\n      \"title\": \"The number of healthy/unhealthy endpoint\",\n      \"type\": \"piechart\"\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"description\": \"\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 12,\n        \"y\": 140\n      },\n      \"hiddenSeries\": false,\n      \"id\": 56,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"show\": true,\n        \"sort\": \"current\",\n        \"sortDesc\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"links\": [],\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 2,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"topk(15, sum by (clusterName,etcdPrefix,resourceName) (kstone_inspection_etcd_key_total{clusterName=\\\"$job\\\"}))\",\n          \"format\": \"time_series\",\n          \"interval\": \"\",\n          \"intervalFactor\": 1,\n          \"legendFormat\": \"{{etcdPrefix}}_{{resourceName}}\",\n          \"refId\": \"A\"\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"The total number of resource key\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 149\n      },\n      \"hiddenSeries\": false,\n      \"id\": 58,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"show\": true,\n        \"sort\": \"current\",\n        \"sortDesc\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"links\": [],\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 2,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"exemplar\": true,\n          \"expr\": \"kstone_inspection_etcd_endpoint_alarm{clusterName=\\\"$job\\\"}\",\n          \"format\": \"time_series\",\n          \"interval\": \"\",\n          \"intervalFactor\": 1,\n          \"legendFormat\": \"{{clusterName}}-{{alarmType}}-{{exported_endpoint}}\",\n          \"refId\": \"A\"\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"Alarm\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 12,\n        \"y\": 149\n      },\n      \"hiddenSeries\": false,\n      \"id\": 54,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"rightSide\": false,\n        \"show\": true,\n        \"sort\": \"current\",\n        \"sortDesc\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"links\": [],\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 2,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"topk(15, sum(rate(kstone_inspection_etcd_request_total{clusterName=\\\"$job\\\"}[5m])) by (clusterName,etcdPrefix,grpcMethod,resourceName))\",\n          \"format\": \"time_series\",\n          \"interval\": \"\",\n          \"intervalFactor\": 1,\n          \"legendFormat\": \"{{etcdPrefix}}_{{grpcMethod}}_{{resourceName}}\",\n          \"refId\": \"A\"\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"Hot Write QPS\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"$datasource\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"links\": []\n        },\n        \"overrides\": []\n      },\n      \"fill\": 1,\n      \"fillGradient\": 0,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 158\n      },\n      \"hiddenSeries\": false,\n      \"id\": 81,\n      \"legend\": {\n        \"alignAsTable\": true,\n        \"avg\": false,\n        \"current\": true,\n        \"max\": true,\n        \"min\": false,\n        \"show\": true,\n        \"sort\": \"current\",\n        \"sortDesc\": true,\n        \"total\": false,\n        \"values\": true\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"links\": [],\n      \"nullPointMode\": \"null\",\n      \"options\": {\n        \"alertThreshold\": true\n      },\n      \"paceLength\": 10,\n      \"percentage\": false,\n      \"pluginVersion\": \"8.0.3\",\n      \"pointradius\": 2,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"exemplar\": true,\n          \"expr\": \"kstone_inspection_etcd_node_diff_total{clusterName=\\\"$job\\\"}\",\n          \"format\": \"time_series\",\n          \"interval\": \"\",\n          \"intervalFactor\": 1,\n          \"legendFormat\": \"key_{{clusterName}}\",\n          \"refId\": \"A\"\n        },\n        {\n          \"exemplar\": true,\n          \"expr\": \"kstone_inspection_etcd_node_revision_diff_total{clusterName=\\\"$job\\\"}\",\n          \"hide\": false,\n          \"interval\": \"\",\n          \"legendFormat\": \"revision_{{clusterName}}\",\n          \"refId\": \"B\"\n        },\n        {\n          \"exemplar\": true,\n          \"expr\": \"kstone_inspection_etcd_node_index_diff_total{clusterName=\\\"$job\\\"}\",\n          \"hide\": false,\n          \"interval\": \"\",\n          \"legendFormat\": \"index_{{clusterName}}\",\n          \"refId\": \"C\"\n        },\n        {\n          \"exemplar\": true,\n          \"expr\": \"kstone_inspection_etcd_node_raft_applied_index_diff_total{clusterName=\\\"$job\\\"}\",\n          \"hide\": false,\n          \"interval\": \"\",\n          \"legendFormat\": \"raft_applied_{{clusterName}}\",\n          \"refId\": \"D\"\n        },\n        {\n          \"exemplar\": true,\n          \"expr\": \"kstone_inspection_etcd_node_raft_index_diff_total{clusterName=\\\"$job\\\"}\",\n          \"hide\": false,\n          \"interval\": \"\",\n          \"legendFormat\": \"raft_index_{{clusterName}}\",\n          \"refId\": \"E\"\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeRegions\": [],\n      \"timeShift\": null,\n      \"title\": \"The consistency difference between each node\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 2,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"datasource\": null,\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"color\": {\n            \"mode\": \"palette-classic\"\n          },\n          \"custom\": {\n            \"axisLabel\": \"\",\n            \"axisPlacement\": \"auto\",\n            \"barAlignment\": 0,\n            \"drawStyle\": \"line\",\n            \"fillOpacity\": 0,\n            \"gradientMode\": \"none\",\n            \"hideFrom\": {\n              \"legend\": false,\n              \"tooltip\": false,\n              \"viz\": false\n            },\n            \"lineInterpolation\": \"linear\",\n            \"lineWidth\": 1,\n            \"pointSize\": 5,\n            \"scaleDistribution\": {\n              \"type\": \"linear\"\n            },\n            \"showPoints\": \"auto\",\n            \"spanNulls\": false,\n            \"stacking\": {\n              \"group\": \"A\",\n              \"mode\": \"none\"\n            },\n            \"thresholdsStyle\": {\n              \"mode\": \"off\"\n            }\n          },\n          \"mappings\": [],\n          \"thresholds\": {\n            \"mode\": \"absolute\",\n            \"steps\": [\n              {\n                \"color\": \"green\",\n                \"value\": null\n              },\n              {\n                \"color\": \"red\",\n                \"value\": 80\n              }\n            ]\n          }\n        },\n        \"overrides\": []\n      },\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 12,\n        \"y\": 158\n      },\n      \"id\": 85,\n      \"options\": {\n        \"legend\": {\n          \"calcs\": [],\n          \"displayMode\": \"list\",\n          \"placement\": \"bottom\"\n        },\n        \"tooltip\": {\n          \"mode\": \"single\"\n        }\n      },\n      \"targets\": [\n        {\n          \"exemplar\": true,\n          \"expr\": \"kstone_inspection_etcd_backup_files\",\n          \"interval\": \"\",\n          \"legendFormat\": \"{{clusterName}}\",\n          \"refId\": \"A\"\n        },\n        {\n          \"exemplar\": true,\n          \"expr\": \"kstone_inspection_etcd_failed_backup_files\",\n          \"hide\": false,\n          \"interval\": \"\",\n          \"legendFormat\": \"{{clusterName}}_failed\",\n          \"refId\": \"B\"\n        }\n      ],\n      \"title\": \"The number of backup file in the last day\",\n      \"type\": \"timeseries\"\n    },\n    {\n      \"datasource\": null,\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"color\": {\n            \"mode\": \"palette-classic\"\n          },\n          \"custom\": {\n            \"axisLabel\": \"\",\n            \"axisPlacement\": \"auto\",\n            \"barAlignment\": 0,\n            \"drawStyle\": \"line\",\n            \"fillOpacity\": 0,\n            \"gradientMode\": \"none\",\n            \"hideFrom\": {\n              \"legend\": false,\n              \"tooltip\": false,\n              \"viz\": false\n            },\n            \"lineInterpolation\": \"linear\",\n            \"lineWidth\": 1,\n            \"pointSize\": 5,\n            \"scaleDistribution\": {\n              \"type\": \"linear\"\n            },\n            \"showPoints\": \"auto\",\n            \"spanNulls\": false,\n            \"stacking\": {\n              \"group\": \"A\",\n              \"mode\": \"none\"\n            },\n            \"thresholdsStyle\": {\n              \"mode\": \"off\"\n            }\n          },\n          \"mappings\": [],\n          \"thresholds\": {\n            \"mode\": \"absolute\",\n            \"steps\": [\n              {\n                \"color\": \"green\",\n                \"value\": null\n              },\n              {\n                \"color\": \"red\",\n                \"value\": 80\n              }\n            ]\n          }\n        },\n        \"overrides\": []\n      },\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 167\n      },\n      \"id\": 84,\n      \"options\": {\n        \"legend\": {\n          \"calcs\": [],\n          \"displayMode\": \"list\",\n          \"placement\": \"bottom\"\n        },\n        \"tooltip\": {\n          \"mode\": \"single\"\n        }\n      },\n      \"targets\": [\n        {\n          \"exemplar\": true,\n          \"expr\": \"kstone_inspection_failed_num\",\n          \"interval\": \"\",\n          \"legendFormat\": \"{{clusterName}}_{{inspectionType}}\",\n          \"refId\": \"A\"\n        }\n      ],\n      \"title\": \"The total number of failed inspection\",\n      \"type\": \"timeseries\"\n    }\n  ],\n  \"refresh\": \"\",\n  \"schemaVersion\": 30,\n  \"style\": \"dark\",\n  \"tags\": [],\n  \"templating\": {\n    \"list\": [\n      {\n        \"current\": {\n          \"selected\": false,\n          \"text\": \"\",\n          \"value\": \"\"\n        },\n        \"description\": null,\n        \"error\": null,\n        \"hide\": 2,\n        \"includeAll\": false,\n        \"label\": \"数据源\",\n        \"multi\": false,\n        \"name\": \"datasource\",\n        \"options\": [],\n        \"query\": \"prometheus\",\n        \"queryValue\": \"\",\n        \"refresh\": 1,\n        \"regex\": \"KSTONE-PROM\",\n        \"skipUrlSync\": false,\n        \"type\": \"datasource\"\n      },\n      {\n        \"allValue\": null,\n        \"current\": {\n          \"selected\": false,\n          \"text\": \"demo\",\n          \"value\": \"demo\"\n        },\n        \"datasource\": \"$datasource\",\n        \"definition\": \"query_result(sum by (job) (increase(etcd_server_has_leader{}[$__range])))\",\n        \"description\": null,\n        \"error\": {\n          \"message\": \"Datasource named  was not found\"\n        },\n        \"hide\": 0,\n        \"includeAll\": false,\n        \"label\": \"etcd\",\n        \"multi\": false,\n        \"name\": \"job\",\n        \"options\": [],\n        \"query\": {\n          \"query\": \"query_result(sum by (job) (increase(etcd_server_has_leader{}[$__range])))\",\n          \"refId\": \"KSTONE-PROM-job-Variable-Query\"\n        },\n        \"refresh\": 1,\n        \"regex\": \"/.*job=\\\"(.*)\\\".*/\",\n        \"skipUrlSync\": false,\n        \"sort\": 1,\n        \"tagValuesQuery\": \"\",\n        \"tagsQuery\": \"\",\n        \"type\": \"query\",\n        \"useTags\": false\n      }\n    ]\n  },\n  \"time\": {\n    \"from\": \"now-15m\",\n    \"to\": \"now\"\n  },\n  \"timepicker\": {\n    \"refresh_intervals\": [\n      \"10s\",\n      \"30s\",\n      \"1m\",\n      \"5m\",\n      \"15m\",\n      \"30m\",\n      \"1h\",\n      \"2h\",\n      \"1d\"\n    ],\n    \"time_options\": [\n      \"5m\",\n      \"15m\",\n      \"1h\",\n      \"6h\",\n      \"12h\",\n      \"24h\",\n      \"2d\",\n      \"7d\",\n      \"30d\"\n    ]\n  },\n  \"timezone\": \"browser\",\n  \"title\": \"Kstone\",\n  \"uid\": \"Hw7tu7aZz123123\",\n  \"version\": 12\n}"
  },
  {
    "path": "charts/charts/grafana/templates/_helpers.tpl",
    "content": "{{/*\nExpand the name of the chart.\n*/}}\n{{- define \"grafana.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 \"grafana.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 \"grafana.chart\" -}}\n{{- printf \"%s-%s\" .Chart.Name .Chart.Version | replace \"+\" \"_\" | trunc 63 | trimSuffix \"-\" }}\n{{- end }}\n\n{{/*\nCommon labels\n*/}}\n{{- define \"grafana.labels\" -}}\nhelm.sh/chart: {{ include \"grafana.chart\" . }}\n{{ include \"grafana.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 \"grafana.selectorLabels\" -}}\napp.kubernetes.io/name: {{ include \"grafana.name\" . }}\napp.kubernetes.io/instance: {{ .Release.Name }}\n{{- end }}"
  },
  {
    "path": "charts/charts/grafana/templates/configmap.yaml",
    "content": "apiVersion: v1\ndata:\n  grafana.ini: |\n    [analytics]\n    check_for_updates = true\n    [grafana_net]\n    url = https://grafana.net\n    [log]\n    mode = console\n    [paths]\n    data = /var/lib/grafana/\n    logs = /var/log/grafana\n    plugins = /var/lib/grafana/plugins\n    provisioning = /etc/grafana/provisioning\n    [auth.anonymous]\n    enabled=true\n    [security]\n    allow_embedding = true\n    [server]\n    root_url = http://localhost/grafana/\n    serve_from_sub_path = true\nkind: ConfigMap\nmetadata:\n  name: grafana\n---\napiVersion: v1\ndata:\n  prometheus.yaml: |-\n    apiVersion: 1\n    datasources:\n     - name: KSTONE-PROM\n       type: prometheus\n       access: proxy\n       orgId: 1\n       url: http://{{ .Release.Name }}-prometheus-prometheus.{{ .Release.Namespace }}.svc.cluster.local:9090\n       isDefault: true\n       editable: false\nkind: ConfigMap\nmetadata:\n  labels:\n    grafana/datasource: default\n  name: grafana-default-datasource\n---\napiVersion: v1\ndata:\n{{ (.Files.Glob \"dashboards/*\").AsConfig | indent 2 }}\nkind: ConfigMap\nmetadata:\n  labels:\n    grafana/dashboards: default\n  name: grafana-etcd-dashboards\n---\napiVersion: v1\ndata:\n  dashboard.yaml: |-\n    apiVersion: 1\n    providers:\n      - name: 'dasboard'\n        type: file\n        disableDeletion: true\n        editable: true\n        updateIntervalSeconds: 10\n        allowUiUpdates: true\n        options:\n          path: /etc/grafana/dashboards\n          foldersFromFilesStructure: false\nkind: ConfigMap\nmetadata:\n  name: grafana-dashboard-import"
  },
  {
    "path": "charts/charts/grafana/templates/deployment.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: {{ include \"grafana.fullname\" . }}\n  labels:\n  {{- include \"grafana.labels\" . | nindent 4 }}\nspec:\n  replicas: {{ .Values.replicaCount }}\n  selector:\n    matchLabels:\n  {{- include \"grafana.selectorLabels\" . | nindent 6 }}\n  template:\n    metadata:\n      {{- with .Values.podAnnotations }}\n      annotations:\n      {{- toYaml . | nindent 8 }}\n      {{- end }}\n      labels:\n    {{- include \"grafana.selectorLabels\" . | nindent 8 }}\n    spec:\n      {{- with .Values.imagePullSecrets }}\n      imagePullSecrets:\n      {{- toYaml . | nindent 8 }}\n      {{- end }}\n      serviceAccountName: {{ .Values.serviceAccountName }}\n      securityContext:\n      {{- toYaml .Values.podSecurityContext | nindent 8 }}\n      volumes:\n        - emptyDir: {}\n          name: datasources\n        - configMap:\n            defaultMode: 420\n            name: grafana-dashboard-import\n          name: dashboard-import\n        - emptyDir: {}\n          name: dashboards\n        - configMap:\n            defaultMode: 420\n            name: grafana\n          name: config\n        - emptyDir: {}\n          name: storage\n      containers:\n        - args:\n            - --namespace={{ .Release.Namespace }}\n            - --flatten\n            - --configmap-label=grafana/dashboards=default:/etc/grafana/dashboards\n            - --configmap-label=grafana/datasource=default:/etc/grafana/provisioning/datasources\n          image: tkestack/configmap-update:v1.0.2\n          imagePullPolicy: IfNotPresent\n          name: dashboards-update\n          resources: {}\n          securityContext:\n            runAsUser: 1000\n          terminationMessagePath: /dev/termination-log\n          terminationMessagePolicy: FallbackToLogsOnError\n          volumeMounts:\n            - mountPath: /etc/grafana/dashboards\n              name: dashboards\n            - mountPath: /etc/grafana/provisioning/datasources\n              name: datasources\n        - env:\n            - name: GF_SECURITY_ADMIN_USER\n              valueFrom:\n                secretKeyRef:\n                  key: admin-user\n                  name: grafana\n            - name: GF_SECURITY_ADMIN_PASSWORD\n              valueFrom:\n                secretKeyRef:\n                  key: admin-password\n                  name: grafana\n            - name: GF_PATHS_DATA\n              value: /var/lib/grafana/\n            - name: GF_PATHS_LOGS\n              value: /var/log/grafana\n            - name: GF_PATHS_PLUGINS\n              value: /var/lib/grafana/plugins\n            - name: GF_PATHS_PROVISIONING\n              value: /etc/grafana/provisioning\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          livenessProbe:\n            failureThreshold: 10\n            httpGet:\n              path: /api/health\n              port: 3000\n              scheme: HTTP\n            initialDelaySeconds: 60\n            periodSeconds: 10\n            successThreshold: 1\n            timeoutSeconds: 30\n          ports:\n            - containerPort: 80\n              name: service\n              protocol: TCP\n            - containerPort: 3000\n              name: grafana\n              protocol: TCP\n          readinessProbe:\n            failureThreshold: 3\n            httpGet:\n              path: /api/health\n              port: 3000\n              scheme: HTTP\n            periodSeconds: 10\n            successThreshold: 1\n            timeoutSeconds: 1\n          resources:\n            {{- if eq .Values.global.env \"production\" }}\n            {{- toYaml .Values.prodResources | nindent 12 }}\n            {{- else }}\n            {{- toYaml .Values.testResources | nindent 12 }}\n            {{- end }}\n          volumeMounts:\n            - mountPath: /etc/grafana/provisioning/datasources\n              name: datasources\n            - mountPath: /etc/grafana/provisioning/dashboards\n              name: dashboard-import\n            - mountPath: /etc/grafana/dashboards\n              name: dashboards\n            - mountPath: /etc/grafana/grafana.ini\n              name: config\n              subPath: grafana.ini\n            - mountPath: /var/lib/grafana\n              name: storage\n      dnsPolicy: ClusterFirst\n      enableServiceLinks: true\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"
  },
  {
    "path": "charts/charts/grafana/templates/secret.yaml",
    "content": "apiVersion: v1\ndata:\n  admin-password: NEtZamozMWpNWmsxeFRpR1BWRUhsTzRrZzVKV1QySzBUeXlpSlRGQw==\n  admin-user: YWRtaW4=\n  ldap-toml: \"\"\nkind: Secret\nmetadata:\n  name: grafana\ntype: Opaque"
  },
  {
    "path": "charts/charts/grafana/templates/service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  name: {{ include \"grafana.fullname\" . }}\n  labels:\n    {{- include \"grafana.labels\" . | nindent 4 }}\nspec:\n  type: {{ .Values.service.type }}\n  ports:\n    - name: service\n      port: {{ .Values.service.port }}\n      protocol: TCP\n      targetPort: 3000\n  selector:\n    {{- include \"grafana.selectorLabels\" . | nindent 4 }}\n"
  },
  {
    "path": "charts/charts/grafana/values.yaml",
    "content": "# Default values for grafana.\n# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\n\nreplicaCount: 1\n\nimage:\n  repository: grafana/grafana\n  pullPolicy: IfNotPresent\n  # Overrides the image tag whose default is the chart appVersion.\n  tag: \"8.0.3\"\n\nimagePullSecrets: []\nnameOverride: \"\"\nfullnameOverride: \"\"\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#  fsGroup: 472\n  runAsGroup: 472\n  runAsUser: 472\n\nservice:\n  type: NodePort\n  port: 80\n\nprodResources:\n  limits:\n    cpu: 2\n    memory: 4G\n  requests:\n    cpu: 500m\n    memory: 512Mi\n\ntestResources:\n  limits:\n    cpu: 1\n    memory: 2G\n  requests:\n    cpu: 100m\n    memory: 50Mi\n\nnodeSelector: {}\n\ntolerations: []\n\naffinity: {}\n\nserviceAccountName: kstone\n"
  },
  {
    "path": "charts/charts/inspection-controller/.helmignore",
    "content": "# Patterns to ignore when building packages.\n# This supports shell glob matching, relative path matching, and\n# negation (prefixed with !). Only one pattern per line.\n.DS_Store\n# Common VCS dirs\n.git/\n.gitignore\n.bzr/\n.bzrignore\n.hg/\n.hgignore\n.svn/\n# Common backup files\n*.swp\n*.bak\n*.tmp\n*.orig\n*~\n# Various IDEs\n.project\n.idea/\n*.tmproj\n.vscode/\n"
  },
  {
    "path": "charts/charts/inspection-controller/Chart.yaml",
    "content": "apiVersion: v2\nname: inspection-controller\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.1.0\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\"\n"
  },
  {
    "path": "charts/charts/inspection-controller/templates/_helpers.tpl",
    "content": "{{/*\nExpand the name of the chart.\n*/}}\n{{- define \"inspection-controller.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 \"inspection-controller.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 \"inspection-controller.chart\" -}}\n{{- printf \"%s-%s\" .Chart.Name .Chart.Version | replace \"+\" \"_\" | trunc 63 | trimSuffix \"-\" }}\n{{- end }}\n\n{{/*\nCommon labels\n*/}}\n{{- define \"inspection-controller.labels\" -}}\nhelm.sh/chart: {{ include \"inspection-controller.chart\" . }}\n{{ include \"inspection-controller.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 \"inspection-controller.selectorLabels\" -}}\napp.kubernetes.io/name: {{ include \"inspection-controller.name\" . }}\napp.kubernetes.io/instance: {{ .Release.Name }}\n{{- end }}"
  },
  {
    "path": "charts/charts/inspection-controller/templates/deployment.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: {{ include \"inspection-controller.fullname\" . }}\n  labels:\n    {{- include \"inspection-controller.labels\" . | nindent 4 }}\nspec:\n  replicas: {{ .Values.replicaCount }}\n  selector:\n    matchLabels:\n      {{- include \"inspection-controller.selectorLabels\" . | nindent 6 }}\n  template:\n    metadata:\n      {{- with .Values.podAnnotations }}\n      annotations:\n        {{- toYaml . | nindent 8 }}\n      {{- end }}\n      labels:\n        {{- include \"inspection-controller.selectorLabels\" . | nindent 8 }}\n    spec:\n      {{- with .Values.imagePullSecrets }}\n      imagePullSecrets:\n        {{- toYaml . | nindent 8 }}\n      {{- end }}\n      serviceAccountName: {{ .Values.serviceAccountName }}\n      securityContext:\n        {{- toYaml .Values.podSecurityContext | nindent 8 }}\n      containers:\n        - args:\n            - inspection\n          command:\n            - /app/bin/kstone-controller\n          name: {{ .Chart.Name }}\n          securityContext:\n            {{- toYaml .Values.securityContext | nindent 12 }}\n          {{- if .Values.global.kstone.tag }}\n          image: \"{{ .Values.image.repository }}:{{ .Values.global.kstone.tag }}\"\n          {{- else }}\n          image: \"{{ .Values.image.repository }}:{{ .Values.image.tag }}\"\n          {{- end }}\n          imagePullPolicy: {{ .Values.image.pullPolicy }}\n          ports:\n            - name: http\n              containerPort: 9090\n              protocol: TCP\n          resources:\n            {{- if eq .Values.global.env \"production\" }}\n            {{- toYaml .Values.prodResources | nindent 12 }}\n            {{- else }}\n            {{- toYaml .Values.testResources | nindent 12 }}\n            {{- end }}\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"
  },
  {
    "path": "charts/charts/inspection-controller/templates/service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  name: {{ include \"inspection-controller.fullname\" . }}\n  labels:\n    app: inspection-controller\n    {{- include \"inspection-controller.labels\" . | nindent 4 }}\nspec:\n  type: {{ .Values.service.type }}\n  ports:\n    - port: {{ .Values.service.port }}\n      targetPort: http\n      protocol: TCP\n      name: http\n  selector:\n    {{- include \"inspection-controller.selectorLabels\" . | nindent 4 }}\n"
  },
  {
    "path": "charts/charts/inspection-controller/templates/servicemonitor.yaml",
    "content": "apiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  name: {{ include \"inspection-controller.fullname\" . }}\n  labels:\n    {{- include \"inspection-controller.labels\" . | nindent 4 }}\nspec:\n  endpoints:\n    - port: http\n  namespaceSelector:\n    matchNames:\n      - {{ .Release.Namespace }}\n  selector:\n    matchLabels:\n      app: inspection-controller"
  },
  {
    "path": "charts/charts/inspection-controller/values.yaml",
    "content": "# Default values for inspection-controller.\n# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\n\nreplicaCount: 1\n\nimage:\n  repository: tkestack/kstone-controller-amd64\n  pullPolicy: IfNotPresent\n\nimagePullSecrets: []\nnameOverride: \"\"\nfullnameOverride: \"\"\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\nservice:\n  type: NodePort\n  port: 80\n\nprodResources:\n  limits:\n    cpu: 2\n    memory: 4G\n  requests:\n    cpu: 500m\n    memory: 512Mi\n\ntestResources:\n  limits:\n    cpu: 1\n    memory: 2G\n  requests:\n    cpu: 100m\n    memory: 50Mi\n\nnodeSelector: {}\n\ntolerations: []\n\naffinity: {}\n\nserviceAccountName: kstone\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/.helmignore",
    "content": "# Patterns to ignore when building packages.\n# This supports shell glob matching, relative path matching, and\n# negation (prefixed with !). Only one pattern per line.\n.DS_Store\n# Common VCS dirs\n.git/\n.gitignore\n.bzr/\n.bzrignore\n.hg/\n.hgignore\n.svn/\n# Common backup files\n*.swp\n*.bak\n*.tmp\n*~\n# Various IDEs\n.project\n.idea/\n*.tmproj\n# helm/charts\nOWNERS\nhack/\nci/\nkube-prometheus-*.tgz\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/CONTRIBUTING.md",
    "content": "# Contributing Guidelines\n\n## How to contribute to this chart\n\n1. Fork this repository, develop and test your Chart.\n1. Bump the chart version for every change.\n1. Ensure PR title has the prefix `[kube-prometheus-stack]`\n1. When making changes to rules or dashboards, see the README.md section on how to sync data from upstream repositories\n1. Check the `hack/minikube` folder has scripts to set up minikube and components of this chart that will allow all components to be scraped. You can use this configuration when validating your changes.\n1. Check for changes of RBAC rules.\n1. Check for changes in CRD specs.\n1. PR must pass the linter (`helm lint`)\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/Chart.yaml",
    "content": "apiVersion: v2\ndescription: kube-prometheus-stack collects Kubernetes manifests, Grafana dashboards, and Prometheus rules combined with documentation and scripts to provide easy to operate end-to-end Kubernetes cluster monitoring with Prometheus using the Prometheus Operator.\nicon: https://raw.githubusercontent.com/prometheus/prometheus.github.io/master/assets/prometheus_logo-cb55bb5c346.png\nengine: gotpl\ntype: application\nmaintainers:\n  - name: vsliouniaev\n  - name: bismarck\n  - name: gianrubio\n    email: gianrubio@gmail.com\n  - name: gkarthiks\n    email: github.gkarthiks@gmail.com\n  - name: scottrigby\n    email: scott@r6by.com\n  - name: Xtigyro\n    email: miroslav.hadzhiev@gmail.com\nname: prometheus\nsources:\n  - https://github.com/prometheus-community/helm-charts\n  - https://github.com/prometheus-operator/kube-prometheus\nversion: 17.0.3\nappVersion: 0.49.0\nkubeVersion: \">=1.16.0-0\"\nhome: https://github.com/prometheus-operator/kube-prometheus\nkeywords:\n- operator\n- prometheus\n- kube-prometheus\nannotations:\n  \"artifacthub.io/operator\": \"true\"\n  \"artifacthub.io/links\": |\n    - name: Chart Source\n      url: https://github.com/prometheus-community/helm-charts\n    - name: Upstream Project\n      url: https://github.com/prometheus-operator/kube-prometheus\n\ndependencies:\n- name: kube-state-metrics\n  version: \"3.4.*\"\n  repository: https://prometheus-community.github.io/helm-charts\n  condition: kubeStateMetrics.enabled\n- name: prometheus-node-exporter\n  version: \"2.0.*\"\n  repository: https://prometheus-community.github.io/helm-charts\n  condition: nodeExporter.enabled\n- name: grafana\n  version: \"6.14.*\"\n  repository: https://grafana.github.io/helm-charts\n  condition: grafana.enabled\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/README.md",
    "content": "# kube-prometheus-stack\n\nInstalls the [kube-prometheus stack](https://github.com/prometheus-operator/kube-prometheus), a collection of Kubernetes manifests, [Grafana](http://grafana.com/) dashboards, and [Prometheus rules](https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/) combined with documentation and scripts to provide easy to operate end-to-end Kubernetes cluster monitoring with [Prometheus](https://prometheus.io/) using the [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator).\n\nSee the [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus) README for details about components, dashboards, and alerts.\n\n_Note: This chart was formerly named `prometheus-operator` chart, now renamed to more clearly reflect that it installs the `kube-prometheus` project stack, within which Prometheus Operator is only one component._\n\n## Prerequisites\n\n- Kubernetes 1.16+\n- Helm 3+\n\n## Get Repo Info\n\n```console\nhelm repo add prometheus-community https://prometheus-community.github.io/helm-charts\nhelm repo update\n```\n\n_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._\n\n## Install Chart\n\n```console\n# Helm\n$ helm install [RELEASE_NAME] prometheus-community/kube-prometheus-stack\n```\n\n_See [configuration](#configuration) below._\n\n_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._\n\n## Dependencies\n\nBy default this chart installs additional, dependent charts:\n\n- [prometheus-community/kube-state-metrics](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-state-metrics)\n- [prometheus-community/prometheus-node-exporter](https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus-node-exporter)\n- [grafana/grafana](https://github.com/grafana/helm-charts/tree/main/charts/grafana)\n\nTo disable dependencies during installation, see [multiple releases](#multiple-releases) below.\n\n_See [helm dependency](https://helm.sh/docs/helm/helm_dependency/) for command documentation._\n\n## Uninstall Chart\n\n```console\n# Helm\n$ helm uninstall [RELEASE_NAME]\n```\n\nThis removes all the Kubernetes components associated with the chart and deletes the release.\n\n_See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._\n\nCRDs created by this chart are not removed by default and should be manually cleaned up:\n\n```console\nkubectl delete crd alertmanagerconfigs.monitoring.coreos.com\nkubectl delete crd alertmanagers.monitoring.coreos.com\nkubectl delete crd podmonitors.monitoring.coreos.com\nkubectl delete crd probes.monitoring.coreos.com\nkubectl delete crd prometheuses.monitoring.coreos.com\nkubectl delete crd prometheusrules.monitoring.coreos.com\nkubectl delete crd servicemonitors.monitoring.coreos.com\nkubectl delete crd thanosrulers.monitoring.coreos.com\n```\n\n## Upgrading Chart\n\n```console\n# Helm\n$ helm upgrade [RELEASE_NAME] prometheus-community/kube-prometheus-stack\n```\n\nWith Helm v3, CRDs created by this chart are not updated by default and should be manually updated.\nConsult also the [Helm Documentation on CRDs](https://helm.sh/docs/chart_best_practices/custom_resource_definitions).\n\n_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._\n\n### Upgrading an existing Release to a new major version\n\nA major chart version change (like v1.2.3 -> v2.0.0) indicates that there is an incompatible breaking change needing manual actions.\n\n### From 16.x to 17.x\nVersion 17 upgrades prometheus-operator from 0.48.x to 0.49.x. Helm does not automatically upgrade or install new CRDs on a chart upgrade, so you have to install the CRDs manually before updating:\n\n```console\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml\n```\n\n\n### From 15.x to 16.x\nVersion 16 upgrades kube-state-metrics to v2.0.0. This includes changed command-line arguments and removed metrics, see this [blog post](https://kubernetes.io/blog/2021/04/13/kube-state-metrics-v-2-0/). This version also removes Grafana dashboards that supported Kubernetes 1.14 or earlier.\n\n### From 14.x to 15.x\nVersion 15 upgrades prometheus-operator from 0.46.x to 0.47.x. Helm does not automatically upgrade or install new CRDs on a chart upgrade, so you have to install the CRDs manually before updating:\n\n```console\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.47.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.47.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.47.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.47.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.47.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.47.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.47.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml\n```\n\n### From 13.x to 14.x\n\nVersion 14 upgrades prometheus-operator from 0.45.x to 0.46.x. Helm does not automatically upgrade or install new CRDs on a chart upgrade, so you have to install the CRDs manually before updating:\n\n```console\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.46.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.46.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.46.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.46.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.46.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.46.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.46.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml\n```\n\n### From 12.x to 13.x\n\nVersion 13 upgrades prometheus-operator from 0.44.x to 0.45.x. Helm does not automatically upgrade or install new CRDs on a chart upgrade, so you have to install the CRD manually before updating:\n\n```console\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.45.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.45.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.45.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml\n```\n\n### From 11.x to 12.x\n\nVersion 12 upgrades prometheus-operator from 0.43.x to 0.44.x. Helm does not automatically upgrade or install new CRDs on a chart upgrade, so you have to install the CRD manually before updating:\n\n```console\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/release-0.44/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml\n```\n\nThe chart was migrated to support only helm v3 and later.\n\n### From 10.x to 11.x\n\nVersion 11 upgrades prometheus-operator from 0.42.x to 0.43.x. Starting with 0.43.x an additional `AlertmanagerConfigs` CRD is introduced. Helm does not automatically upgrade or install new CRDs on a chart upgrade, so you have to install the CRD manually before updating:\n\n```console\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/release-0.43/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml\n```\n\nVersion 11 removes the deprecated tlsProxy via ghostunnel in favor of native TLS support the prometheus-operator gained with v0.39.0.\n\n### From 9.x to 10.x\n\nVersion 10 upgrades prometheus-operator from 0.38.x to 0.42.x. Starting with 0.40.x an additional `Probes` CRD is introduced. Helm does not automatically upgrade or install new CRDs on a chart upgrade, so you have to install the CRD manually before updating:\n\n```console\nkubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/release-0.42/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml\n```\n\n### From 8.x to 9.x\n\nVersion 9 of the helm chart removes the existing `additionalScrapeConfigsExternal` in favour of `additionalScrapeConfigsSecret`. This change lets users specify the secret name and secret key to use for the additional scrape configuration of prometheus. This is useful for users that have prometheus-operator as a subchart and also have a template that creates the additional scrape configuration.\n\n### From 7.x to 8.x\n\nDue to new template functions being used in the rules in version 8.x.x of the chart, an upgrade to Prometheus Operator and Prometheus is necessary in order to support them. First, upgrade to the latest version of 7.x.x\n\n```console\nhelm upgrade [RELEASE_NAME] prometheus-community/kube-prometheus-stack --version 7.5.0\n```\n\nThen upgrade to 8.x.x\n\n```console\nhelm upgrade [RELEASE_NAME] prometheus-community/kube-prometheus-stack --version [8.x.x]\n```\n\nMinimal recommended Prometheus version for this chart release is `2.12.x`\n\n### From 6.x to 7.x\n\nDue to a change in grafana subchart, version 7.x.x now requires Helm >= 2.12.0.\n\n### From 5.x to 6.x\n\nDue to a change in deployment labels of kube-state-metrics, the upgrade requires `helm upgrade --force` in order to re-create the deployment. If this is not done an error will occur indicating that the deployment cannot be modified:\n\n```console\ninvalid: spec.selector: Invalid value: v1.LabelSelector{MatchLabels:map[string]string{\"app.kubernetes.io/name\":\"kube-state-metrics\"}, MatchExpressions:[]v1.LabelSelectorRequirement(nil)}: field is immutable\n```\n\nIf this error has already been encountered, a `helm history` command can be used to determine which release has worked, then `helm rollback` to the release, then `helm upgrade --force` to this new one\n\n## Configuration\n\nSee [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). To see all configurable options with detailed comments:\n\n```console\nhelm show values prometheus-community/kube-prometheus-stack\n```\n\nYou may also `helm show values` on this chart's [dependencies](#dependencies) for additional options.\n\n### Multiple releases\n\nThe same chart can be used to run multiple Prometheus instances in the same cluster if required. To achieve this, it is necessary to run only one instance of prometheus-operator and a pair of alertmanager pods for an HA configuration, while all other components need to be disabled. To disable a dependency during installation, set `kubeStateMetrics.enabled`, `nodeExporter.enabled` and `grafana.enabled` to `false`.\n\n## Work-Arounds for Known Issues\n\n### Running on private GKE clusters\n\nWhen Google configure the control plane for private clusters, they automatically configure VPC peering between your Kubernetes cluster’s network and a separate Google managed project. In order to restrict what Google are able to access within your cluster, the firewall rules configured restrict access to your Kubernetes pods. This means that in order to use the webhook component with a GKE private cluster, you must configure an additional firewall rule to allow the GKE control plane access to your webhook pod.\n\nYou can read more information on how to add firewall rules for the GKE control plane nodes in the [GKE docs](https://cloud.google.com/kubernetes-engine/docs/how-to/private-clusters#add_firewall_rules)\n\nAlternatively, you can disable the hooks by setting `prometheusOperator.admissionWebhooks.enabled=false`.\n\n## PrometheusRules Admission Webhooks\n\nWith Prometheus Operator version 0.30+, the core Prometheus Operator pod exposes an endpoint that will integrate with the `validatingwebhookconfiguration` Kubernetes feature to prevent malformed rules from being added to the cluster.\n\n### How the Chart Configures the Hooks\n\nA validating and mutating webhook configuration requires the endpoint to which the request is sent to use TLS. It is possible to set up custom certificates to do this, but in most cases, a self-signed certificate is enough. The setup of this component requires some more complex orchestration when using helm. The steps are created to be idempotent and to allow turning the feature on and off without running into helm quirks.\n\n1. A pre-install hook provisions a certificate into the same namespace using a format compatible with provisioning using end-user certificates. If the certificate already exists, the hook exits.\n2. The prometheus operator pod is configured to use a TLS proxy container, which will load that certificate.\n3. Validating and Mutating webhook configurations are created in the cluster, with their failure mode set to Ignore. This allows rules to be created by the same chart at the same time, even though the webhook has not yet been fully set up - it does not have the correct CA field set.\n4. A post-install hook reads the CA from the secret created by step 1 and patches the Validating and Mutating webhook configurations. This process will allow a custom CA provisioned by some other process to also be patched into the webhook configurations. The chosen failure policy is also patched into the webhook configurations\n\n### Alternatives\n\nIt should be possible to use [jetstack/cert-manager](https://github.com/jetstack/cert-manager) if a more complete solution is required, but it has not been tested.\n\nYou can enable automatic self-signed TLS certificate provisioning via cert-manager by setting the `prometheusOperator.admissionWebhooks.certManager.enabled` value to true.\n\n### Limitations\n\nBecause the operator can only run as a single pod, there is potential for this component failure to cause rule deployment failure. Because this risk is outweighed by the benefit of having validation, the feature is enabled by default.\n\n## Developing Prometheus Rules and Grafana Dashboards\n\nThis chart Grafana Dashboards and Prometheus Rules are just a copy from [prometheus-operator/prometheus-operator](https://github.com/prometheus-operator/prometheus-operator) and other sources, synced (with alterations) by scripts in [hack](hack) folder. In order to introduce any changes you need to first [add them to the original repo](https://github.com/prometheus-operator/kube-prometheus/blob/master/docs/developing-prometheus-rules-and-grafana-dashboards.md) and then sync there by scripts.\n\n## Further Information\n\nFor more in-depth documentation of configuration options meanings, please see\n\n- [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)\n- [Prometheus](https://prometheus.io/docs/introduction/overview/)\n- [Grafana](https://github.com/grafana/helm-charts/tree/main/charts/grafana#grafana-helm-chart)\n\n## prometheus.io/scrape\n\nThe prometheus operator does not support annotation-based discovery of services, using the `PodMonitor` or `ServiceMonitor` CRD in its place as they provide far more configuration options.\nFor information on how to use PodMonitors/ServiceMonitors, please see the documentation on the `prometheus-operator/prometheus-operator` documentation here:\n\n- [ServiceMonitors](https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/user-guides/getting-started.md#include-servicemonitors)\n- [PodMonitors](https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/user-guides/getting-started.md#include-podmonitors)\n- [Running Exporters](https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/user-guides/running-exporters.md)\n\nBy default, Prometheus discovers PodMonitors and ServiceMonitors within its namespace, that are labeled with the same release tag as the prometheus-operator release.\nSometimes, you may need to discover custom PodMonitors/ServiceMonitors, for example used to scrape data from third-party applications.\nAn easy way of doing this, without compromising the default PodMonitors/ServiceMonitors discovery, is allowing Prometheus to discover all PodMonitors/ServiceMonitors within its namespace, without applying label filtering.\nTo do so, you can set `prometheus.prometheusSpec.podMonitorSelectorNilUsesHelmValues` and `prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues` to `false`.\n\n## Migrating from stable/prometheus-operator chart\n\n## Zero downtime\n\nSince `kube-prometheus-stack` is fully compatible with the `stable/prometheus-operator` chart, a migration without downtime can be achieved.\nHowever, the old name prefix needs to be kept. If you want the new name please follow the step by step guide below (with downtime).\n\nYou can override the name to achieve this:\n\n```console\nhelm upgrade prometheus-operator prometheus-community/kube-prometheus-stack -n monitoring --reuse-values --set nameOverride=prometheus-operator\n```\n\n**Note**: It is recommended to run this first with `--dry-run --debug`.\n\n## Redeploy with new name (downtime)\n\nIf the **prometheus-operator** values are compatible with the new **kube-prometheus-stack** chart, please follow the below steps for migration:\n\n> The guide presumes that chart is deployed in `monitoring` namespace and the deployments are running there. If in other namespace, please replace the `monitoring` to the deployed namespace.\n\n1. Patch the PersistenceVolume created/used by the prometheus-operator chart to `Retain` claim policy:\n\n    ```console\n    kubectl patch pv/<PersistentVolume name> -p '{\"spec\":{\"persistentVolumeReclaimPolicy\":\"Retain\"}}'\n    ```\n\n    **Note:** To execute the above command, the user must have a cluster wide permission. Please refer [Kubernetes RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)\n\n2. Uninstall the **prometheus-operator** release and delete the existing PersistentVolumeClaim, and verify PV become Released.\n\n    ```console\n    helm uninstall prometheus-operator -n monitoring\n    kubectl delete pvc/<PersistenceVolumeClaim name> -n monitoring\n    ```\n\n    Additionally, you have to manually remove the remaining `prometheus-operator-kubelet` service.\n\n    ```console\n    kubectl delete service/prometheus-operator-kubelet -n kube-system\n    ```\n\n    You can choose to remove all your existing CRDs (ServiceMonitors, Podmonitors, etc.) if you want to.\n\n3. Remove current `spec.claimRef` values to change the PV's status from Released to Available.\n\n    ```console\n    kubectl patch pv/<PersistentVolume name> --type json -p='[{\"op\": \"remove\", \"path\": \"/spec/claimRef\"}]' -n monitoring\n    ```\n\n**Note:** To execute the above command, the user must have a cluster wide permission. Please refer to [Kubernetes RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)\n\nAfter these steps, proceed to a fresh **kube-prometheus-stack** installation and make sure the current release of **kube-prometheus-stack** matching the `volumeClaimTemplate` values in the `values.yaml`.\n\nThe binding is done via matching a specific amount of storage requested and with certain access modes.\n\nFor example, if you had storage specified as this with **prometheus-operator**:\n\n```yaml\nvolumeClaimTemplate:\n  spec:\n    storageClassName: gp2\n    accessModes: [\"ReadWriteOnce\"]\n    resources:\n     requests:\n       storage: 50Gi\n```\n\nYou have to specify matching `volumeClaimTemplate` with 50Gi storage and `ReadWriteOnce` access mode.\n\nAdditionally, you should check the current AZ of your legacy installation's PV, and configure the fresh release to use the same AZ as the old one. If the pods are in a different AZ than the PV, the release will fail to bind the existing one, hence creating a new PV.\n\nThis can be achieved either by specifying the labels through `values.yaml`, e.g. setting `prometheus.prometheusSpec.nodeSelector` to:\n\n```yaml\nnodeSelector:\n  failure-domain.beta.kubernetes.io/zone: east-west-1a\n```\n\nor passing these values as `--set` overrides during installation.\n\nThe new release should now re-attach your previously released PV with its content.\n\n## Migrating from coreos/prometheus-operator chart\n\nThe multiple charts have been combined into a single chart that installs prometheus operator, prometheus, alertmanager, grafana as well as the multitude of exporters necessary to monitor a cluster.\n\nThere is no simple and direct migration path between the charts as the changes are extensive and intended to make the chart easier to support.\n\nThe capabilities of the old chart are all available in the new chart, including the ability to run multiple prometheus instances on a single cluster - you will need to disable the parts of the chart you do not wish to deploy.\n\nYou can check out the tickets for this change [here](https://github.com/prometheus-operator/prometheus-operator/issues/592) and [here](https://github.com/helm/charts/pull/6765).\n\n### High-level overview of Changes\n\n#### Added dependencies\n\nThe chart has added 3 [dependencies](#dependencies).\n\n- Node-Exporter, Kube-State-Metrics: These components are loaded as dependencies into the chart, and are relatively simple components\n- Grafana: The Grafana chart is more feature-rich than this chart - it contains a sidecar that is able to load data sources and dashboards from configmaps deployed into the same cluster. For more information check out the [documentation for the chart](https://github.com/grafana/helm-charts/blob/main/charts/grafana/README.md)\n\n#### Kubelet Service\n\nBecause the kubelet service has a new name in the chart, make sure to clean up the old kubelet service in the `kube-system` namespace to prevent counting container metrics twice.\n\n#### Persistent Volumes\n\nIf you would like to keep the data of the current persistent volumes, it should be possible to attach existing volumes to new PVCs and PVs that are created using the conventions in the new chart. For example, in order to use an existing Azure disk for a helm release called `prometheus-migration` the following resources can be created:\n\n```yaml\napiVersion: v1\nkind: PersistentVolume\nmetadata:\n  name: pvc-prometheus-migration-prometheus-0\nspec:\n  accessModes:\n  - ReadWriteOnce\n  azureDisk:\n    cachingMode: None\n    diskName: pvc-prometheus-migration-prometheus-0\n    diskURI: /subscriptions/f5125d82-2622-4c50-8d25-3f7ba3e9ac4b/resourceGroups/sample-migration-resource-group/providers/Microsoft.Compute/disks/pvc-prometheus-migration-prometheus-0\n    fsType: \"\"\n    kind: Managed\n    readOnly: false\n  capacity:\n    storage: 1Gi\n  persistentVolumeReclaimPolicy: Delete\n  storageClassName: prometheus\n  volumeMode: Filesystem\n```\n\n```yaml\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  labels:\n    app.kubernetes.io/name: prometheus\n    prometheus: prometheus-migration-prometheus\n  name: prometheus-prometheus-migration-prometheus-db-prometheus-prometheus-migration-prometheus-0\n  namespace: monitoring\nspec:\n  accessModes:\n  - ReadWriteOnce\n  resources:\n    requests:\n      storage: 1Gi\n  storageClassName: prometheus\n  volumeMode: Filesystem\n  volumeName: pvc-prometheus-migration-prometheus-0\n```\n\nThe PVC will take ownership of the PV and when you create a release using a persistent volume claim template it will use the existing PVCs as they match the naming convention used by the chart. For other cloud providers similar approaches can be used.\n\n#### KubeProxy\n\nThe metrics bind address of kube-proxy is default to `127.0.0.1:10249` that prometheus instances **cannot** access to. You should expose metrics by changing `metricsBindAddress` field value to `0.0.0.0:10249` if you want to collect them.\n\nDepending on the cluster, the relevant part `config.conf` will be in ConfigMap `kube-system/kube-proxy` or `kube-system/kube-proxy-config`. For example:\n\n```console\nkubectl -n kube-system edit cm kube-proxy\n```\n\n```yaml\napiVersion: v1\ndata:\n  config.conf: |-\n    apiVersion: kubeproxy.config.k8s.io/v1alpha1\n    kind: KubeProxyConfiguration\n    # ...\n    # metricsBindAddress: 127.0.0.1:10249\n    metricsBindAddress: 0.0.0.0:10249\n    # ...\n  kubeconfig.conf: |-\n    # ...\nkind: ConfigMap\nmetadata:\n  labels:\n    app: kube-proxy\n  name: kube-proxy\n  namespace: kube-system\n```\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/ci/01-provision-crds-values.yaml",
    "content": "alertmanager:\n  enabled: false\ncoreDns:\n  enabled: false\nkubeApiServer:\n  enabled: false\nkubeControllerManager:\n  enabled: false\nkubeDns:\n  enabled: false\nkubeEtcd:\n  enabled: false\nkubeProxy:\n  enabled: false\nkubeScheduler:\n  enabled: false\nkubeStateMetrics:\n  enabled: false\nkubelet:\n  enabled: false\nnodeExporter:\n  enabled: false\ngrafana:\n  enabled: false\nprometheus:\n  enabled: false\ndefaultRules:\n  create: false\n# Default configuration of prometheus operator will create CRDs in the cluster idempotently\nprometheusOperator:\n  enabled: true\n  serviceMonitor:\n    selfMonitor: false\n  tls:\n    enabled: false\n  admissionWebhooks:\n    enabled: false\n  namespaces:\n    releaseNamespace: true\n    additional:\n      - kube-system\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/ci/02-test-without-crds-values.yaml",
    "content": "prometheusOperator:\n  namespaces:\n    releaseNamespace: true\n    additional:\n      - kube-system\n\nprometheus-node-exporter:\n  service:\n    targetPort: 9101\n    port: 9101\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/crds/crd-alertmanagerconfigs.yaml",
    "content": "# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml\n\n---\napiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.4.1\n  creationTimestamp: null\n  name: alertmanagerconfigs.monitoring.coreos.com\nspec:\n  group: monitoring.coreos.com\n  names:\n    categories:\n    - prometheus-operator\n    kind: AlertmanagerConfig\n    listKind: AlertmanagerConfigList\n    plural: alertmanagerconfigs\n    singular: alertmanagerconfig\n  scope: Namespaced\n  versions:\n  - name: v1alpha1\n    schema:\n      openAPIV3Schema:\n        description: AlertmanagerConfig defines a namespaced AlertmanagerConfig to\n          be aggregated across multiple namespaces configuring one Alertmanager cluster.\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: AlertmanagerConfigSpec is a specification of the desired\n              behavior of the Alertmanager configuration. By definition, the Alertmanager\n              configuration only applies to alerts for which the `namespace` label\n              is equal to the namespace of the AlertmanagerConfig resource.\n            properties:\n              inhibitRules:\n                description: List of inhibition rules. The rules will only apply to\n                  alerts matching the resource’s namespace.\n                items:\n                  description: InhibitRule defines an inhibition rule that allows\n                    to mute alerts when other alerts are already firing. See https://prometheus.io/docs/alerting/latest/configuration/#inhibit_rule\n                  properties:\n                    equal:\n                      description: Labels that must have an equal value in the source\n                        and target alert for the inhibition to take effect.\n                      items:\n                        type: string\n                      type: array\n                    sourceMatch:\n                      description: Matchers for which one or more alerts have to exist\n                        for the inhibition to take effect. The operator enforces that\n                        the alert matches the resource’s namespace.\n                      items:\n                        description: Matcher defines how to match on alert's labels.\n                        properties:\n                          name:\n                            description: Label to match.\n                            minLength: 1\n                            type: string\n                          regex:\n                            description: Whether to match on equality (false) or regular-expression\n                              (true).\n                            type: boolean\n                          value:\n                            description: Label value to match.\n                            type: string\n                        required:\n                        - name\n                        type: object\n                      type: array\n                    targetMatch:\n                      description: Matchers that have to be fulfilled in the alerts\n                        to be muted. The operator enforces that the alert matches\n                        the resource’s namespace.\n                      items:\n                        description: Matcher defines how to match on alert's labels.\n                        properties:\n                          name:\n                            description: Label to match.\n                            minLength: 1\n                            type: string\n                          regex:\n                            description: Whether to match on equality (false) or regular-expression\n                              (true).\n                            type: boolean\n                          value:\n                            description: Label value to match.\n                            type: string\n                        required:\n                        - name\n                        type: object\n                      type: array\n                  type: object\n                type: array\n              receivers:\n                description: List of receivers.\n                items:\n                  description: Receiver defines one or more notification integrations.\n                  properties:\n                    emailConfigs:\n                      description: List of Email configurations.\n                      items:\n                        description: EmailConfig configures notifications via Email.\n                        properties:\n                          authIdentity:\n                            description: The identity to use for authentication.\n                            type: string\n                          authPassword:\n                            description: The secret's key that contains the password\n                              to use for authentication. The secret needs to be in\n                              the same namespace as the AlertmanagerConfig object\n                              and accessible by the Prometheus Operator.\n                            properties:\n                              key:\n                                description: The key of the secret to select from.  Must\n                                  be a valid secret key.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret or its key\n                                  must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                          authSecret:\n                            description: The secret's key that contains the CRAM-MD5\n                              secret. The secret needs to be in the same namespace\n                              as the AlertmanagerConfig object and accessible by the\n                              Prometheus Operator.\n                            properties:\n                              key:\n                                description: The key of the secret to select from.  Must\n                                  be a valid secret key.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret or its key\n                                  must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                          authUsername:\n                            description: The username to use for authentication.\n                            type: string\n                          from:\n                            description: The sender address.\n                            type: string\n                          headers:\n                            description: Further headers email header key/value pairs.\n                              Overrides any headers previously set by the notification\n                              implementation.\n                            items:\n                              description: KeyValue defines a (key, value) tuple.\n                              properties:\n                                key:\n                                  description: Key of the tuple.\n                                  minLength: 1\n                                  type: string\n                                value:\n                                  description: Value of the tuple.\n                                  type: string\n                              required:\n                              - key\n                              - value\n                              type: object\n                            type: array\n                          hello:\n                            description: The hostname to identify to the SMTP server.\n                            type: string\n                          html:\n                            description: The HTML body of the email notification.\n                            type: string\n                          requireTLS:\n                            description: The SMTP TLS requirement. Note that Go does\n                              not support unencrypted connections to remote SMTP endpoints.\n                            type: boolean\n                          sendResolved:\n                            description: Whether or not to notify about resolved alerts.\n                            type: boolean\n                          smarthost:\n                            description: The SMTP host through which emails are sent.\n                            type: string\n                          text:\n                            description: The text body of the email notification.\n                            type: string\n                          tlsConfig:\n                            description: TLS configuration\n                            properties:\n                              ca:\n                                description: Struct containing the CA cert to use\n                                  for the targets.\n                                properties:\n                                  configMap:\n                                    description: ConfigMap containing data to use\n                                      for the targets.\n                                    properties:\n                                      key:\n                                        description: The key to select.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the ConfigMap\n                                          or its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                  secret:\n                                    description: Secret containing data to use for\n                                      the targets.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                type: object\n                              cert:\n                                description: Struct containing the client cert file\n                                  for the targets.\n                                properties:\n                                  configMap:\n                                    description: ConfigMap containing data to use\n                                      for the targets.\n                                    properties:\n                                      key:\n                                        description: The key to select.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the ConfigMap\n                                          or its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                  secret:\n                                    description: Secret containing data to use for\n                                      the targets.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                type: object\n                              insecureSkipVerify:\n                                description: Disable target certificate validation.\n                                type: boolean\n                              keySecret:\n                                description: Secret containing the client key file\n                                  for the targets.\n                                properties:\n                                  key:\n                                    description: The key of the secret to select from.  Must\n                                      be a valid secret key.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the Secret or its\n                                      key must be defined\n                                    type: boolean\n                                required:\n                                - key\n                                type: object\n                              serverName:\n                                description: Used to verify the hostname for the targets.\n                                type: string\n                            type: object\n                          to:\n                            description: The email address to send notifications to.\n                            type: string\n                        type: object\n                      type: array\n                    name:\n                      description: Name of the receiver. Must be unique across all\n                        items from the list.\n                      minLength: 1\n                      type: string\n                    opsgenieConfigs:\n                      description: List of OpsGenie configurations.\n                      items:\n                        description: OpsGenieConfig configures notifications via OpsGenie.\n                          See https://prometheus.io/docs/alerting/latest/configuration/#opsgenie_config\n                        properties:\n                          apiKey:\n                            description: The secret's key that contains the OpsGenie\n                              API key. The secret needs to be in the same namespace\n                              as the AlertmanagerConfig object and accessible by the\n                              Prometheus Operator.\n                            properties:\n                              key:\n                                description: The key of the secret to select from.  Must\n                                  be a valid secret key.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret or its key\n                                  must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                          apiURL:\n                            description: The URL to send OpsGenie API requests to.\n                            type: string\n                          description:\n                            description: Description of the incident.\n                            type: string\n                          details:\n                            description: A set of arbitrary key/value pairs that provide\n                              further detail about the incident.\n                            items:\n                              description: KeyValue defines a (key, value) tuple.\n                              properties:\n                                key:\n                                  description: Key of the tuple.\n                                  minLength: 1\n                                  type: string\n                                value:\n                                  description: Value of the tuple.\n                                  type: string\n                              required:\n                              - key\n                              - value\n                              type: object\n                            type: array\n                          httpConfig:\n                            description: HTTP client configuration.\n                            properties:\n                              basicAuth:\n                                description: BasicAuth for the client.\n                                properties:\n                                  password:\n                                    description: The secret in the service monitor\n                                      namespace that contains the password for authentication.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                  username:\n                                    description: The secret in the service monitor\n                                      namespace that contains the username for authentication.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                type: object\n                              bearerTokenSecret:\n                                description: The secret's key that contains the bearer\n                                  token to be used by the client for authentication.\n                                  The secret needs to be in the same namespace as\n                                  the AlertmanagerConfig object and accessible by\n                                  the Prometheus Operator.\n                                properties:\n                                  key:\n                                    description: The key of the secret to select from.  Must\n                                      be a valid secret key.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the Secret or its\n                                      key must be defined\n                                    type: boolean\n                                required:\n                                - key\n                                type: object\n                              proxyURL:\n                                description: Optional proxy URL.\n                                type: string\n                              tlsConfig:\n                                description: TLS configuration for the client.\n                                properties:\n                                  ca:\n                                    description: Struct containing the CA cert to\n                                      use for the targets.\n                                    properties:\n                                      configMap:\n                                        description: ConfigMap containing data to\n                                          use for the targets.\n                                        properties:\n                                          key:\n                                            description: The key to select.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the ConfigMap\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                      secret:\n                                        description: Secret containing data to use\n                                          for the targets.\n                                        properties:\n                                          key:\n                                            description: The key of the secret to\n                                              select from.  Must be a valid secret\n                                              key.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the Secret\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                    type: object\n                                  cert:\n                                    description: Struct containing the client cert\n                                      file for the targets.\n                                    properties:\n                                      configMap:\n                                        description: ConfigMap containing data to\n                                          use for the targets.\n                                        properties:\n                                          key:\n                                            description: The key to select.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the ConfigMap\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                      secret:\n                                        description: Secret containing data to use\n                                          for the targets.\n                                        properties:\n                                          key:\n                                            description: The key of the secret to\n                                              select from.  Must be a valid secret\n                                              key.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the Secret\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                    type: object\n                                  insecureSkipVerify:\n                                    description: Disable target certificate validation.\n                                    type: boolean\n                                  keySecret:\n                                    description: Secret containing the client key\n                                      file for the targets.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                  serverName:\n                                    description: Used to verify the hostname for the\n                                      targets.\n                                    type: string\n                                type: object\n                            type: object\n                          message:\n                            description: Alert text limited to 130 characters.\n                            type: string\n                          note:\n                            description: Additional alert note.\n                            type: string\n                          priority:\n                            description: Priority level of alert. Possible values\n                              are P1, P2, P3, P4, and P5.\n                            type: string\n                          responders:\n                            description: List of responders responsible for notifications.\n                            items:\n                              description: OpsGenieConfigResponder defines a responder\n                                to an incident. One of `id`, `name` or `username`\n                                has to be defined.\n                              properties:\n                                id:\n                                  description: ID of the responder.\n                                  type: string\n                                name:\n                                  description: Name of the responder.\n                                  type: string\n                                type:\n                                  description: Type of responder.\n                                  minLength: 1\n                                  type: string\n                                username:\n                                  description: Username of the responder.\n                                  type: string\n                              required:\n                              - type\n                              type: object\n                            type: array\n                          sendResolved:\n                            description: Whether or not to notify about resolved alerts.\n                            type: boolean\n                          source:\n                            description: Backlink to the sender of the notification.\n                            type: string\n                          tags:\n                            description: Comma separated list of tags attached to\n                              the notifications.\n                            type: string\n                        type: object\n                      type: array\n                    pagerdutyConfigs:\n                      description: List of PagerDuty configurations.\n                      items:\n                        description: PagerDutyConfig configures notifications via\n                          PagerDuty. See https://prometheus.io/docs/alerting/latest/configuration/#pagerduty_config\n                        properties:\n                          class:\n                            description: The class/type of the event.\n                            type: string\n                          client:\n                            description: Client identification.\n                            type: string\n                          clientURL:\n                            description: Backlink to the sender of notification.\n                            type: string\n                          component:\n                            description: The part or component of the affected system\n                              that is broken.\n                            type: string\n                          description:\n                            description: Description of the incident.\n                            type: string\n                          details:\n                            description: Arbitrary key/value pairs that provide further\n                              detail about the incident.\n                            items:\n                              description: KeyValue defines a (key, value) tuple.\n                              properties:\n                                key:\n                                  description: Key of the tuple.\n                                  minLength: 1\n                                  type: string\n                                value:\n                                  description: Value of the tuple.\n                                  type: string\n                              required:\n                              - key\n                              - value\n                              type: object\n                            type: array\n                          group:\n                            description: A cluster or grouping of sources.\n                            type: string\n                          httpConfig:\n                            description: HTTP client configuration.\n                            properties:\n                              basicAuth:\n                                description: BasicAuth for the client.\n                                properties:\n                                  password:\n                                    description: The secret in the service monitor\n                                      namespace that contains the password for authentication.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                  username:\n                                    description: The secret in the service monitor\n                                      namespace that contains the username for authentication.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                type: object\n                              bearerTokenSecret:\n                                description: The secret's key that contains the bearer\n                                  token to be used by the client for authentication.\n                                  The secret needs to be in the same namespace as\n                                  the AlertmanagerConfig object and accessible by\n                                  the Prometheus Operator.\n                                properties:\n                                  key:\n                                    description: The key of the secret to select from.  Must\n                                      be a valid secret key.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the Secret or its\n                                      key must be defined\n                                    type: boolean\n                                required:\n                                - key\n                                type: object\n                              proxyURL:\n                                description: Optional proxy URL.\n                                type: string\n                              tlsConfig:\n                                description: TLS configuration for the client.\n                                properties:\n                                  ca:\n                                    description: Struct containing the CA cert to\n                                      use for the targets.\n                                    properties:\n                                      configMap:\n                                        description: ConfigMap containing data to\n                                          use for the targets.\n                                        properties:\n                                          key:\n                                            description: The key to select.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the ConfigMap\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                      secret:\n                                        description: Secret containing data to use\n                                          for the targets.\n                                        properties:\n                                          key:\n                                            description: The key of the secret to\n                                              select from.  Must be a valid secret\n                                              key.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the Secret\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                    type: object\n                                  cert:\n                                    description: Struct containing the client cert\n                                      file for the targets.\n                                    properties:\n                                      configMap:\n                                        description: ConfigMap containing data to\n                                          use for the targets.\n                                        properties:\n                                          key:\n                                            description: The key to select.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the ConfigMap\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                      secret:\n                                        description: Secret containing data to use\n                                          for the targets.\n                                        properties:\n                                          key:\n                                            description: The key of the secret to\n                                              select from.  Must be a valid secret\n                                              key.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the Secret\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                    type: object\n                                  insecureSkipVerify:\n                                    description: Disable target certificate validation.\n                                    type: boolean\n                                  keySecret:\n                                    description: Secret containing the client key\n                                      file for the targets.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                  serverName:\n                                    description: Used to verify the hostname for the\n                                      targets.\n                                    type: string\n                                type: object\n                            type: object\n                          routingKey:\n                            description: The secret's key that contains the PagerDuty\n                              integration key (when using Events API v2). Either this\n                              field or `serviceKey` needs to be defined. The secret\n                              needs to be in the same namespace as the AlertmanagerConfig\n                              object and accessible by the Prometheus Operator.\n                            properties:\n                              key:\n                                description: The key of the secret to select from.  Must\n                                  be a valid secret key.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret or its key\n                                  must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                          sendResolved:\n                            description: Whether or not to notify about resolved alerts.\n                            type: boolean\n                          serviceKey:\n                            description: The secret's key that contains the PagerDuty\n                              service key (when using integration type \"Prometheus\").\n                              Either this field or `routingKey` needs to be defined.\n                              The secret needs to be in the same namespace as the\n                              AlertmanagerConfig object and accessible by the Prometheus\n                              Operator.\n                            properties:\n                              key:\n                                description: The key of the secret to select from.  Must\n                                  be a valid secret key.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret or its key\n                                  must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                          severity:\n                            description: Severity of the incident.\n                            type: string\n                          url:\n                            description: The URL to send requests to.\n                            type: string\n                        type: object\n                      type: array\n                    pushoverConfigs:\n                      description: List of Pushover configurations.\n                      items:\n                        description: PushoverConfig configures notifications via Pushover.\n                          See https://prometheus.io/docs/alerting/latest/configuration/#pushover_config\n                        properties:\n                          expire:\n                            description: How long your notification will continue\n                              to be retried for, unless the user acknowledges the\n                              notification.\n                            type: string\n                          html:\n                            description: Whether notification message is HTML or plain\n                              text.\n                            type: boolean\n                          httpConfig:\n                            description: HTTP client configuration.\n                            properties:\n                              basicAuth:\n                                description: BasicAuth for the client.\n                                properties:\n                                  password:\n                                    description: The secret in the service monitor\n                                      namespace that contains the password for authentication.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                  username:\n                                    description: The secret in the service monitor\n                                      namespace that contains the username for authentication.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                type: object\n                              bearerTokenSecret:\n                                description: The secret's key that contains the bearer\n                                  token to be used by the client for authentication.\n                                  The secret needs to be in the same namespace as\n                                  the AlertmanagerConfig object and accessible by\n                                  the Prometheus Operator.\n                                properties:\n                                  key:\n                                    description: The key of the secret to select from.  Must\n                                      be a valid secret key.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the Secret or its\n                                      key must be defined\n                                    type: boolean\n                                required:\n                                - key\n                                type: object\n                              proxyURL:\n                                description: Optional proxy URL.\n                                type: string\n                              tlsConfig:\n                                description: TLS configuration for the client.\n                                properties:\n                                  ca:\n                                    description: Struct containing the CA cert to\n                                      use for the targets.\n                                    properties:\n                                      configMap:\n                                        description: ConfigMap containing data to\n                                          use for the targets.\n                                        properties:\n                                          key:\n                                            description: The key to select.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the ConfigMap\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                      secret:\n                                        description: Secret containing data to use\n                                          for the targets.\n                                        properties:\n                                          key:\n                                            description: The key of the secret to\n                                              select from.  Must be a valid secret\n                                              key.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the Secret\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                    type: object\n                                  cert:\n                                    description: Struct containing the client cert\n                                      file for the targets.\n                                    properties:\n                                      configMap:\n                                        description: ConfigMap containing data to\n                                          use for the targets.\n                                        properties:\n                                          key:\n                                            description: The key to select.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the ConfigMap\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                      secret:\n                                        description: Secret containing data to use\n                                          for the targets.\n                                        properties:\n                                          key:\n                                            description: The key of the secret to\n                                              select from.  Must be a valid secret\n                                              key.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the Secret\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                    type: object\n                                  insecureSkipVerify:\n                                    description: Disable target certificate validation.\n                                    type: boolean\n                                  keySecret:\n                                    description: Secret containing the client key\n                                      file for the targets.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                  serverName:\n                                    description: Used to verify the hostname for the\n                                      targets.\n                                    type: string\n                                type: object\n                            type: object\n                          message:\n                            description: Notification message.\n                            type: string\n                          priority:\n                            description: Priority, see https://pushover.net/api#priority\n                            type: string\n                          retry:\n                            description: How often the Pushover servers will send\n                              the same notification to the user. Must be at least\n                              30 seconds.\n                            type: string\n                          sendResolved:\n                            description: Whether or not to notify about resolved alerts.\n                            type: boolean\n                          sound:\n                            description: The name of one of the sounds supported by\n                              device clients to override the user's default sound\n                              choice\n                            type: string\n                          title:\n                            description: Notification title.\n                            type: string\n                          token:\n                            description: The secret's key that contains the registered\n                              application’s API token, see https://pushover.net/apps.\n                              The secret needs to be in the same namespace as the\n                              AlertmanagerConfig object and accessible by the Prometheus\n                              Operator.\n                            properties:\n                              key:\n                                description: The key of the secret to select from.  Must\n                                  be a valid secret key.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret or its key\n                                  must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                          url:\n                            description: A supplementary URL shown alongside the message.\n                            type: string\n                          urlTitle:\n                            description: A title for supplementary URL, otherwise\n                              just the URL is shown\n                            type: string\n                          userKey:\n                            description: The secret's key that contains the recipient\n                              user’s user key. The secret needs to be in the same\n                              namespace as the AlertmanagerConfig object and accessible\n                              by the Prometheus Operator.\n                            properties:\n                              key:\n                                description: The key of the secret to select from.  Must\n                                  be a valid secret key.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret or its key\n                                  must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                        type: object\n                      type: array\n                    slackConfigs:\n                      description: List of Slack configurations.\n                      items:\n                        description: SlackConfig configures notifications via Slack.\n                          See https://prometheus.io/docs/alerting/latest/configuration/#slack_config\n                        properties:\n                          actions:\n                            description: A list of Slack actions that are sent with\n                              each notification.\n                            items:\n                              description: SlackAction configures a single Slack action\n                                that is sent with each notification. See https://api.slack.com/docs/message-attachments#action_fields\n                                and https://api.slack.com/docs/message-buttons for\n                                more information.\n                              properties:\n                                confirm:\n                                  description: SlackConfirmationField protect users\n                                    from destructive actions or particularly distinguished\n                                    decisions by asking them to confirm their button\n                                    click one more time. See https://api.slack.com/docs/interactive-message-field-guide#confirmation_fields\n                                    for more information.\n                                  properties:\n                                    dismissText:\n                                      type: string\n                                    okText:\n                                      type: string\n                                    text:\n                                      minLength: 1\n                                      type: string\n                                    title:\n                                      type: string\n                                  required:\n                                  - text\n                                  type: object\n                                name:\n                                  type: string\n                                style:\n                                  type: string\n                                text:\n                                  minLength: 1\n                                  type: string\n                                type:\n                                  minLength: 1\n                                  type: string\n                                url:\n                                  type: string\n                                value:\n                                  type: string\n                              required:\n                              - text\n                              - type\n                              type: object\n                            type: array\n                          apiURL:\n                            description: The secret's key that contains the Slack\n                              webhook URL. The secret needs to be in the same namespace\n                              as the AlertmanagerConfig object and accessible by the\n                              Prometheus Operator.\n                            properties:\n                              key:\n                                description: The key of the secret to select from.  Must\n                                  be a valid secret key.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret or its key\n                                  must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                          callbackId:\n                            type: string\n                          channel:\n                            description: The channel or user to send notifications\n                              to.\n                            type: string\n                          color:\n                            type: string\n                          fallback:\n                            type: string\n                          fields:\n                            description: A list of Slack fields that are sent with\n                              each notification.\n                            items:\n                              description: SlackField configures a single Slack field\n                                that is sent with each notification. Each field must\n                                contain a title, value, and optionally, a boolean\n                                value to indicate if the field is short enough to\n                                be displayed next to other fields designated as short.\n                                See https://api.slack.com/docs/message-attachments#fields\n                                for more information.\n                              properties:\n                                short:\n                                  type: boolean\n                                title:\n                                  minLength: 1\n                                  type: string\n                                value:\n                                  minLength: 1\n                                  type: string\n                              required:\n                              - title\n                              - value\n                              type: object\n                            type: array\n                          footer:\n                            type: string\n                          httpConfig:\n                            description: HTTP client configuration.\n                            properties:\n                              basicAuth:\n                                description: BasicAuth for the client.\n                                properties:\n                                  password:\n                                    description: The secret in the service monitor\n                                      namespace that contains the password for authentication.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                  username:\n                                    description: The secret in the service monitor\n                                      namespace that contains the username for authentication.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                type: object\n                              bearerTokenSecret:\n                                description: The secret's key that contains the bearer\n                                  token to be used by the client for authentication.\n                                  The secret needs to be in the same namespace as\n                                  the AlertmanagerConfig object and accessible by\n                                  the Prometheus Operator.\n                                properties:\n                                  key:\n                                    description: The key of the secret to select from.  Must\n                                      be a valid secret key.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the Secret or its\n                                      key must be defined\n                                    type: boolean\n                                required:\n                                - key\n                                type: object\n                              proxyURL:\n                                description: Optional proxy URL.\n                                type: string\n                              tlsConfig:\n                                description: TLS configuration for the client.\n                                properties:\n                                  ca:\n                                    description: Struct containing the CA cert to\n                                      use for the targets.\n                                    properties:\n                                      configMap:\n                                        description: ConfigMap containing data to\n                                          use for the targets.\n                                        properties:\n                                          key:\n                                            description: The key to select.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the ConfigMap\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                      secret:\n                                        description: Secret containing data to use\n                                          for the targets.\n                                        properties:\n                                          key:\n                                            description: The key of the secret to\n                                              select from.  Must be a valid secret\n                                              key.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the Secret\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                    type: object\n                                  cert:\n                                    description: Struct containing the client cert\n                                      file for the targets.\n                                    properties:\n                                      configMap:\n                                        description: ConfigMap containing data to\n                                          use for the targets.\n                                        properties:\n                                          key:\n                                            description: The key to select.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the ConfigMap\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                      secret:\n                                        description: Secret containing data to use\n                                          for the targets.\n                                        properties:\n                                          key:\n                                            description: The key of the secret to\n                                              select from.  Must be a valid secret\n                                              key.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the Secret\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                    type: object\n                                  insecureSkipVerify:\n                                    description: Disable target certificate validation.\n                                    type: boolean\n                                  keySecret:\n                                    description: Secret containing the client key\n                                      file for the targets.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                  serverName:\n                                    description: Used to verify the hostname for the\n                                      targets.\n                                    type: string\n                                type: object\n                            type: object\n                          iconEmoji:\n                            type: string\n                          iconURL:\n                            type: string\n                          imageURL:\n                            type: string\n                          linkNames:\n                            type: boolean\n                          mrkdwnIn:\n                            items:\n                              type: string\n                            type: array\n                          pretext:\n                            type: string\n                          sendResolved:\n                            description: Whether or not to notify about resolved alerts.\n                            type: boolean\n                          shortFields:\n                            type: boolean\n                          text:\n                            type: string\n                          thumbURL:\n                            type: string\n                          title:\n                            type: string\n                          titleLink:\n                            type: string\n                          username:\n                            type: string\n                        type: object\n                      type: array\n                    victoropsConfigs:\n                      description: List of VictorOps configurations.\n                      items:\n                        description: VictorOpsConfig configures notifications via\n                          VictorOps. See https://prometheus.io/docs/alerting/latest/configuration/#victorops_config\n                        properties:\n                          apiKey:\n                            description: The secret's key that contains the API key\n                              to use when talking to the VictorOps API. The secret\n                              needs to be in the same namespace as the AlertmanagerConfig\n                              object and accessible by the Prometheus Operator.\n                            properties:\n                              key:\n                                description: The key of the secret to select from.  Must\n                                  be a valid secret key.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret or its key\n                                  must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                          apiUrl:\n                            description: The VictorOps API URL.\n                            type: string\n                          customFields:\n                            description: Additional custom fields for notification.\n                            items:\n                              description: KeyValue defines a (key, value) tuple.\n                              properties:\n                                key:\n                                  description: Key of the tuple.\n                                  minLength: 1\n                                  type: string\n                                value:\n                                  description: Value of the tuple.\n                                  type: string\n                              required:\n                              - key\n                              - value\n                              type: object\n                            type: array\n                          entityDisplayName:\n                            description: Contains summary of the alerted problem.\n                            type: string\n                          httpConfig:\n                            description: The HTTP client's configuration.\n                            properties:\n                              basicAuth:\n                                description: BasicAuth for the client.\n                                properties:\n                                  password:\n                                    description: The secret in the service monitor\n                                      namespace that contains the password for authentication.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                  username:\n                                    description: The secret in the service monitor\n                                      namespace that contains the username for authentication.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                type: object\n                              bearerTokenSecret:\n                                description: The secret's key that contains the bearer\n                                  token to be used by the client for authentication.\n                                  The secret needs to be in the same namespace as\n                                  the AlertmanagerConfig object and accessible by\n                                  the Prometheus Operator.\n                                properties:\n                                  key:\n                                    description: The key of the secret to select from.  Must\n                                      be a valid secret key.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the Secret or its\n                                      key must be defined\n                                    type: boolean\n                                required:\n                                - key\n                                type: object\n                              proxyURL:\n                                description: Optional proxy URL.\n                                type: string\n                              tlsConfig:\n                                description: TLS configuration for the client.\n                                properties:\n                                  ca:\n                                    description: Struct containing the CA cert to\n                                      use for the targets.\n                                    properties:\n                                      configMap:\n                                        description: ConfigMap containing data to\n                                          use for the targets.\n                                        properties:\n                                          key:\n                                            description: The key to select.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the ConfigMap\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                      secret:\n                                        description: Secret containing data to use\n                                          for the targets.\n                                        properties:\n                                          key:\n                                            description: The key of the secret to\n                                              select from.  Must be a valid secret\n                                              key.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the Secret\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                    type: object\n                                  cert:\n                                    description: Struct containing the client cert\n                                      file for the targets.\n                                    properties:\n                                      configMap:\n                                        description: ConfigMap containing data to\n                                          use for the targets.\n                                        properties:\n                                          key:\n                                            description: The key to select.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the ConfigMap\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                      secret:\n                                        description: Secret containing data to use\n                                          for the targets.\n                                        properties:\n                                          key:\n                                            description: The key of the secret to\n                                              select from.  Must be a valid secret\n                                              key.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the Secret\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                    type: object\n                                  insecureSkipVerify:\n                                    description: Disable target certificate validation.\n                                    type: boolean\n                                  keySecret:\n                                    description: Secret containing the client key\n                                      file for the targets.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                  serverName:\n                                    description: Used to verify the hostname for the\n                                      targets.\n                                    type: string\n                                type: object\n                            type: object\n                          messageType:\n                            description: Describes the behavior of the alert (CRITICAL,\n                              WARNING, INFO).\n                            type: string\n                          monitoringTool:\n                            description: The monitoring tool the state message is\n                              from.\n                            type: string\n                          routingKey:\n                            description: A key used to map the alert to a team.\n                            type: string\n                          sendResolved:\n                            description: Whether or not to notify about resolved alerts.\n                            type: boolean\n                          stateMessage:\n                            description: Contains long explanation of the alerted\n                              problem.\n                            type: string\n                        type: object\n                      type: array\n                    webhookConfigs:\n                      description: List of webhook configurations.\n                      items:\n                        description: WebhookConfig configures notifications via a\n                          generic receiver supporting the webhook payload. See https://prometheus.io/docs/alerting/latest/configuration/#webhook_config\n                        properties:\n                          httpConfig:\n                            description: HTTP client configuration.\n                            properties:\n                              basicAuth:\n                                description: BasicAuth for the client.\n                                properties:\n                                  password:\n                                    description: The secret in the service monitor\n                                      namespace that contains the password for authentication.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                  username:\n                                    description: The secret in the service monitor\n                                      namespace that contains the username for authentication.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                type: object\n                              bearerTokenSecret:\n                                description: The secret's key that contains the bearer\n                                  token to be used by the client for authentication.\n                                  The secret needs to be in the same namespace as\n                                  the AlertmanagerConfig object and accessible by\n                                  the Prometheus Operator.\n                                properties:\n                                  key:\n                                    description: The key of the secret to select from.  Must\n                                      be a valid secret key.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the Secret or its\n                                      key must be defined\n                                    type: boolean\n                                required:\n                                - key\n                                type: object\n                              proxyURL:\n                                description: Optional proxy URL.\n                                type: string\n                              tlsConfig:\n                                description: TLS configuration for the client.\n                                properties:\n                                  ca:\n                                    description: Struct containing the CA cert to\n                                      use for the targets.\n                                    properties:\n                                      configMap:\n                                        description: ConfigMap containing data to\n                                          use for the targets.\n                                        properties:\n                                          key:\n                                            description: The key to select.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the ConfigMap\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                      secret:\n                                        description: Secret containing data to use\n                                          for the targets.\n                                        properties:\n                                          key:\n                                            description: The key of the secret to\n                                              select from.  Must be a valid secret\n                                              key.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the Secret\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                    type: object\n                                  cert:\n                                    description: Struct containing the client cert\n                                      file for the targets.\n                                    properties:\n                                      configMap:\n                                        description: ConfigMap containing data to\n                                          use for the targets.\n                                        properties:\n                                          key:\n                                            description: The key to select.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the ConfigMap\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                      secret:\n                                        description: Secret containing data to use\n                                          for the targets.\n                                        properties:\n                                          key:\n                                            description: The key of the secret to\n                                              select from.  Must be a valid secret\n                                              key.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the Secret\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                    type: object\n                                  insecureSkipVerify:\n                                    description: Disable target certificate validation.\n                                    type: boolean\n                                  keySecret:\n                                    description: Secret containing the client key\n                                      file for the targets.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                  serverName:\n                                    description: Used to verify the hostname for the\n                                      targets.\n                                    type: string\n                                type: object\n                            type: object\n                          maxAlerts:\n                            description: Maximum number of alerts to be sent per webhook\n                              message. When 0, all alerts are included.\n                            format: int32\n                            minimum: 0\n                            type: integer\n                          sendResolved:\n                            description: Whether or not to notify about resolved alerts.\n                            type: boolean\n                          url:\n                            description: The URL to send HTTP POST requests to. `urlSecret`\n                              takes precedence over `url`. One of `urlSecret` and\n                              `url` should be defined.\n                            type: string\n                          urlSecret:\n                            description: The secret's key that contains the webhook\n                              URL to send HTTP requests to. `urlSecret` takes precedence\n                              over `url`. One of `urlSecret` and `url` should be defined.\n                              The secret needs to be in the same namespace as the\n                              AlertmanagerConfig object and accessible by the Prometheus\n                              Operator.\n                            properties:\n                              key:\n                                description: The key of the secret to select from.  Must\n                                  be a valid secret key.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret or its key\n                                  must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                        type: object\n                      type: array\n                    wechatConfigs:\n                      description: List of WeChat configurations.\n                      items:\n                        description: WeChatConfig configures notifications via WeChat.\n                          See https://prometheus.io/docs/alerting/latest/configuration/#wechat_config\n                        properties:\n                          agentID:\n                            type: string\n                          apiSecret:\n                            description: The secret's key that contains the WeChat\n                              API key. The secret needs to be in the same namespace\n                              as the AlertmanagerConfig object and accessible by the\n                              Prometheus Operator.\n                            properties:\n                              key:\n                                description: The key of the secret to select from.  Must\n                                  be a valid secret key.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret or its key\n                                  must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                          apiURL:\n                            description: The WeChat API URL.\n                            type: string\n                          corpID:\n                            description: The corp id for authentication.\n                            type: string\n                          httpConfig:\n                            description: HTTP client configuration.\n                            properties:\n                              basicAuth:\n                                description: BasicAuth for the client.\n                                properties:\n                                  password:\n                                    description: The secret in the service monitor\n                                      namespace that contains the password for authentication.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                  username:\n                                    description: The secret in the service monitor\n                                      namespace that contains the username for authentication.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                type: object\n                              bearerTokenSecret:\n                                description: The secret's key that contains the bearer\n                                  token to be used by the client for authentication.\n                                  The secret needs to be in the same namespace as\n                                  the AlertmanagerConfig object and accessible by\n                                  the Prometheus Operator.\n                                properties:\n                                  key:\n                                    description: The key of the secret to select from.  Must\n                                      be a valid secret key.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the Secret or its\n                                      key must be defined\n                                    type: boolean\n                                required:\n                                - key\n                                type: object\n                              proxyURL:\n                                description: Optional proxy URL.\n                                type: string\n                              tlsConfig:\n                                description: TLS configuration for the client.\n                                properties:\n                                  ca:\n                                    description: Struct containing the CA cert to\n                                      use for the targets.\n                                    properties:\n                                      configMap:\n                                        description: ConfigMap containing data to\n                                          use for the targets.\n                                        properties:\n                                          key:\n                                            description: The key to select.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the ConfigMap\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                      secret:\n                                        description: Secret containing data to use\n                                          for the targets.\n                                        properties:\n                                          key:\n                                            description: The key of the secret to\n                                              select from.  Must be a valid secret\n                                              key.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the Secret\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                    type: object\n                                  cert:\n                                    description: Struct containing the client cert\n                                      file for the targets.\n                                    properties:\n                                      configMap:\n                                        description: ConfigMap containing data to\n                                          use for the targets.\n                                        properties:\n                                          key:\n                                            description: The key to select.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the ConfigMap\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                      secret:\n                                        description: Secret containing data to use\n                                          for the targets.\n                                        properties:\n                                          key:\n                                            description: The key of the secret to\n                                              select from.  Must be a valid secret\n                                              key.\n                                            type: string\n                                          name:\n                                            description: 'Name of the referent. More\n                                              info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                              TODO: Add other useful fields. apiVersion,\n                                              kind, uid?'\n                                            type: string\n                                          optional:\n                                            description: Specify whether the Secret\n                                              or its key must be defined\n                                            type: boolean\n                                        required:\n                                        - key\n                                        type: object\n                                    type: object\n                                  insecureSkipVerify:\n                                    description: Disable target certificate validation.\n                                    type: boolean\n                                  keySecret:\n                                    description: Secret containing the client key\n                                      file for the targets.\n                                    properties:\n                                      key:\n                                        description: The key of the secret to select\n                                          from.  Must be a valid secret key.\n                                        type: string\n                                      name:\n                                        description: 'Name of the referent. More info:\n                                          https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                          TODO: Add other useful fields. apiVersion,\n                                          kind, uid?'\n                                        type: string\n                                      optional:\n                                        description: Specify whether the Secret or\n                                          its key must be defined\n                                        type: boolean\n                                    required:\n                                    - key\n                                    type: object\n                                  serverName:\n                                    description: Used to verify the hostname for the\n                                      targets.\n                                    type: string\n                                type: object\n                            type: object\n                          message:\n                            description: API request data as defined by the WeChat\n                              API.\n                            type: string\n                          messageType:\n                            type: string\n                          sendResolved:\n                            description: Whether or not to notify about resolved alerts.\n                            type: boolean\n                          toParty:\n                            type: string\n                          toTag:\n                            type: string\n                          toUser:\n                            type: string\n                        type: object\n                      type: array\n                  required:\n                  - name\n                  type: object\n                type: array\n              route:\n                description: The Alertmanager route definition for alerts matching\n                  the resource’s namespace. If present, it will be added to the generated\n                  Alertmanager configuration as a first-level route.\n                properties:\n                  continue:\n                    description: Boolean indicating whether an alert should continue\n                      matching subsequent sibling nodes. It will always be overridden\n                      to true for the first-level route by the Prometheus operator.\n                    type: boolean\n                  groupBy:\n                    description: List of labels to group by.\n                    items:\n                      type: string\n                    type: array\n                  groupInterval:\n                    description: How long to wait before sending an updated notification.\n                      Must match the regular expression `[0-9]+(ms|s|m|h)` (milliseconds\n                      seconds minutes hours).\n                    type: string\n                  groupWait:\n                    description: How long to wait before sending the initial notification.\n                      Must match the regular expression `[0-9]+(ms|s|m|h)` (milliseconds\n                      seconds minutes hours).\n                    type: string\n                  matchers:\n                    description: 'List of matchers that the alert’s labels should\n                      match. For the first level route, the operator removes any existing\n                      equality and regexp matcher on the `namespace` label and adds\n                      a `namespace: <object namespace>` matcher.'\n                    items:\n                      description: Matcher defines how to match on alert's labels.\n                      properties:\n                        name:\n                          description: Label to match.\n                          minLength: 1\n                          type: string\n                        regex:\n                          description: Whether to match on equality (false) or regular-expression\n                            (true).\n                          type: boolean\n                        value:\n                          description: Label value to match.\n                          type: string\n                      required:\n                      - name\n                      type: object\n                    type: array\n                  receiver:\n                    description: Name of the receiver for this route. If not empty,\n                      it should be listed in the `receivers` field.\n                    type: string\n                  repeatInterval:\n                    description: How long to wait before repeating the last notification.\n                      Must match the regular expression `[0-9]+(ms|s|m|h)` (milliseconds\n                      seconds minutes hours).\n                    type: string\n                  routes:\n                    description: Child routes.\n                    items:\n                      x-kubernetes-preserve-unknown-fields: true\n                    type: array\n                type: object\n            type: object\n        required:\n        - spec\n        type: object\n    served: true\n    storage: true\nstatus:\n  acceptedNames:\n    kind: \"\"\n    plural: \"\"\n  conditions: []\n  storedVersions: []\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/crds/crd-alertmanagers.yaml",
    "content": "# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml\n\n---\napiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.4.1\n  creationTimestamp: null\n  name: alertmanagers.monitoring.coreos.com\nspec:\n  group: monitoring.coreos.com\n  names:\n    categories:\n    - prometheus-operator\n    kind: Alertmanager\n    listKind: AlertmanagerList\n    plural: alertmanagers\n    singular: alertmanager\n  scope: Namespaced\n  versions:\n  - additionalPrinterColumns:\n    - description: The version of Alertmanager\n      jsonPath: .spec.version\n      name: Version\n      type: string\n    - description: The desired replicas number of Alertmanagers\n      jsonPath: .spec.replicas\n      name: Replicas\n      type: integer\n    - jsonPath: .metadata.creationTimestamp\n      name: Age\n      type: date\n    name: v1\n    schema:\n      openAPIV3Schema:\n        description: Alertmanager describes an Alertmanager cluster.\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: 'Specification of the desired behavior of the Alertmanager\n              cluster. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status'\n            properties:\n              additionalPeers:\n                description: AdditionalPeers allows injecting a set of additional\n                  Alertmanagers to peer with to form a highly available cluster.\n                items:\n                  type: string\n                type: array\n              affinity:\n                description: If specified, the pod's scheduling constraints.\n                properties:\n                  nodeAffinity:\n                    description: Describes node affinity scheduling rules for the\n                      pod.\n                    properties:\n                      preferredDuringSchedulingIgnoredDuringExecution:\n                        description: The scheduler will prefer to schedule pods to\n                          nodes that satisfy the affinity expressions specified by\n                          this field, but it may choose a node that violates one or\n                          more of the expressions. The node that is most preferred\n                          is the one with the greatest sum of weights, i.e. for each\n                          node that meets all of the scheduling requirements (resource\n                          request, requiredDuringScheduling affinity expressions,\n                          etc.), compute a sum by iterating through the elements of\n                          this field and adding \"weight\" to the sum if the node matches\n                          the corresponding matchExpressions; the node(s) with the\n                          highest sum are the most preferred.\n                        items:\n                          description: An empty preferred scheduling term matches\n                            all objects with implicit weight 0 (i.e. it's a no-op).\n                            A null preferred scheduling term matches no objects (i.e.\n                            is also a no-op).\n                          properties:\n                            preference:\n                              description: A node selector term, associated with the\n                                corresponding weight.\n                              properties:\n                                matchExpressions:\n                                  description: A list of node selector requirements\n                                    by node's labels.\n                                  items:\n                                    description: A node selector requirement is a\n                                      selector that contains values, a key, and an\n                                      operator that relates the key and values.\n                                    properties:\n                                      key:\n                                        description: The label key that the selector\n                                          applies to.\n                                        type: string\n                                      operator:\n                                        description: Represents a key's relationship\n                                          to a set of values. Valid operators are\n                                          In, NotIn, Exists, DoesNotExist. Gt, and\n                                          Lt.\n                                        type: string\n                                      values:\n                                        description: An array of string values. If\n                                          the operator is In or NotIn, the values\n                                          array must be non-empty. If the operator\n                                          is Exists or DoesNotExist, the values array\n                                          must be empty. If the operator is Gt or\n                                          Lt, the values array must have a single\n                                          element, which will be interpreted as an\n                                          integer. This array is replaced during a\n                                          strategic merge patch.\n                                        items:\n                                          type: string\n                                        type: array\n                                    required:\n                                    - key\n                                    - operator\n                                    type: object\n                                  type: array\n                                matchFields:\n                                  description: A list of node selector requirements\n                                    by node's fields.\n                                  items:\n                                    description: A node selector requirement is a\n                                      selector that contains values, a key, and an\n                                      operator that relates the key and values.\n                                    properties:\n                                      key:\n                                        description: The label key that the selector\n                                          applies to.\n                                        type: string\n                                      operator:\n                                        description: Represents a key's relationship\n                                          to a set of values. Valid operators are\n                                          In, NotIn, Exists, DoesNotExist. Gt, and\n                                          Lt.\n                                        type: string\n                                      values:\n                                        description: An array of string values. If\n                                          the operator is In or NotIn, the values\n                                          array must be non-empty. If the operator\n                                          is Exists or DoesNotExist, the values array\n                                          must be empty. If the operator is Gt or\n                                          Lt, the values array must have a single\n                                          element, which will be interpreted as an\n                                          integer. This array is replaced during a\n                                          strategic merge patch.\n                                        items:\n                                          type: string\n                                        type: array\n                                    required:\n                                    - key\n                                    - operator\n                                    type: object\n                                  type: array\n                              type: object\n                            weight:\n                              description: Weight associated with matching the corresponding\n                                nodeSelectorTerm, in the range 1-100.\n                              format: int32\n                              type: integer\n                          required:\n                          - preference\n                          - weight\n                          type: object\n                        type: array\n                      requiredDuringSchedulingIgnoredDuringExecution:\n                        description: If the affinity requirements specified by this\n                          field are not met at scheduling time, the pod will not be\n                          scheduled onto the node. If the affinity requirements specified\n                          by this field cease to be met at some point during pod execution\n                          (e.g. due to an update), the system may or may not try to\n                          eventually evict the pod from its node.\n                        properties:\n                          nodeSelectorTerms:\n                            description: Required. A list of node selector terms.\n                              The terms are ORed.\n                            items:\n                              description: A null or empty node selector term matches\n                                no objects. The requirements of them are ANDed. The\n                                TopologySelectorTerm type implements a subset of the\n                                NodeSelectorTerm.\n                              properties:\n                                matchExpressions:\n                                  description: A list of node selector requirements\n                                    by node's labels.\n                                  items:\n                                    description: A node selector requirement is a\n                                      selector that contains values, a key, and an\n                                      operator that relates the key and values.\n                                    properties:\n                                      key:\n                                        description: The label key that the selector\n                                          applies to.\n                                        type: string\n                                      operator:\n                                        description: Represents a key's relationship\n                                          to a set of values. Valid operators are\n                                          In, NotIn, Exists, DoesNotExist. Gt, and\n                                          Lt.\n                                        type: string\n                                      values:\n                                        description: An array of string values. If\n                                          the operator is In or NotIn, the values\n                                          array must be non-empty. If the operator\n                                          is Exists or DoesNotExist, the values array\n                                          must be empty. If the operator is Gt or\n                                          Lt, the values array must have a single\n                                          element, which will be interpreted as an\n                                          integer. This array is replaced during a\n                                          strategic merge patch.\n                                        items:\n                                          type: string\n                                        type: array\n                                    required:\n                                    - key\n                                    - operator\n                                    type: object\n                                  type: array\n                                matchFields:\n                                  description: A list of node selector requirements\n                                    by node's fields.\n                                  items:\n                                    description: A node selector requirement is a\n                                      selector that contains values, a key, and an\n                                      operator that relates the key and values.\n                                    properties:\n                                      key:\n                                        description: The label key that the selector\n                                          applies to.\n                                        type: string\n                                      operator:\n                                        description: Represents a key's relationship\n                                          to a set of values. Valid operators are\n                                          In, NotIn, Exists, DoesNotExist. Gt, and\n                                          Lt.\n                                        type: string\n                                      values:\n                                        description: An array of string values. If\n                                          the operator is In or NotIn, the values\n                                          array must be non-empty. If the operator\n                                          is Exists or DoesNotExist, the values array\n                                          must be empty. If the operator is Gt or\n                                          Lt, the values array must have a single\n                                          element, which will be interpreted as an\n                                          integer. This array is replaced during a\n                                          strategic merge patch.\n                                        items:\n                                          type: string\n                                        type: array\n                                    required:\n                                    - key\n                                    - operator\n                                    type: object\n                                  type: array\n                              type: object\n                            type: array\n                        required:\n                        - nodeSelectorTerms\n                        type: object\n                    type: object\n                  podAffinity:\n                    description: Describes pod affinity scheduling rules (e.g. co-locate\n                      this pod in the same node, zone, etc. as some other pod(s)).\n                    properties:\n                      preferredDuringSchedulingIgnoredDuringExecution:\n                        description: The scheduler will prefer to schedule pods to\n                          nodes that satisfy the affinity expressions specified by\n                          this field, but it may choose a node that violates one or\n                          more of the expressions. The node that is most preferred\n                          is the one with the greatest sum of weights, i.e. for each\n                          node that meets all of the scheduling requirements (resource\n                          request, requiredDuringScheduling affinity expressions,\n                          etc.), compute a sum by iterating through the elements of\n                          this field and adding \"weight\" to the sum if the node has\n                          pods which matches the corresponding podAffinityTerm; the\n                          node(s) with the highest sum are the most preferred.\n                        items:\n                          description: The weights of all of the matched WeightedPodAffinityTerm\n                            fields are added per-node to find the most preferred node(s)\n                          properties:\n                            podAffinityTerm:\n                              description: Required. A pod affinity term, associated\n                                with the corresponding weight.\n                              properties:\n                                labelSelector:\n                                  description: A label query over a set of resources,\n                                    in this case pods.\n                                  properties:\n                                    matchExpressions:\n                                      description: matchExpressions is a list of label\n                                        selector requirements. The requirements are\n                                        ANDed.\n                                      items:\n                                        description: A label selector requirement\n                                          is a selector that contains values, a key,\n                                          and an operator that relates the key and\n                                          values.\n                                        properties:\n                                          key:\n                                            description: key is the label key that\n                                              the selector applies to.\n                                            type: string\n                                          operator:\n                                            description: operator represents a key's\n                                              relationship to a set of values. Valid\n                                              operators are In, NotIn, Exists and\n                                              DoesNotExist.\n                                            type: string\n                                          values:\n                                            description: values is an array of string\n                                              values. If the operator is In or NotIn,\n                                              the values array must be non-empty.\n                                              If the operator is Exists or DoesNotExist,\n                                              the values array must be empty. This\n                                              array is replaced during a strategic\n                                              merge patch.\n                                            items:\n                                              type: string\n                                            type: array\n                                        required:\n                                        - key\n                                        - operator\n                                        type: object\n                                      type: array\n                                    matchLabels:\n                                      additionalProperties:\n                                        type: string\n                                      description: matchLabels is a map of {key,value}\n                                        pairs. A single {key,value} in the matchLabels\n                                        map is equivalent to an element of matchExpressions,\n                                        whose key field is \"key\", the operator is\n                                        \"In\", and the values array contains only \"value\".\n                                        The requirements are ANDed.\n                                      type: object\n                                  type: object\n                                namespaces:\n                                  description: namespaces specifies which namespaces\n                                    the labelSelector applies to (matches against);\n                                    null or empty list means \"this pod's namespace\"\n                                  items:\n                                    type: string\n                                  type: array\n                                topologyKey:\n                                  description: This pod should be co-located (affinity)\n                                    or not co-located (anti-affinity) with the pods\n                                    matching the labelSelector in the specified namespaces,\n                                    where co-located is defined as running on a node\n                                    whose value of the label with key topologyKey\n                                    matches that of any node on which any of the selected\n                                    pods is running. Empty topologyKey is not allowed.\n                                  type: string\n                              required:\n                              - topologyKey\n                              type: object\n                            weight:\n                              description: weight associated with matching the corresponding\n                                podAffinityTerm, in the range 1-100.\n                              format: int32\n                              type: integer\n                          required:\n                          - podAffinityTerm\n                          - weight\n                          type: object\n                        type: array\n                      requiredDuringSchedulingIgnoredDuringExecution:\n                        description: If the affinity requirements specified by this\n                          field are not met at scheduling time, the pod will not be\n                          scheduled onto the node. If the affinity requirements specified\n                          by this field cease to be met at some point during pod execution\n                          (e.g. due to a pod label update), the system may or may\n                          not try to eventually evict the pod from its node. When\n                          there are multiple elements, the lists of nodes corresponding\n                          to each podAffinityTerm are intersected, i.e. all terms\n                          must be satisfied.\n                        items:\n                          description: Defines a set of pods (namely those matching\n                            the labelSelector relative to the given namespace(s))\n                            that this pod should be co-located (affinity) or not co-located\n                            (anti-affinity) with, where co-located is defined as running\n                            on a node whose value of the label with key <topologyKey>\n                            matches that of any node on which a pod of the set of\n                            pods is running\n                          properties:\n                            labelSelector:\n                              description: A label query over a set of resources,\n                                in this case pods.\n                              properties:\n                                matchExpressions:\n                                  description: matchExpressions is a list of label\n                                    selector requirements. The requirements are ANDed.\n                                  items:\n                                    description: A label selector requirement is a\n                                      selector that contains values, a key, and an\n                                      operator that relates the key and values.\n                                    properties:\n                                      key:\n                                        description: key is the label key that the\n                                          selector applies to.\n                                        type: string\n                                      operator:\n                                        description: operator represents a key's relationship\n                                          to a set of values. Valid operators are\n                                          In, NotIn, Exists and DoesNotExist.\n                                        type: string\n                                      values:\n                                        description: values is an array of string\n                                          values. If the operator is In or NotIn,\n                                          the values array must be non-empty. If the\n                                          operator is Exists or DoesNotExist, the\n                                          values array must be empty. This array is\n                                          replaced during a strategic merge patch.\n                                        items:\n                                          type: string\n                                        type: array\n                                    required:\n                                    - key\n                                    - operator\n                                    type: object\n                                  type: array\n                                matchLabels:\n                                  additionalProperties:\n                                    type: string\n                                  description: matchLabels is a map of {key,value}\n                                    pairs. A single {key,value} in the matchLabels\n                                    map is equivalent to an element of matchExpressions,\n                                    whose key field is \"key\", the operator is \"In\",\n                                    and the values array contains only \"value\". The\n                                    requirements are ANDed.\n                                  type: object\n                              type: object\n                            namespaces:\n                              description: namespaces specifies which namespaces the\n                                labelSelector applies to (matches against); null or\n                                empty list means \"this pod's namespace\"\n                              items:\n                                type: string\n                              type: array\n                            topologyKey:\n                              description: This pod should be co-located (affinity)\n                                or not co-located (anti-affinity) with the pods matching\n                                the labelSelector in the specified namespaces, where\n                                co-located is defined as running on a node whose value\n                                of the label with key topologyKey matches that of\n                                any node on which any of the selected pods is running.\n                                Empty topologyKey is not allowed.\n                              type: string\n                          required:\n                          - topologyKey\n                          type: object\n                        type: array\n                    type: object\n                  podAntiAffinity:\n                    description: Describes pod anti-affinity scheduling rules (e.g.\n                      avoid putting this pod in the same node, zone, etc. as some\n                      other pod(s)).\n                    properties:\n                      preferredDuringSchedulingIgnoredDuringExecution:\n                        description: The scheduler will prefer to schedule pods to\n                          nodes that satisfy the anti-affinity expressions specified\n                          by this field, but it may choose a node that violates one\n                          or more of the expressions. The node that is most preferred\n                          is the one with the greatest sum of weights, i.e. for each\n                          node that meets all of the scheduling requirements (resource\n                          request, requiredDuringScheduling anti-affinity expressions,\n                          etc.), compute a sum by iterating through the elements of\n                          this field and adding \"weight\" to the sum if the node has\n                          pods which matches the corresponding podAffinityTerm; the\n                          node(s) with the highest sum are the most preferred.\n                        items:\n                          description: The weights of all of the matched WeightedPodAffinityTerm\n                            fields are added per-node to find the most preferred node(s)\n                          properties:\n                            podAffinityTerm:\n                              description: Required. A pod affinity term, associated\n                                with the corresponding weight.\n                              properties:\n                                labelSelector:\n                                  description: A label query over a set of resources,\n                                    in this case pods.\n                                  properties:\n                                    matchExpressions:\n                                      description: matchExpressions is a list of label\n                                        selector requirements. The requirements are\n                                        ANDed.\n                                      items:\n                                        description: A label selector requirement\n                                          is a selector that contains values, a key,\n                                          and an operator that relates the key and\n                                          values.\n                                        properties:\n                                          key:\n                                            description: key is the label key that\n                                              the selector applies to.\n                                            type: string\n                                          operator:\n                                            description: operator represents a key's\n                                              relationship to a set of values. Valid\n                                              operators are In, NotIn, Exists and\n                                              DoesNotExist.\n                                            type: string\n                                          values:\n                                            description: values is an array of string\n                                              values. If the operator is In or NotIn,\n                                              the values array must be non-empty.\n                                              If the operator is Exists or DoesNotExist,\n                                              the values array must be empty. This\n                                              array is replaced during a strategic\n                                              merge patch.\n                                            items:\n                                              type: string\n                                            type: array\n                                        required:\n                                        - key\n                                        - operator\n                                        type: object\n                                      type: array\n                                    matchLabels:\n                                      additionalProperties:\n                                        type: string\n                                      description: matchLabels is a map of {key,value}\n                                        pairs. A single {key,value} in the matchLabels\n                                        map is equivalent to an element of matchExpressions,\n                                        whose key field is \"key\", the operator is\n                                        \"In\", and the values array contains only \"value\".\n                                        The requirements are ANDed.\n                                      type: object\n                                  type: object\n                                namespaces:\n                                  description: namespaces specifies which namespaces\n                                    the labelSelector applies to (matches against);\n                                    null or empty list means \"this pod's namespace\"\n                                  items:\n                                    type: string\n                                  type: array\n                                topologyKey:\n                                  description: This pod should be co-located (affinity)\n                                    or not co-located (anti-affinity) with the pods\n                                    matching the labelSelector in the specified namespaces,\n                                    where co-located is defined as running on a node\n                                    whose value of the label with key topologyKey\n                                    matches that of any node on which any of the selected\n                                    pods is running. Empty topologyKey is not allowed.\n                                  type: string\n                              required:\n                              - topologyKey\n                              type: object\n                            weight:\n                              description: weight associated with matching the corresponding\n                                podAffinityTerm, in the range 1-100.\n                              format: int32\n                              type: integer\n                          required:\n                          - podAffinityTerm\n                          - weight\n                          type: object\n                        type: array\n                      requiredDuringSchedulingIgnoredDuringExecution:\n                        description: If the anti-affinity requirements specified by\n                          this field are not met at scheduling time, the pod will\n                          not be scheduled onto the node. If the anti-affinity requirements\n                          specified by this field cease to be met at some point during\n                          pod execution (e.g. due to a pod label update), the system\n                          may or may not try to eventually evict the pod from its\n                          node. When there are multiple elements, the lists of nodes\n                          corresponding to each podAffinityTerm are intersected, i.e.\n                          all terms must be satisfied.\n                        items:\n                          description: Defines a set of pods (namely those matching\n                            the labelSelector relative to the given namespace(s))\n                            that this pod should be co-located (affinity) or not co-located\n                            (anti-affinity) with, where co-located is defined as running\n                            on a node whose value of the label with key <topologyKey>\n                            matches that of any node on which a pod of the set of\n                            pods is running\n                          properties:\n                            labelSelector:\n                              description: A label query over a set of resources,\n                                in this case pods.\n                              properties:\n                                matchExpressions:\n                                  description: matchExpressions is a list of label\n                                    selector requirements. The requirements are ANDed.\n                                  items:\n                                    description: A label selector requirement is a\n                                      selector that contains values, a key, and an\n                                      operator that relates the key and values.\n                                    properties:\n                                      key:\n                                        description: key is the label key that the\n                                          selector applies to.\n                                        type: string\n                                      operator:\n                                        description: operator represents a key's relationship\n                                          to a set of values. Valid operators are\n                                          In, NotIn, Exists and DoesNotExist.\n                                        type: string\n                                      values:\n                                        description: values is an array of string\n                                          values. If the operator is In or NotIn,\n                                          the values array must be non-empty. If the\n                                          operator is Exists or DoesNotExist, the\n                                          values array must be empty. This array is\n                                          replaced during a strategic merge patch.\n                                        items:\n                                          type: string\n                                        type: array\n                                    required:\n                                    - key\n                                    - operator\n                                    type: object\n                                  type: array\n                                matchLabels:\n                                  additionalProperties:\n                                    type: string\n                                  description: matchLabels is a map of {key,value}\n                                    pairs. A single {key,value} in the matchLabels\n                                    map is equivalent to an element of matchExpressions,\n                                    whose key field is \"key\", the operator is \"In\",\n                                    and the values array contains only \"value\". The\n                                    requirements are ANDed.\n                                  type: object\n                              type: object\n                            namespaces:\n                              description: namespaces specifies which namespaces the\n                                labelSelector applies to (matches against); null or\n                                empty list means \"this pod's namespace\"\n                              items:\n                                type: string\n                              type: array\n                            topologyKey:\n                              description: This pod should be co-located (affinity)\n                                or not co-located (anti-affinity) with the pods matching\n                                the labelSelector in the specified namespaces, where\n                                co-located is defined as running on a node whose value\n                                of the label with key topologyKey matches that of\n                                any node on which any of the selected pods is running.\n                                Empty topologyKey is not allowed.\n                              type: string\n                          required:\n                          - topologyKey\n                          type: object\n                        type: array\n                    type: object\n                type: object\n              alertmanagerConfigNamespaceSelector:\n                description: Namespaces to be selected for AlertmanagerConfig discovery.\n                  If nil, only check own namespace.\n                properties:\n                  matchExpressions:\n                    description: matchExpressions is a list of label selector requirements.\n                      The requirements are ANDed.\n                    items:\n                      description: A label selector requirement is a selector that\n                        contains values, a key, and an operator that relates the key\n                        and values.\n                      properties:\n                        key:\n                          description: key is the label key that the selector applies\n                            to.\n                          type: string\n                        operator:\n                          description: operator represents a key's relationship to\n                            a set of values. Valid operators are In, NotIn, Exists\n                            and DoesNotExist.\n                          type: string\n                        values:\n                          description: values is an array of string values. If the\n                            operator is In or NotIn, the values array must be non-empty.\n                            If the operator is Exists or DoesNotExist, the values\n                            array must be empty. This array is replaced during a strategic\n                            merge patch.\n                          items:\n                            type: string\n                          type: array\n                      required:\n                      - key\n                      - operator\n                      type: object\n                    type: array\n                  matchLabels:\n                    additionalProperties:\n                      type: string\n                    description: matchLabels is a map of {key,value} pairs. A single\n                      {key,value} in the matchLabels map is equivalent to an element\n                      of matchExpressions, whose key field is \"key\", the operator\n                      is \"In\", and the values array contains only \"value\". The requirements\n                      are ANDed.\n                    type: object\n                type: object\n              alertmanagerConfigSelector:\n                description: AlertmanagerConfigs to be selected for to merge and configure\n                  Alertmanager with.\n                properties:\n                  matchExpressions:\n                    description: matchExpressions is a list of label selector requirements.\n                      The requirements are ANDed.\n                    items:\n                      description: A label selector requirement is a selector that\n                        contains values, a key, and an operator that relates the key\n                        and values.\n                      properties:\n                        key:\n                          description: key is the label key that the selector applies\n                            to.\n                          type: string\n                        operator:\n                          description: operator represents a key's relationship to\n                            a set of values. Valid operators are In, NotIn, Exists\n                            and DoesNotExist.\n                          type: string\n                        values:\n                          description: values is an array of string values. If the\n                            operator is In or NotIn, the values array must be non-empty.\n                            If the operator is Exists or DoesNotExist, the values\n                            array must be empty. This array is replaced during a strategic\n                            merge patch.\n                          items:\n                            type: string\n                          type: array\n                      required:\n                      - key\n                      - operator\n                      type: object\n                    type: array\n                  matchLabels:\n                    additionalProperties:\n                      type: string\n                    description: matchLabels is a map of {key,value} pairs. A single\n                      {key,value} in the matchLabels map is equivalent to an element\n                      of matchExpressions, whose key field is \"key\", the operator\n                      is \"In\", and the values array contains only \"value\". The requirements\n                      are ANDed.\n                    type: object\n                type: object\n              baseImage:\n                description: 'Base image that is used to deploy pods, without tag.\n                  Deprecated: use ''image'' instead'\n                type: string\n              clusterAdvertiseAddress:\n                description: 'ClusterAdvertiseAddress is the explicit address to advertise\n                  in cluster. Needs to be provided for non RFC1918 [1] (public) addresses.\n                  [1] RFC1918: https://tools.ietf.org/html/rfc1918'\n                type: string\n              clusterGossipInterval:\n                description: Interval between gossip attempts.\n                type: string\n              clusterPeerTimeout:\n                description: Timeout for cluster peering.\n                type: string\n              clusterPushpullInterval:\n                description: Interval between pushpull attempts.\n                type: string\n              configMaps:\n                description: ConfigMaps is a list of ConfigMaps in the same namespace\n                  as the Alertmanager object, which shall be mounted into the Alertmanager\n                  Pods. The ConfigMaps are mounted into /etc/alertmanager/configmaps/<configmap-name>.\n                items:\n                  type: string\n                type: array\n              configSecret:\n                description: ConfigSecret is the name of a Kubernetes Secret in the\n                  same namespace as the Alertmanager object, which contains configuration\n                  for this Alertmanager instance. Defaults to 'alertmanager-<alertmanager-name>'\n                  The secret is mounted into /etc/alertmanager/config.\n                type: string\n              containers:\n                description: 'Containers allows injecting additional containers. This\n                  is meant to allow adding an authentication proxy to an Alertmanager\n                  pod. Containers described here modify an operator generated container\n                  if they share the same name and modifications are done via a strategic\n                  merge patch. The current container names are: `alertmanager` and\n                  `config-reloader`. Overriding containers is entirely outside the\n                  scope of what the maintainers will support and by doing so, you\n                  accept that this behaviour may break at any time without notice.'\n                items:\n                  description: A single application container that you want to run\n                    within a pod.\n                  properties:\n                    args:\n                      description: 'Arguments to the entrypoint. The docker image''s\n                        CMD is used if this is not provided. Variable references $(VAR_NAME)\n                        are expanded using the container''s environment. If a variable\n                        cannot be resolved, the reference in the input string will\n                        be unchanged. The $(VAR_NAME) syntax can be escaped with a\n                        double $$, ie: $$(VAR_NAME). Escaped references will never\n                        be expanded, regardless of whether the variable exists or\n                        not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell'\n                      items:\n                        type: string\n                      type: array\n                    command:\n                      description: 'Entrypoint array. Not executed within a shell.\n                        The docker image''s ENTRYPOINT is used if this is not provided.\n                        Variable references $(VAR_NAME) are expanded using the container''s\n                        environment. If a variable cannot be resolved, the reference\n                        in the input string will be unchanged. The $(VAR_NAME) syntax\n                        can be escaped with a double $$, ie: $$(VAR_NAME). Escaped\n                        references will never be expanded, regardless of whether the\n                        variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell'\n                      items:\n                        type: string\n                      type: array\n                    env:\n                      description: List of environment variables to set in the container.\n                        Cannot be updated.\n                      items:\n                        description: EnvVar represents an environment variable present\n                          in a Container.\n                        properties:\n                          name:\n                            description: Name of the environment variable. Must be\n                              a C_IDENTIFIER.\n                            type: string\n                          value:\n                            description: 'Variable references $(VAR_NAME) are expanded\n                              using the previous defined environment variables in\n                              the container and any service environment variables.\n                              If a variable cannot be resolved, the reference in the\n                              input string will be unchanged. The $(VAR_NAME) syntax\n                              can be escaped with a double $$, ie: $$(VAR_NAME). Escaped\n                              references will never be expanded, regardless of whether\n                              the variable exists or not. Defaults to \"\".'\n                            type: string\n                          valueFrom:\n                            description: Source for the environment variable's value.\n                              Cannot be used if value is not empty.\n                            properties:\n                              configMapKeyRef:\n                                description: Selects a key of a ConfigMap.\n                                properties:\n                                  key:\n                                    description: The key to select.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the ConfigMap or\n                                      its key must be defined\n                                    type: boolean\n                                required:\n                                - key\n                                type: object\n                              fieldRef:\n                                description: 'Selects a field of the pod: supports\n                                  metadata.name, metadata.namespace, metadata.labels,\n                                  metadata.annotations, spec.nodeName, spec.serviceAccountName,\n                                  status.hostIP, status.podIP, status.podIPs.'\n                                properties:\n                                  apiVersion:\n                                    description: Version of the schema the FieldPath\n                                      is written in terms of, defaults to \"v1\".\n                                    type: string\n                                  fieldPath:\n                                    description: Path of the field to select in the\n                                      specified API version.\n                                    type: string\n                                required:\n                                - fieldPath\n                                type: object\n                              resourceFieldRef:\n                                description: 'Selects a resource of the container:\n                                  only resources limits and requests (limits.cpu,\n                                  limits.memory, limits.ephemeral-storage, requests.cpu,\n                                  requests.memory and requests.ephemeral-storage)\n                                  are currently supported.'\n                                properties:\n                                  containerName:\n                                    description: 'Container name: required for volumes,\n                                      optional for env vars'\n                                    type: string\n                                  divisor:\n                                    anyOf:\n                                    - type: integer\n                                    - type: string\n                                    description: Specifies the output format of the\n                                      exposed resources, defaults to \"1\"\n                                    pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                    x-kubernetes-int-or-string: true\n                                  resource:\n                                    description: 'Required: resource to select'\n                                    type: string\n                                required:\n                                - resource\n                                type: object\n                              secretKeyRef:\n                                description: Selects a key of a secret in the pod's\n                                  namespace\n                                properties:\n                                  key:\n                                    description: The key of the secret to select from.  Must\n                                      be a valid secret key.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the Secret or its\n                                      key must be defined\n                                    type: boolean\n                                required:\n                                - key\n                                type: object\n                            type: object\n                        required:\n                        - name\n                        type: object\n                      type: array\n                    envFrom:\n                      description: List of sources to populate environment variables\n                        in the container. The keys defined within a source must be\n                        a C_IDENTIFIER. All invalid keys will be reported as an event\n                        when the container is starting. When a key exists in multiple\n                        sources, the value associated with the last source will take\n                        precedence. Values defined by an Env with a duplicate key\n                        will take precedence. Cannot be updated.\n                      items:\n                        description: EnvFromSource represents the source of a set\n                          of ConfigMaps\n                        properties:\n                          configMapRef:\n                            description: The ConfigMap to select from\n                            properties:\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the ConfigMap must be\n                                  defined\n                                type: boolean\n                            type: object\n                          prefix:\n                            description: An optional identifier to prepend to each\n                              key in the ConfigMap. Must be a C_IDENTIFIER.\n                            type: string\n                          secretRef:\n                            description: The Secret to select from\n                            properties:\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret must be defined\n                                type: boolean\n                            type: object\n                        type: object\n                      type: array\n                    image:\n                      description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images\n                        This field is optional to allow higher level config management\n                        to default or override container images in workload controllers\n                        like Deployments and StatefulSets.'\n                      type: string\n                    imagePullPolicy:\n                      description: 'Image pull policy. One of Always, Never, IfNotPresent.\n                        Defaults to Always if :latest tag is specified, or IfNotPresent\n                        otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images'\n                      type: string\n                    lifecycle:\n                      description: Actions that the management system should take\n                        in response to container lifecycle events. Cannot be updated.\n                      properties:\n                        postStart:\n                          description: 'PostStart is called immediately after a container\n                            is created. If the handler fails, the container is terminated\n                            and restarted according to its restart policy. Other management\n                            of the container blocks until the hook completes. More\n                            info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks'\n                          properties:\n                            exec:\n                              description: One and only one of the following should\n                                be specified. Exec specifies the action to take.\n                              properties:\n                                command:\n                                  description: Command is the command line to execute\n                                    inside the container, the working directory for\n                                    the command  is root ('/') in the container's\n                                    filesystem. The command is simply exec'd, it is\n                                    not run inside a shell, so traditional shell instructions\n                                    ('|', etc) won't work. To use a shell, you need\n                                    to explicitly call out to that shell. Exit status\n                                    of 0 is treated as live/healthy and non-zero is\n                                    unhealthy.\n                                  items:\n                                    type: string\n                                  type: array\n                              type: object\n                            httpGet:\n                              description: HTTPGet specifies the http request to perform.\n                              properties:\n                                host:\n                                  description: Host name to connect to, defaults to\n                                    the pod IP. You probably want to set \"Host\" in\n                                    httpHeaders instead.\n                                  type: string\n                                httpHeaders:\n                                  description: Custom headers to set in the request.\n                                    HTTP allows repeated headers.\n                                  items:\n                                    description: HTTPHeader describes a custom header\n                                      to be used in HTTP probes\n                                    properties:\n                                      name:\n                                        description: The header field name\n                                        type: string\n                                      value:\n                                        description: The header field value\n                                        type: string\n                                    required:\n                                    - name\n                                    - value\n                                    type: object\n                                  type: array\n                                path:\n                                  description: Path to access on the HTTP server.\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Name or number of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                                scheme:\n                                  description: Scheme to use for connecting to the\n                                    host. Defaults to HTTP.\n                                  type: string\n                              required:\n                              - port\n                              type: object\n                            tcpSocket:\n                              description: 'TCPSocket specifies an action involving\n                                a TCP port. TCP hooks not yet supported TODO: implement\n                                a realistic TCP lifecycle hook'\n                              properties:\n                                host:\n                                  description: 'Optional: Host name to connect to,\n                                    defaults to the pod IP.'\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Number or name of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                              required:\n                              - port\n                              type: object\n                          type: object\n                        preStop:\n                          description: 'PreStop is called immediately before a container\n                            is terminated due to an API request or management event\n                            such as liveness/startup probe failure, preemption, resource\n                            contention, etc. The handler is not called if the container\n                            crashes or exits. The reason for termination is passed\n                            to the handler. The Pod''s termination grace period countdown\n                            begins before the PreStop hooked is executed. Regardless\n                            of the outcome of the handler, the container will eventually\n                            terminate within the Pod''s termination grace period.\n                            Other management of the container blocks until the hook\n                            completes or until the termination grace period is reached.\n                            More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks'\n                          properties:\n                            exec:\n                              description: One and only one of the following should\n                                be specified. Exec specifies the action to take.\n                              properties:\n                                command:\n                                  description: Command is the command line to execute\n                                    inside the container, the working directory for\n                                    the command  is root ('/') in the container's\n                                    filesystem. The command is simply exec'd, it is\n                                    not run inside a shell, so traditional shell instructions\n                                    ('|', etc) won't work. To use a shell, you need\n                                    to explicitly call out to that shell. Exit status\n                                    of 0 is treated as live/healthy and non-zero is\n                                    unhealthy.\n                                  items:\n                                    type: string\n                                  type: array\n                              type: object\n                            httpGet:\n                              description: HTTPGet specifies the http request to perform.\n                              properties:\n                                host:\n                                  description: Host name to connect to, defaults to\n                                    the pod IP. You probably want to set \"Host\" in\n                                    httpHeaders instead.\n                                  type: string\n                                httpHeaders:\n                                  description: Custom headers to set in the request.\n                                    HTTP allows repeated headers.\n                                  items:\n                                    description: HTTPHeader describes a custom header\n                                      to be used in HTTP probes\n                                    properties:\n                                      name:\n                                        description: The header field name\n                                        type: string\n                                      value:\n                                        description: The header field value\n                                        type: string\n                                    required:\n                                    - name\n                                    - value\n                                    type: object\n                                  type: array\n                                path:\n                                  description: Path to access on the HTTP server.\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Name or number of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                                scheme:\n                                  description: Scheme to use for connecting to the\n                                    host. Defaults to HTTP.\n                                  type: string\n                              required:\n                              - port\n                              type: object\n                            tcpSocket:\n                              description: 'TCPSocket specifies an action involving\n                                a TCP port. TCP hooks not yet supported TODO: implement\n                                a realistic TCP lifecycle hook'\n                              properties:\n                                host:\n                                  description: 'Optional: Host name to connect to,\n                                    defaults to the pod IP.'\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Number or name of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                              required:\n                              - port\n                              type: object\n                          type: object\n                      type: object\n                    livenessProbe:\n                      description: 'Periodic probe of container liveness. Container\n                        will be restarted if the probe fails. Cannot be updated. More\n                        info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                      properties:\n                        exec:\n                          description: One and only one of the following should be\n                            specified. Exec specifies the action to take.\n                          properties:\n                            command:\n                              description: Command is the command line to execute\n                                inside the container, the working directory for the\n                                command  is root ('/') in the container's filesystem.\n                                The command is simply exec'd, it is not run inside\n                                a shell, so traditional shell instructions ('|', etc)\n                                won't work. To use a shell, you need to explicitly\n                                call out to that shell. Exit status of 0 is treated\n                                as live/healthy and non-zero is unhealthy.\n                              items:\n                                type: string\n                              type: array\n                          type: object\n                        failureThreshold:\n                          description: Minimum consecutive failures for the probe\n                            to be considered failed after having succeeded. Defaults\n                            to 3. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        httpGet:\n                          description: HTTPGet specifies the http request to perform.\n                          properties:\n                            host:\n                              description: Host name to connect to, defaults to the\n                                pod IP. You probably want to set \"Host\" in httpHeaders\n                                instead.\n                              type: string\n                            httpHeaders:\n                              description: Custom headers to set in the request. HTTP\n                                allows repeated headers.\n                              items:\n                                description: HTTPHeader describes a custom header\n                                  to be used in HTTP probes\n                                properties:\n                                  name:\n                                    description: The header field name\n                                    type: string\n                                  value:\n                                    description: The header field value\n                                    type: string\n                                required:\n                                - name\n                                - value\n                                type: object\n                              type: array\n                            path:\n                              description: Path to access on the HTTP server.\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Name or number of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                            scheme:\n                              description: Scheme to use for connecting to the host.\n                                Defaults to HTTP.\n                              type: string\n                          required:\n                          - port\n                          type: object\n                        initialDelaySeconds:\n                          description: 'Number of seconds after the container has\n                            started before liveness probes are initiated. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                        periodSeconds:\n                          description: How often (in seconds) to perform the probe.\n                            Default to 10 seconds. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        successThreshold:\n                          description: Minimum consecutive successes for the probe\n                            to be considered successful after having failed. Defaults\n                            to 1. Must be 1 for liveness and startup. Minimum value\n                            is 1.\n                          format: int32\n                          type: integer\n                        tcpSocket:\n                          description: 'TCPSocket specifies an action involving a\n                            TCP port. TCP hooks not yet supported TODO: implement\n                            a realistic TCP lifecycle hook'\n                          properties:\n                            host:\n                              description: 'Optional: Host name to connect to, defaults\n                                to the pod IP.'\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Number or name of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                          required:\n                          - port\n                          type: object\n                        timeoutSeconds:\n                          description: 'Number of seconds after which the probe times\n                            out. Defaults to 1 second. Minimum value is 1. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                      type: object\n                    name:\n                      description: Name of the container specified as a DNS_LABEL.\n                        Each container in a pod must have a unique name (DNS_LABEL).\n                        Cannot be updated.\n                      type: string\n                    ports:\n                      description: List of ports to expose from the container. Exposing\n                        a port here gives the system additional information about\n                        the network connections a container uses, but is primarily\n                        informational. Not specifying a port here DOES NOT prevent\n                        that port from being exposed. Any port which is listening\n                        on the default \"0.0.0.0\" address inside a container will be\n                        accessible from the network. Cannot be updated.\n                      items:\n                        description: ContainerPort represents a network port in a\n                          single container.\n                        properties:\n                          containerPort:\n                            description: Number of port to expose on the pod's IP\n                              address. This must be a valid port number, 0 < x < 65536.\n                            format: int32\n                            type: integer\n                          hostIP:\n                            description: What host IP to bind the external port to.\n                            type: string\n                          hostPort:\n                            description: Number of port to expose on the host. If\n                              specified, this must be a valid port number, 0 < x <\n                              65536. If HostNetwork is specified, this must match\n                              ContainerPort. Most containers do not need this.\n                            format: int32\n                            type: integer\n                          name:\n                            description: If specified, this must be an IANA_SVC_NAME\n                              and unique within the pod. Each named port in a pod\n                              must have a unique name. Name for the port that can\n                              be referred to by services.\n                            type: string\n                          protocol:\n                            default: TCP\n                            description: Protocol for port. Must be UDP, TCP, or SCTP.\n                              Defaults to \"TCP\".\n                            type: string\n                        required:\n                        - containerPort\n                        type: object\n                      type: array\n                      x-kubernetes-list-map-keys:\n                      - containerPort\n                      - protocol\n                      x-kubernetes-list-type: map\n                    readinessProbe:\n                      description: 'Periodic probe of container service readiness.\n                        Container will be removed from service endpoints if the probe\n                        fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                      properties:\n                        exec:\n                          description: One and only one of the following should be\n                            specified. Exec specifies the action to take.\n                          properties:\n                            command:\n                              description: Command is the command line to execute\n                                inside the container, the working directory for the\n                                command  is root ('/') in the container's filesystem.\n                                The command is simply exec'd, it is not run inside\n                                a shell, so traditional shell instructions ('|', etc)\n                                won't work. To use a shell, you need to explicitly\n                                call out to that shell. Exit status of 0 is treated\n                                as live/healthy and non-zero is unhealthy.\n                              items:\n                                type: string\n                              type: array\n                          type: object\n                        failureThreshold:\n                          description: Minimum consecutive failures for the probe\n                            to be considered failed after having succeeded. Defaults\n                            to 3. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        httpGet:\n                          description: HTTPGet specifies the http request to perform.\n                          properties:\n                            host:\n                              description: Host name to connect to, defaults to the\n                                pod IP. You probably want to set \"Host\" in httpHeaders\n                                instead.\n                              type: string\n                            httpHeaders:\n                              description: Custom headers to set in the request. HTTP\n                                allows repeated headers.\n                              items:\n                                description: HTTPHeader describes a custom header\n                                  to be used in HTTP probes\n                                properties:\n                                  name:\n                                    description: The header field name\n                                    type: string\n                                  value:\n                                    description: The header field value\n                                    type: string\n                                required:\n                                - name\n                                - value\n                                type: object\n                              type: array\n                            path:\n                              description: Path to access on the HTTP server.\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Name or number of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                            scheme:\n                              description: Scheme to use for connecting to the host.\n                                Defaults to HTTP.\n                              type: string\n                          required:\n                          - port\n                          type: object\n                        initialDelaySeconds:\n                          description: 'Number of seconds after the container has\n                            started before liveness probes are initiated. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                        periodSeconds:\n                          description: How often (in seconds) to perform the probe.\n                            Default to 10 seconds. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        successThreshold:\n                          description: Minimum consecutive successes for the probe\n                            to be considered successful after having failed. Defaults\n                            to 1. Must be 1 for liveness and startup. Minimum value\n                            is 1.\n                          format: int32\n                          type: integer\n                        tcpSocket:\n                          description: 'TCPSocket specifies an action involving a\n                            TCP port. TCP hooks not yet supported TODO: implement\n                            a realistic TCP lifecycle hook'\n                          properties:\n                            host:\n                              description: 'Optional: Host name to connect to, defaults\n                                to the pod IP.'\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Number or name of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                          required:\n                          - port\n                          type: object\n                        timeoutSeconds:\n                          description: 'Number of seconds after which the probe times\n                            out. Defaults to 1 second. Minimum value is 1. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                      type: object\n                    resources:\n                      description: 'Compute Resources required by this container.\n                        Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                      properties:\n                        limits:\n                          additionalProperties:\n                            anyOf:\n                            - type: integer\n                            - type: string\n                            pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                            x-kubernetes-int-or-string: true\n                          description: 'Limits describes the maximum amount of compute\n                            resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                          type: object\n                        requests:\n                          additionalProperties:\n                            anyOf:\n                            - type: integer\n                            - type: string\n                            pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                            x-kubernetes-int-or-string: true\n                          description: 'Requests describes the minimum amount of compute\n                            resources required. If Requests is omitted for a container,\n                            it defaults to Limits if that is explicitly specified,\n                            otherwise to an implementation-defined value. More info:\n                            https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                          type: object\n                      type: object\n                    securityContext:\n                      description: 'Security options the pod should run with. More\n                        info: https://kubernetes.io/docs/concepts/policy/security-context/\n                        More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/'\n                      properties:\n                        allowPrivilegeEscalation:\n                          description: 'AllowPrivilegeEscalation controls whether\n                            a process can gain more privileges than its parent process.\n                            This bool directly controls if the no_new_privs flag will\n                            be set on the container process. AllowPrivilegeEscalation\n                            is true always when the container is: 1) run as Privileged\n                            2) has CAP_SYS_ADMIN'\n                          type: boolean\n                        capabilities:\n                          description: The capabilities to add/drop when running containers.\n                            Defaults to the default set of capabilities granted by\n                            the container runtime.\n                          properties:\n                            add:\n                              description: Added capabilities\n                              items:\n                                description: Capability represent POSIX capabilities\n                                  type\n                                type: string\n                              type: array\n                            drop:\n                              description: Removed capabilities\n                              items:\n                                description: Capability represent POSIX capabilities\n                                  type\n                                type: string\n                              type: array\n                          type: object\n                        privileged:\n                          description: Run container in privileged mode. Processes\n                            in privileged containers are essentially equivalent to\n                            root on the host. Defaults to false.\n                          type: boolean\n                        procMount:\n                          description: procMount denotes the type of proc mount to\n                            use for the containers. The default is DefaultProcMount\n                            which uses the container runtime defaults for readonly\n                            paths and masked paths. This requires the ProcMountType\n                            feature flag to be enabled.\n                          type: string\n                        readOnlyRootFilesystem:\n                          description: Whether this container has a read-only root\n                            filesystem. Default is false.\n                          type: boolean\n                        runAsGroup:\n                          description: The GID to run the entrypoint of the container\n                            process. Uses runtime default if unset. May also be set\n                            in PodSecurityContext.  If set in both SecurityContext\n                            and PodSecurityContext, the value specified in SecurityContext\n                            takes precedence.\n                          format: int64\n                          type: integer\n                        runAsNonRoot:\n                          description: Indicates that the container must run as a\n                            non-root user. If true, the Kubelet will validate the\n                            image at runtime to ensure that it does not run as UID\n                            0 (root) and fail to start the container if it does. If\n                            unset or false, no such validation will be performed.\n                            May also be set in PodSecurityContext.  If set in both\n                            SecurityContext and PodSecurityContext, the value specified\n                            in SecurityContext takes precedence.\n                          type: boolean\n                        runAsUser:\n                          description: The UID to run the entrypoint of the container\n                            process. Defaults to user specified in image metadata\n                            if unspecified. May also be set in PodSecurityContext.  If\n                            set in both SecurityContext and PodSecurityContext, the\n                            value specified in SecurityContext takes precedence.\n                          format: int64\n                          type: integer\n                        seLinuxOptions:\n                          description: The SELinux context to be applied to the container.\n                            If unspecified, the container runtime will allocate a\n                            random SELinux context for each container.  May also be\n                            set in PodSecurityContext.  If set in both SecurityContext\n                            and PodSecurityContext, the value specified in SecurityContext\n                            takes precedence.\n                          properties:\n                            level:\n                              description: Level is SELinux level label that applies\n                                to the container.\n                              type: string\n                            role:\n                              description: Role is a SELinux role label that applies\n                                to the container.\n                              type: string\n                            type:\n                              description: Type is a SELinux type label that applies\n                                to the container.\n                              type: string\n                            user:\n                              description: User is a SELinux user label that applies\n                                to the container.\n                              type: string\n                          type: object\n                        windowsOptions:\n                          description: The Windows specific settings applied to all\n                            containers. If unspecified, the options from the PodSecurityContext\n                            will be used. If set in both SecurityContext and PodSecurityContext,\n                            the value specified in SecurityContext takes precedence.\n                          properties:\n                            gmsaCredentialSpec:\n                              description: GMSACredentialSpec is where the GMSA admission\n                                webhook (https://github.com/kubernetes-sigs/windows-gmsa)\n                                inlines the contents of the GMSA credential spec named\n                                by the GMSACredentialSpecName field.\n                              type: string\n                            gmsaCredentialSpecName:\n                              description: GMSACredentialSpecName is the name of the\n                                GMSA credential spec to use.\n                              type: string\n                            runAsUserName:\n                              description: The UserName in Windows to run the entrypoint\n                                of the container process. Defaults to the user specified\n                                in image metadata if unspecified. May also be set\n                                in PodSecurityContext. If set in both SecurityContext\n                                and PodSecurityContext, the value specified in SecurityContext\n                                takes precedence.\n                              type: string\n                          type: object\n                      type: object\n                    startupProbe:\n                      description: 'StartupProbe indicates that the Pod has successfully\n                        initialized. If specified, no other probes are executed until\n                        this completes successfully. If this probe fails, the Pod\n                        will be restarted, just as if the livenessProbe failed. This\n                        can be used to provide different probe parameters at the beginning\n                        of a Pod''s lifecycle, when it might take a long time to load\n                        data or warm a cache, than during steady-state operation.\n                        This cannot be updated. This is a beta feature enabled by\n                        the StartupProbe feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                      properties:\n                        exec:\n                          description: One and only one of the following should be\n                            specified. Exec specifies the action to take.\n                          properties:\n                            command:\n                              description: Command is the command line to execute\n                                inside the container, the working directory for the\n                                command  is root ('/') in the container's filesystem.\n                                The command is simply exec'd, it is not run inside\n                                a shell, so traditional shell instructions ('|', etc)\n                                won't work. To use a shell, you need to explicitly\n                                call out to that shell. Exit status of 0 is treated\n                                as live/healthy and non-zero is unhealthy.\n                              items:\n                                type: string\n                              type: array\n                          type: object\n                        failureThreshold:\n                          description: Minimum consecutive failures for the probe\n                            to be considered failed after having succeeded. Defaults\n                            to 3. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        httpGet:\n                          description: HTTPGet specifies the http request to perform.\n                          properties:\n                            host:\n                              description: Host name to connect to, defaults to the\n                                pod IP. You probably want to set \"Host\" in httpHeaders\n                                instead.\n                              type: string\n                            httpHeaders:\n                              description: Custom headers to set in the request. HTTP\n                                allows repeated headers.\n                              items:\n                                description: HTTPHeader describes a custom header\n                                  to be used in HTTP probes\n                                properties:\n                                  name:\n                                    description: The header field name\n                                    type: string\n                                  value:\n                                    description: The header field value\n                                    type: string\n                                required:\n                                - name\n                                - value\n                                type: object\n                              type: array\n                            path:\n                              description: Path to access on the HTTP server.\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Name or number of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                            scheme:\n                              description: Scheme to use for connecting to the host.\n                                Defaults to HTTP.\n                              type: string\n                          required:\n                          - port\n                          type: object\n                        initialDelaySeconds:\n                          description: 'Number of seconds after the container has\n                            started before liveness probes are initiated. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                        periodSeconds:\n                          description: How often (in seconds) to perform the probe.\n                            Default to 10 seconds. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        successThreshold:\n                          description: Minimum consecutive successes for the probe\n                            to be considered successful after having failed. Defaults\n                            to 1. Must be 1 for liveness and startup. Minimum value\n                            is 1.\n                          format: int32\n                          type: integer\n                        tcpSocket:\n                          description: 'TCPSocket specifies an action involving a\n                            TCP port. TCP hooks not yet supported TODO: implement\n                            a realistic TCP lifecycle hook'\n                          properties:\n                            host:\n                              description: 'Optional: Host name to connect to, defaults\n                                to the pod IP.'\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Number or name of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                          required:\n                          - port\n                          type: object\n                        timeoutSeconds:\n                          description: 'Number of seconds after which the probe times\n                            out. Defaults to 1 second. Minimum value is 1. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                      type: object\n                    stdin:\n                      description: Whether this container should allocate a buffer\n                        for stdin in the container runtime. If this is not set, reads\n                        from stdin in the container will always result in EOF. Default\n                        is false.\n                      type: boolean\n                    stdinOnce:\n                      description: Whether the container runtime should close the\n                        stdin channel after it has been opened by a single attach.\n                        When stdin is true the stdin stream will remain open across\n                        multiple attach sessions. If stdinOnce is set to true, stdin\n                        is opened on container start, is empty until the first client\n                        attaches to stdin, and then remains open and accepts data\n                        until the client disconnects, at which time stdin is closed\n                        and remains closed until the container is restarted. If this\n                        flag is false, a container processes that reads from stdin\n                        will never receive an EOF. Default is false\n                      type: boolean\n                    terminationMessagePath:\n                      description: 'Optional: Path at which the file to which the\n                        container''s termination message will be written is mounted\n                        into the container''s filesystem. Message written is intended\n                        to be brief final status, such as an assertion failure message.\n                        Will be truncated by the node if greater than 4096 bytes.\n                        The total message length across all containers will be limited\n                        to 12kb. Defaults to /dev/termination-log. Cannot be updated.'\n                      type: string\n                    terminationMessagePolicy:\n                      description: Indicate how the termination message should be\n                        populated. File will use the contents of terminationMessagePath\n                        to populate the container status message on both success and\n                        failure. FallbackToLogsOnError will use the last chunk of\n                        container log output if the termination message file is empty\n                        and the container exited with an error. The log output is\n                        limited to 2048 bytes or 80 lines, whichever is smaller. Defaults\n                        to File. Cannot be updated.\n                      type: string\n                    tty:\n                      description: Whether this container should allocate a TTY for\n                        itself, also requires 'stdin' to be true. Default is false.\n                      type: boolean\n                    volumeDevices:\n                      description: volumeDevices is the list of block devices to be\n                        used by the container.\n                      items:\n                        description: volumeDevice describes a mapping of a raw block\n                          device within a container.\n                        properties:\n                          devicePath:\n                            description: devicePath is the path inside of the container\n                              that the device will be mapped to.\n                            type: string\n                          name:\n                            description: name must match the name of a persistentVolumeClaim\n                              in the pod\n                            type: string\n                        required:\n                        - devicePath\n                        - name\n                        type: object\n                      type: array\n                    volumeMounts:\n                      description: Pod volumes to mount into the container's filesystem.\n                        Cannot be updated.\n                      items:\n                        description: VolumeMount describes a mounting of a Volume\n                          within a container.\n                        properties:\n                          mountPath:\n                            description: Path within the container at which the volume\n                              should be mounted.  Must not contain ':'.\n                            type: string\n                          mountPropagation:\n                            description: mountPropagation determines how mounts are\n                              propagated from the host to container and the other\n                              way around. When not set, MountPropagationNone is used.\n                              This field is beta in 1.10.\n                            type: string\n                          name:\n                            description: This must match the Name of a Volume.\n                            type: string\n                          readOnly:\n                            description: Mounted read-only if true, read-write otherwise\n                              (false or unspecified). Defaults to false.\n                            type: boolean\n                          subPath:\n                            description: Path within the volume from which the container's\n                              volume should be mounted. Defaults to \"\" (volume's root).\n                            type: string\n                          subPathExpr:\n                            description: Expanded path within the volume from which\n                              the container's volume should be mounted. Behaves similarly\n                              to SubPath but environment variable references $(VAR_NAME)\n                              are expanded using the container's environment. Defaults\n                              to \"\" (volume's root). SubPathExpr and SubPath are mutually\n                              exclusive.\n                            type: string\n                        required:\n                        - mountPath\n                        - name\n                        type: object\n                      type: array\n                    workingDir:\n                      description: Container's working directory. If not specified,\n                        the container runtime's default will be used, which might\n                        be configured in the container image. Cannot be updated.\n                      type: string\n                  required:\n                  - name\n                  type: object\n                type: array\n              externalUrl:\n                description: The external URL the Alertmanager instances will be available\n                  under. This is necessary to generate correct URLs. This is necessary\n                  if Alertmanager is not served from root of a DNS name.\n                type: string\n              forceEnableClusterMode:\n                description: ForceEnableClusterMode ensures Alertmanager does not\n                  deactivate the cluster mode when running with a single replica.\n                  Use case is e.g. spanning an Alertmanager cluster across Kubernetes\n                  clusters with a single replica in each.\n                type: boolean\n              image:\n                description: Image if specified has precedence over baseImage, tag\n                  and sha combinations. Specifying the version is still necessary\n                  to ensure the Prometheus Operator knows what version of Alertmanager\n                  is being configured.\n                type: string\n              imagePullSecrets:\n                description: An optional list of references to secrets in the same\n                  namespace to use for pulling prometheus and alertmanager images\n                  from registries see http://kubernetes.io/docs/user-guide/images#specifying-imagepullsecrets-on-a-pod\n                items:\n                  description: LocalObjectReference contains enough information to\n                    let you locate the referenced object inside the same namespace.\n                  properties:\n                    name:\n                      description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                        TODO: Add other useful fields. apiVersion, kind, uid?'\n                      type: string\n                  type: object\n                type: array\n              initContainers:\n                description: 'InitContainers allows adding initContainers to the pod\n                  definition. Those can be used to e.g. fetch secrets for injection\n                  into the Alertmanager configuration from external sources. Any errors\n                  during the execution of an initContainer will lead to a restart\n                  of the Pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/\n                  Using initContainers for any use case other then secret fetching\n                  is entirely outside the scope of what the maintainers will support\n                  and by doing so, you accept that this behaviour may break at any\n                  time without notice.'\n                items:\n                  description: A single application container that you want to run\n                    within a pod.\n                  properties:\n                    args:\n                      description: 'Arguments to the entrypoint. The docker image''s\n                        CMD is used if this is not provided. Variable references $(VAR_NAME)\n                        are expanded using the container''s environment. If a variable\n                        cannot be resolved, the reference in the input string will\n                        be unchanged. The $(VAR_NAME) syntax can be escaped with a\n                        double $$, ie: $$(VAR_NAME). Escaped references will never\n                        be expanded, regardless of whether the variable exists or\n                        not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell'\n                      items:\n                        type: string\n                      type: array\n                    command:\n                      description: 'Entrypoint array. Not executed within a shell.\n                        The docker image''s ENTRYPOINT is used if this is not provided.\n                        Variable references $(VAR_NAME) are expanded using the container''s\n                        environment. If a variable cannot be resolved, the reference\n                        in the input string will be unchanged. The $(VAR_NAME) syntax\n                        can be escaped with a double $$, ie: $$(VAR_NAME). Escaped\n                        references will never be expanded, regardless of whether the\n                        variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell'\n                      items:\n                        type: string\n                      type: array\n                    env:\n                      description: List of environment variables to set in the container.\n                        Cannot be updated.\n                      items:\n                        description: EnvVar represents an environment variable present\n                          in a Container.\n                        properties:\n                          name:\n                            description: Name of the environment variable. Must be\n                              a C_IDENTIFIER.\n                            type: string\n                          value:\n                            description: 'Variable references $(VAR_NAME) are expanded\n                              using the previous defined environment variables in\n                              the container and any service environment variables.\n                              If a variable cannot be resolved, the reference in the\n                              input string will be unchanged. The $(VAR_NAME) syntax\n                              can be escaped with a double $$, ie: $$(VAR_NAME). Escaped\n                              references will never be expanded, regardless of whether\n                              the variable exists or not. Defaults to \"\".'\n                            type: string\n                          valueFrom:\n                            description: Source for the environment variable's value.\n                              Cannot be used if value is not empty.\n                            properties:\n                              configMapKeyRef:\n                                description: Selects a key of a ConfigMap.\n                                properties:\n                                  key:\n                                    description: The key to select.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the ConfigMap or\n                                      its key must be defined\n                                    type: boolean\n                                required:\n                                - key\n                                type: object\n                              fieldRef:\n                                description: 'Selects a field of the pod: supports\n                                  metadata.name, metadata.namespace, metadata.labels,\n                                  metadata.annotations, spec.nodeName, spec.serviceAccountName,\n                                  status.hostIP, status.podIP, status.podIPs.'\n                                properties:\n                                  apiVersion:\n                                    description: Version of the schema the FieldPath\n                                      is written in terms of, defaults to \"v1\".\n                                    type: string\n                                  fieldPath:\n                                    description: Path of the field to select in the\n                                      specified API version.\n                                    type: string\n                                required:\n                                - fieldPath\n                                type: object\n                              resourceFieldRef:\n                                description: 'Selects a resource of the container:\n                                  only resources limits and requests (limits.cpu,\n                                  limits.memory, limits.ephemeral-storage, requests.cpu,\n                                  requests.memory and requests.ephemeral-storage)\n                                  are currently supported.'\n                                properties:\n                                  containerName:\n                                    description: 'Container name: required for volumes,\n                                      optional for env vars'\n                                    type: string\n                                  divisor:\n                                    anyOf:\n                                    - type: integer\n                                    - type: string\n                                    description: Specifies the output format of the\n                                      exposed resources, defaults to \"1\"\n                                    pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                    x-kubernetes-int-or-string: true\n                                  resource:\n                                    description: 'Required: resource to select'\n                                    type: string\n                                required:\n                                - resource\n                                type: object\n                              secretKeyRef:\n                                description: Selects a key of a secret in the pod's\n                                  namespace\n                                properties:\n                                  key:\n                                    description: The key of the secret to select from.  Must\n                                      be a valid secret key.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the Secret or its\n                                      key must be defined\n                                    type: boolean\n                                required:\n                                - key\n                                type: object\n                            type: object\n                        required:\n                        - name\n                        type: object\n                      type: array\n                    envFrom:\n                      description: List of sources to populate environment variables\n                        in the container. The keys defined within a source must be\n                        a C_IDENTIFIER. All invalid keys will be reported as an event\n                        when the container is starting. When a key exists in multiple\n                        sources, the value associated with the last source will take\n                        precedence. Values defined by an Env with a duplicate key\n                        will take precedence. Cannot be updated.\n                      items:\n                        description: EnvFromSource represents the source of a set\n                          of ConfigMaps\n                        properties:\n                          configMapRef:\n                            description: The ConfigMap to select from\n                            properties:\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the ConfigMap must be\n                                  defined\n                                type: boolean\n                            type: object\n                          prefix:\n                            description: An optional identifier to prepend to each\n                              key in the ConfigMap. Must be a C_IDENTIFIER.\n                            type: string\n                          secretRef:\n                            description: The Secret to select from\n                            properties:\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret must be defined\n                                type: boolean\n                            type: object\n                        type: object\n                      type: array\n                    image:\n                      description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images\n                        This field is optional to allow higher level config management\n                        to default or override container images in workload controllers\n                        like Deployments and StatefulSets.'\n                      type: string\n                    imagePullPolicy:\n                      description: 'Image pull policy. One of Always, Never, IfNotPresent.\n                        Defaults to Always if :latest tag is specified, or IfNotPresent\n                        otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images'\n                      type: string\n                    lifecycle:\n                      description: Actions that the management system should take\n                        in response to container lifecycle events. Cannot be updated.\n                      properties:\n                        postStart:\n                          description: 'PostStart is called immediately after a container\n                            is created. If the handler fails, the container is terminated\n                            and restarted according to its restart policy. Other management\n                            of the container blocks until the hook completes. More\n                            info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks'\n                          properties:\n                            exec:\n                              description: One and only one of the following should\n                                be specified. Exec specifies the action to take.\n                              properties:\n                                command:\n                                  description: Command is the command line to execute\n                                    inside the container, the working directory for\n                                    the command  is root ('/') in the container's\n                                    filesystem. The command is simply exec'd, it is\n                                    not run inside a shell, so traditional shell instructions\n                                    ('|', etc) won't work. To use a shell, you need\n                                    to explicitly call out to that shell. Exit status\n                                    of 0 is treated as live/healthy and non-zero is\n                                    unhealthy.\n                                  items:\n                                    type: string\n                                  type: array\n                              type: object\n                            httpGet:\n                              description: HTTPGet specifies the http request to perform.\n                              properties:\n                                host:\n                                  description: Host name to connect to, defaults to\n                                    the pod IP. You probably want to set \"Host\" in\n                                    httpHeaders instead.\n                                  type: string\n                                httpHeaders:\n                                  description: Custom headers to set in the request.\n                                    HTTP allows repeated headers.\n                                  items:\n                                    description: HTTPHeader describes a custom header\n                                      to be used in HTTP probes\n                                    properties:\n                                      name:\n                                        description: The header field name\n                                        type: string\n                                      value:\n                                        description: The header field value\n                                        type: string\n                                    required:\n                                    - name\n                                    - value\n                                    type: object\n                                  type: array\n                                path:\n                                  description: Path to access on the HTTP server.\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Name or number of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                                scheme:\n                                  description: Scheme to use for connecting to the\n                                    host. Defaults to HTTP.\n                                  type: string\n                              required:\n                              - port\n                              type: object\n                            tcpSocket:\n                              description: 'TCPSocket specifies an action involving\n                                a TCP port. TCP hooks not yet supported TODO: implement\n                                a realistic TCP lifecycle hook'\n                              properties:\n                                host:\n                                  description: 'Optional: Host name to connect to,\n                                    defaults to the pod IP.'\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Number or name of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                              required:\n                              - port\n                              type: object\n                          type: object\n                        preStop:\n                          description: 'PreStop is called immediately before a container\n                            is terminated due to an API request or management event\n                            such as liveness/startup probe failure, preemption, resource\n                            contention, etc. The handler is not called if the container\n                            crashes or exits. The reason for termination is passed\n                            to the handler. The Pod''s termination grace period countdown\n                            begins before the PreStop hooked is executed. Regardless\n                            of the outcome of the handler, the container will eventually\n                            terminate within the Pod''s termination grace period.\n                            Other management of the container blocks until the hook\n                            completes or until the termination grace period is reached.\n                            More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks'\n                          properties:\n                            exec:\n                              description: One and only one of the following should\n                                be specified. Exec specifies the action to take.\n                              properties:\n                                command:\n                                  description: Command is the command line to execute\n                                    inside the container, the working directory for\n                                    the command  is root ('/') in the container's\n                                    filesystem. The command is simply exec'd, it is\n                                    not run inside a shell, so traditional shell instructions\n                                    ('|', etc) won't work. To use a shell, you need\n                                    to explicitly call out to that shell. Exit status\n                                    of 0 is treated as live/healthy and non-zero is\n                                    unhealthy.\n                                  items:\n                                    type: string\n                                  type: array\n                              type: object\n                            httpGet:\n                              description: HTTPGet specifies the http request to perform.\n                              properties:\n                                host:\n                                  description: Host name to connect to, defaults to\n                                    the pod IP. You probably want to set \"Host\" in\n                                    httpHeaders instead.\n                                  type: string\n                                httpHeaders:\n                                  description: Custom headers to set in the request.\n                                    HTTP allows repeated headers.\n                                  items:\n                                    description: HTTPHeader describes a custom header\n                                      to be used in HTTP probes\n                                    properties:\n                                      name:\n                                        description: The header field name\n                                        type: string\n                                      value:\n                                        description: The header field value\n                                        type: string\n                                    required:\n                                    - name\n                                    - value\n                                    type: object\n                                  type: array\n                                path:\n                                  description: Path to access on the HTTP server.\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Name or number of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                                scheme:\n                                  description: Scheme to use for connecting to the\n                                    host. Defaults to HTTP.\n                                  type: string\n                              required:\n                              - port\n                              type: object\n                            tcpSocket:\n                              description: 'TCPSocket specifies an action involving\n                                a TCP port. TCP hooks not yet supported TODO: implement\n                                a realistic TCP lifecycle hook'\n                              properties:\n                                host:\n                                  description: 'Optional: Host name to connect to,\n                                    defaults to the pod IP.'\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Number or name of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                              required:\n                              - port\n                              type: object\n                          type: object\n                      type: object\n                    livenessProbe:\n                      description: 'Periodic probe of container liveness. Container\n                        will be restarted if the probe fails. Cannot be updated. More\n                        info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                      properties:\n                        exec:\n                          description: One and only one of the following should be\n                            specified. Exec specifies the action to take.\n                          properties:\n                            command:\n                              description: Command is the command line to execute\n                                inside the container, the working directory for the\n                                command  is root ('/') in the container's filesystem.\n                                The command is simply exec'd, it is not run inside\n                                a shell, so traditional shell instructions ('|', etc)\n                                won't work. To use a shell, you need to explicitly\n                                call out to that shell. Exit status of 0 is treated\n                                as live/healthy and non-zero is unhealthy.\n                              items:\n                                type: string\n                              type: array\n                          type: object\n                        failureThreshold:\n                          description: Minimum consecutive failures for the probe\n                            to be considered failed after having succeeded. Defaults\n                            to 3. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        httpGet:\n                          description: HTTPGet specifies the http request to perform.\n                          properties:\n                            host:\n                              description: Host name to connect to, defaults to the\n                                pod IP. You probably want to set \"Host\" in httpHeaders\n                                instead.\n                              type: string\n                            httpHeaders:\n                              description: Custom headers to set in the request. HTTP\n                                allows repeated headers.\n                              items:\n                                description: HTTPHeader describes a custom header\n                                  to be used in HTTP probes\n                                properties:\n                                  name:\n                                    description: The header field name\n                                    type: string\n                                  value:\n                                    description: The header field value\n                                    type: string\n                                required:\n                                - name\n                                - value\n                                type: object\n                              type: array\n                            path:\n                              description: Path to access on the HTTP server.\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Name or number of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                            scheme:\n                              description: Scheme to use for connecting to the host.\n                                Defaults to HTTP.\n                              type: string\n                          required:\n                          - port\n                          type: object\n                        initialDelaySeconds:\n                          description: 'Number of seconds after the container has\n                            started before liveness probes are initiated. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                        periodSeconds:\n                          description: How often (in seconds) to perform the probe.\n                            Default to 10 seconds. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        successThreshold:\n                          description: Minimum consecutive successes for the probe\n                            to be considered successful after having failed. Defaults\n                            to 1. Must be 1 for liveness and startup. Minimum value\n                            is 1.\n                          format: int32\n                          type: integer\n                        tcpSocket:\n                          description: 'TCPSocket specifies an action involving a\n                            TCP port. TCP hooks not yet supported TODO: implement\n                            a realistic TCP lifecycle hook'\n                          properties:\n                            host:\n                              description: 'Optional: Host name to connect to, defaults\n                                to the pod IP.'\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Number or name of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                          required:\n                          - port\n                          type: object\n                        timeoutSeconds:\n                          description: 'Number of seconds after which the probe times\n                            out. Defaults to 1 second. Minimum value is 1. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                      type: object\n                    name:\n                      description: Name of the container specified as a DNS_LABEL.\n                        Each container in a pod must have a unique name (DNS_LABEL).\n                        Cannot be updated.\n                      type: string\n                    ports:\n                      description: List of ports to expose from the container. Exposing\n                        a port here gives the system additional information about\n                        the network connections a container uses, but is primarily\n                        informational. Not specifying a port here DOES NOT prevent\n                        that port from being exposed. Any port which is listening\n                        on the default \"0.0.0.0\" address inside a container will be\n                        accessible from the network. Cannot be updated.\n                      items:\n                        description: ContainerPort represents a network port in a\n                          single container.\n                        properties:\n                          containerPort:\n                            description: Number of port to expose on the pod's IP\n                              address. This must be a valid port number, 0 < x < 65536.\n                            format: int32\n                            type: integer\n                          hostIP:\n                            description: What host IP to bind the external port to.\n                            type: string\n                          hostPort:\n                            description: Number of port to expose on the host. If\n                              specified, this must be a valid port number, 0 < x <\n                              65536. If HostNetwork is specified, this must match\n                              ContainerPort. Most containers do not need this.\n                            format: int32\n                            type: integer\n                          name:\n                            description: If specified, this must be an IANA_SVC_NAME\n                              and unique within the pod. Each named port in a pod\n                              must have a unique name. Name for the port that can\n                              be referred to by services.\n                            type: string\n                          protocol:\n                            default: TCP\n                            description: Protocol for port. Must be UDP, TCP, or SCTP.\n                              Defaults to \"TCP\".\n                            type: string\n                        required:\n                        - containerPort\n                        type: object\n                      type: array\n                      x-kubernetes-list-map-keys:\n                      - containerPort\n                      - protocol\n                      x-kubernetes-list-type: map\n                    readinessProbe:\n                      description: 'Periodic probe of container service readiness.\n                        Container will be removed from service endpoints if the probe\n                        fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                      properties:\n                        exec:\n                          description: One and only one of the following should be\n                            specified. Exec specifies the action to take.\n                          properties:\n                            command:\n                              description: Command is the command line to execute\n                                inside the container, the working directory for the\n                                command  is root ('/') in the container's filesystem.\n                                The command is simply exec'd, it is not run inside\n                                a shell, so traditional shell instructions ('|', etc)\n                                won't work. To use a shell, you need to explicitly\n                                call out to that shell. Exit status of 0 is treated\n                                as live/healthy and non-zero is unhealthy.\n                              items:\n                                type: string\n                              type: array\n                          type: object\n                        failureThreshold:\n                          description: Minimum consecutive failures for the probe\n                            to be considered failed after having succeeded. Defaults\n                            to 3. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        httpGet:\n                          description: HTTPGet specifies the http request to perform.\n                          properties:\n                            host:\n                              description: Host name to connect to, defaults to the\n                                pod IP. You probably want to set \"Host\" in httpHeaders\n                                instead.\n                              type: string\n                            httpHeaders:\n                              description: Custom headers to set in the request. HTTP\n                                allows repeated headers.\n                              items:\n                                description: HTTPHeader describes a custom header\n                                  to be used in HTTP probes\n                                properties:\n                                  name:\n                                    description: The header field name\n                                    type: string\n                                  value:\n                                    description: The header field value\n                                    type: string\n                                required:\n                                - name\n                                - value\n                                type: object\n                              type: array\n                            path:\n                              description: Path to access on the HTTP server.\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Name or number of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                            scheme:\n                              description: Scheme to use for connecting to the host.\n                                Defaults to HTTP.\n                              type: string\n                          required:\n                          - port\n                          type: object\n                        initialDelaySeconds:\n                          description: 'Number of seconds after the container has\n                            started before liveness probes are initiated. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                        periodSeconds:\n                          description: How often (in seconds) to perform the probe.\n                            Default to 10 seconds. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        successThreshold:\n                          description: Minimum consecutive successes for the probe\n                            to be considered successful after having failed. Defaults\n                            to 1. Must be 1 for liveness and startup. Minimum value\n                            is 1.\n                          format: int32\n                          type: integer\n                        tcpSocket:\n                          description: 'TCPSocket specifies an action involving a\n                            TCP port. TCP hooks not yet supported TODO: implement\n                            a realistic TCP lifecycle hook'\n                          properties:\n                            host:\n                              description: 'Optional: Host name to connect to, defaults\n                                to the pod IP.'\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Number or name of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                          required:\n                          - port\n                          type: object\n                        timeoutSeconds:\n                          description: 'Number of seconds after which the probe times\n                            out. Defaults to 1 second. Minimum value is 1. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                      type: object\n                    resources:\n                      description: 'Compute Resources required by this container.\n                        Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                      properties:\n                        limits:\n                          additionalProperties:\n                            anyOf:\n                            - type: integer\n                            - type: string\n                            pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                            x-kubernetes-int-or-string: true\n                          description: 'Limits describes the maximum amount of compute\n                            resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                          type: object\n                        requests:\n                          additionalProperties:\n                            anyOf:\n                            - type: integer\n                            - type: string\n                            pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                            x-kubernetes-int-or-string: true\n                          description: 'Requests describes the minimum amount of compute\n                            resources required. If Requests is omitted for a container,\n                            it defaults to Limits if that is explicitly specified,\n                            otherwise to an implementation-defined value. More info:\n                            https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                          type: object\n                      type: object\n                    securityContext:\n                      description: 'Security options the pod should run with. More\n                        info: https://kubernetes.io/docs/concepts/policy/security-context/\n                        More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/'\n                      properties:\n                        allowPrivilegeEscalation:\n                          description: 'AllowPrivilegeEscalation controls whether\n                            a process can gain more privileges than its parent process.\n                            This bool directly controls if the no_new_privs flag will\n                            be set on the container process. AllowPrivilegeEscalation\n                            is true always when the container is: 1) run as Privileged\n                            2) has CAP_SYS_ADMIN'\n                          type: boolean\n                        capabilities:\n                          description: The capabilities to add/drop when running containers.\n                            Defaults to the default set of capabilities granted by\n                            the container runtime.\n                          properties:\n                            add:\n                              description: Added capabilities\n                              items:\n                                description: Capability represent POSIX capabilities\n                                  type\n                                type: string\n                              type: array\n                            drop:\n                              description: Removed capabilities\n                              items:\n                                description: Capability represent POSIX capabilities\n                                  type\n                                type: string\n                              type: array\n                          type: object\n                        privileged:\n                          description: Run container in privileged mode. Processes\n                            in privileged containers are essentially equivalent to\n                            root on the host. Defaults to false.\n                          type: boolean\n                        procMount:\n                          description: procMount denotes the type of proc mount to\n                            use for the containers. The default is DefaultProcMount\n                            which uses the container runtime defaults for readonly\n                            paths and masked paths. This requires the ProcMountType\n                            feature flag to be enabled.\n                          type: string\n                        readOnlyRootFilesystem:\n                          description: Whether this container has a read-only root\n                            filesystem. Default is false.\n                          type: boolean\n                        runAsGroup:\n                          description: The GID to run the entrypoint of the container\n                            process. Uses runtime default if unset. May also be set\n                            in PodSecurityContext.  If set in both SecurityContext\n                            and PodSecurityContext, the value specified in SecurityContext\n                            takes precedence.\n                          format: int64\n                          type: integer\n                        runAsNonRoot:\n                          description: Indicates that the container must run as a\n                            non-root user. If true, the Kubelet will validate the\n                            image at runtime to ensure that it does not run as UID\n                            0 (root) and fail to start the container if it does. If\n                            unset or false, no such validation will be performed.\n                            May also be set in PodSecurityContext.  If set in both\n                            SecurityContext and PodSecurityContext, the value specified\n                            in SecurityContext takes precedence.\n                          type: boolean\n                        runAsUser:\n                          description: The UID to run the entrypoint of the container\n                            process. Defaults to user specified in image metadata\n                            if unspecified. May also be set in PodSecurityContext.  If\n                            set in both SecurityContext and PodSecurityContext, the\n                            value specified in SecurityContext takes precedence.\n                          format: int64\n                          type: integer\n                        seLinuxOptions:\n                          description: The SELinux context to be applied to the container.\n                            If unspecified, the container runtime will allocate a\n                            random SELinux context for each container.  May also be\n                            set in PodSecurityContext.  If set in both SecurityContext\n                            and PodSecurityContext, the value specified in SecurityContext\n                            takes precedence.\n                          properties:\n                            level:\n                              description: Level is SELinux level label that applies\n                                to the container.\n                              type: string\n                            role:\n                              description: Role is a SELinux role label that applies\n                                to the container.\n                              type: string\n                            type:\n                              description: Type is a SELinux type label that applies\n                                to the container.\n                              type: string\n                            user:\n                              description: User is a SELinux user label that applies\n                                to the container.\n                              type: string\n                          type: object\n                        windowsOptions:\n                          description: The Windows specific settings applied to all\n                            containers. If unspecified, the options from the PodSecurityContext\n                            will be used. If set in both SecurityContext and PodSecurityContext,\n                            the value specified in SecurityContext takes precedence.\n                          properties:\n                            gmsaCredentialSpec:\n                              description: GMSACredentialSpec is where the GMSA admission\n                                webhook (https://github.com/kubernetes-sigs/windows-gmsa)\n                                inlines the contents of the GMSA credential spec named\n                                by the GMSACredentialSpecName field.\n                              type: string\n                            gmsaCredentialSpecName:\n                              description: GMSACredentialSpecName is the name of the\n                                GMSA credential spec to use.\n                              type: string\n                            runAsUserName:\n                              description: The UserName in Windows to run the entrypoint\n                                of the container process. Defaults to the user specified\n                                in image metadata if unspecified. May also be set\n                                in PodSecurityContext. If set in both SecurityContext\n                                and PodSecurityContext, the value specified in SecurityContext\n                                takes precedence.\n                              type: string\n                          type: object\n                      type: object\n                    startupProbe:\n                      description: 'StartupProbe indicates that the Pod has successfully\n                        initialized. If specified, no other probes are executed until\n                        this completes successfully. If this probe fails, the Pod\n                        will be restarted, just as if the livenessProbe failed. This\n                        can be used to provide different probe parameters at the beginning\n                        of a Pod''s lifecycle, when it might take a long time to load\n                        data or warm a cache, than during steady-state operation.\n                        This cannot be updated. This is a beta feature enabled by\n                        the StartupProbe feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                      properties:\n                        exec:\n                          description: One and only one of the following should be\n                            specified. Exec specifies the action to take.\n                          properties:\n                            command:\n                              description: Command is the command line to execute\n                                inside the container, the working directory for the\n                                command  is root ('/') in the container's filesystem.\n                                The command is simply exec'd, it is not run inside\n                                a shell, so traditional shell instructions ('|', etc)\n                                won't work. To use a shell, you need to explicitly\n                                call out to that shell. Exit status of 0 is treated\n                                as live/healthy and non-zero is unhealthy.\n                              items:\n                                type: string\n                              type: array\n                          type: object\n                        failureThreshold:\n                          description: Minimum consecutive failures for the probe\n                            to be considered failed after having succeeded. Defaults\n                            to 3. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        httpGet:\n                          description: HTTPGet specifies the http request to perform.\n                          properties:\n                            host:\n                              description: Host name to connect to, defaults to the\n                                pod IP. You probably want to set \"Host\" in httpHeaders\n                                instead.\n                              type: string\n                            httpHeaders:\n                              description: Custom headers to set in the request. HTTP\n                                allows repeated headers.\n                              items:\n                                description: HTTPHeader describes a custom header\n                                  to be used in HTTP probes\n                                properties:\n                                  name:\n                                    description: The header field name\n                                    type: string\n                                  value:\n                                    description: The header field value\n                                    type: string\n                                required:\n                                - name\n                                - value\n                                type: object\n                              type: array\n                            path:\n                              description: Path to access on the HTTP server.\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Name or number of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                            scheme:\n                              description: Scheme to use for connecting to the host.\n                                Defaults to HTTP.\n                              type: string\n                          required:\n                          - port\n                          type: object\n                        initialDelaySeconds:\n                          description: 'Number of seconds after the container has\n                            started before liveness probes are initiated. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                        periodSeconds:\n                          description: How often (in seconds) to perform the probe.\n                            Default to 10 seconds. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        successThreshold:\n                          description: Minimum consecutive successes for the probe\n                            to be considered successful after having failed. Defaults\n                            to 1. Must be 1 for liveness and startup. Minimum value\n                            is 1.\n                          format: int32\n                          type: integer\n                        tcpSocket:\n                          description: 'TCPSocket specifies an action involving a\n                            TCP port. TCP hooks not yet supported TODO: implement\n                            a realistic TCP lifecycle hook'\n                          properties:\n                            host:\n                              description: 'Optional: Host name to connect to, defaults\n                                to the pod IP.'\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Number or name of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                          required:\n                          - port\n                          type: object\n                        timeoutSeconds:\n                          description: 'Number of seconds after which the probe times\n                            out. Defaults to 1 second. Minimum value is 1. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                      type: object\n                    stdin:\n                      description: Whether this container should allocate a buffer\n                        for stdin in the container runtime. If this is not set, reads\n                        from stdin in the container will always result in EOF. Default\n                        is false.\n                      type: boolean\n                    stdinOnce:\n                      description: Whether the container runtime should close the\n                        stdin channel after it has been opened by a single attach.\n                        When stdin is true the stdin stream will remain open across\n                        multiple attach sessions. If stdinOnce is set to true, stdin\n                        is opened on container start, is empty until the first client\n                        attaches to stdin, and then remains open and accepts data\n                        until the client disconnects, at which time stdin is closed\n                        and remains closed until the container is restarted. If this\n                        flag is false, a container processes that reads from stdin\n                        will never receive an EOF. Default is false\n                      type: boolean\n                    terminationMessagePath:\n                      description: 'Optional: Path at which the file to which the\n                        container''s termination message will be written is mounted\n                        into the container''s filesystem. Message written is intended\n                        to be brief final status, such as an assertion failure message.\n                        Will be truncated by the node if greater than 4096 bytes.\n                        The total message length across all containers will be limited\n                        to 12kb. Defaults to /dev/termination-log. Cannot be updated.'\n                      type: string\n                    terminationMessagePolicy:\n                      description: Indicate how the termination message should be\n                        populated. File will use the contents of terminationMessagePath\n                        to populate the container status message on both success and\n                        failure. FallbackToLogsOnError will use the last chunk of\n                        container log output if the termination message file is empty\n                        and the container exited with an error. The log output is\n                        limited to 2048 bytes or 80 lines, whichever is smaller. Defaults\n                        to File. Cannot be updated.\n                      type: string\n                    tty:\n                      description: Whether this container should allocate a TTY for\n                        itself, also requires 'stdin' to be true. Default is false.\n                      type: boolean\n                    volumeDevices:\n                      description: volumeDevices is the list of block devices to be\n                        used by the container.\n                      items:\n                        description: volumeDevice describes a mapping of a raw block\n                          device within a container.\n                        properties:\n                          devicePath:\n                            description: devicePath is the path inside of the container\n                              that the device will be mapped to.\n                            type: string\n                          name:\n                            description: name must match the name of a persistentVolumeClaim\n                              in the pod\n                            type: string\n                        required:\n                        - devicePath\n                        - name\n                        type: object\n                      type: array\n                    volumeMounts:\n                      description: Pod volumes to mount into the container's filesystem.\n                        Cannot be updated.\n                      items:\n                        description: VolumeMount describes a mounting of a Volume\n                          within a container.\n                        properties:\n                          mountPath:\n                            description: Path within the container at which the volume\n                              should be mounted.  Must not contain ':'.\n                            type: string\n                          mountPropagation:\n                            description: mountPropagation determines how mounts are\n                              propagated from the host to container and the other\n                              way around. When not set, MountPropagationNone is used.\n                              This field is beta in 1.10.\n                            type: string\n                          name:\n                            description: This must match the Name of a Volume.\n                            type: string\n                          readOnly:\n                            description: Mounted read-only if true, read-write otherwise\n                              (false or unspecified). Defaults to false.\n                            type: boolean\n                          subPath:\n                            description: Path within the volume from which the container's\n                              volume should be mounted. Defaults to \"\" (volume's root).\n                            type: string\n                          subPathExpr:\n                            description: Expanded path within the volume from which\n                              the container's volume should be mounted. Behaves similarly\n                              to SubPath but environment variable references $(VAR_NAME)\n                              are expanded using the container's environment. Defaults\n                              to \"\" (volume's root). SubPathExpr and SubPath are mutually\n                              exclusive.\n                            type: string\n                        required:\n                        - mountPath\n                        - name\n                        type: object\n                      type: array\n                    workingDir:\n                      description: Container's working directory. If not specified,\n                        the container runtime's default will be used, which might\n                        be configured in the container image. Cannot be updated.\n                      type: string\n                  required:\n                  - name\n                  type: object\n                type: array\n              listenLocal:\n                description: ListenLocal makes the Alertmanager server listen on loopback,\n                  so that it does not bind against the Pod IP. Note this is only for\n                  the Alertmanager UI, not the gossip communication.\n                type: boolean\n              logFormat:\n                description: Log format for Alertmanager to be configured with.\n                type: string\n              logLevel:\n                description: Log level for Alertmanager to be configured with.\n                type: string\n              nodeSelector:\n                additionalProperties:\n                  type: string\n                description: Define which Nodes the Pods are scheduled on.\n                type: object\n              paused:\n                description: If set to true all actions on the underlying managed\n                  objects are not goint to be performed, except for delete actions.\n                type: boolean\n              podMetadata:\n                description: PodMetadata configures Labels and Annotations which are\n                  propagated to the alertmanager pods.\n                properties:\n                  annotations:\n                    additionalProperties:\n                      type: string\n                    description: 'Annotations is an unstructured key value map stored\n                      with a resource that may be set by external tools to store and\n                      retrieve arbitrary metadata. They are not queryable and should\n                      be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations'\n                    type: object\n                  labels:\n                    additionalProperties:\n                      type: string\n                    description: 'Map of string keys and values that can be used to\n                      organize and categorize (scope and select) objects. May match\n                      selectors of replication controllers and services. More info:\n                      http://kubernetes.io/docs/user-guide/labels'\n                    type: object\n                  name:\n                    description: 'Name must be unique within a namespace. Is required\n                      when creating resources, although some resources may allow a\n                      client to request the generation of an appropriate name automatically.\n                      Name is primarily intended for creation idempotence and configuration\n                      definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names'\n                    type: string\n                type: object\n              portName:\n                description: Port name used for the pods and governing service. This\n                  defaults to web\n                type: string\n              priorityClassName:\n                description: Priority class assigned to the Pods\n                type: string\n              replicas:\n                description: Size is the expected size of the alertmanager cluster.\n                  The controller will eventually make the size of the running cluster\n                  equal to the expected size.\n                format: int32\n                type: integer\n              resources:\n                description: Define resources requests and limits for single Pods.\n                properties:\n                  limits:\n                    additionalProperties:\n                      anyOf:\n                      - type: integer\n                      - type: string\n                      pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                      x-kubernetes-int-or-string: true\n                    description: 'Limits describes the maximum amount of compute resources\n                      allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                    type: object\n                  requests:\n                    additionalProperties:\n                      anyOf:\n                      - type: integer\n                      - type: string\n                      pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                      x-kubernetes-int-or-string: true\n                    description: 'Requests describes the minimum amount of compute\n                      resources required. If Requests is omitted for a container,\n                      it defaults to Limits if that is explicitly specified, otherwise\n                      to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                    type: object\n                type: object\n              retention:\n                description: Time duration Alertmanager shall retain data for. Default\n                  is '120h', and must match the regular expression `[0-9]+(ms|s|m|h)`\n                  (milliseconds seconds minutes hours).\n                type: string\n              routePrefix:\n                description: The route prefix Alertmanager registers HTTP handlers\n                  for. This is useful, if using ExternalURL and a proxy is rewriting\n                  HTTP routes of a request, and the actual ExternalURL is still true,\n                  but the server serves requests under a different route prefix. For\n                  example for use with `kubectl proxy`.\n                type: string\n              secrets:\n                description: Secrets is a list of Secrets in the same namespace as\n                  the Alertmanager object, which shall be mounted into the Alertmanager\n                  Pods. The Secrets are mounted into /etc/alertmanager/secrets/<secret-name>.\n                items:\n                  type: string\n                type: array\n              securityContext:\n                description: SecurityContext holds pod-level security attributes and\n                  common container settings. This defaults to the default PodSecurityContext.\n                properties:\n                  fsGroup:\n                    description: \"A special supplemental group that applies to all\n                      containers in a pod. Some volume types allow the Kubelet to\n                      change the ownership of that volume to be owned by the pod:\n                      \\n 1. The owning GID will be the FSGroup 2. The setgid bit is\n                      set (new files created in the volume will be owned by FSGroup)\n                      3. The permission bits are OR'd with rw-rw---- \\n If unset,\n                      the Kubelet will not modify the ownership and permissions of\n                      any volume.\"\n                    format: int64\n                    type: integer\n                  fsGroupChangePolicy:\n                    description: 'fsGroupChangePolicy defines behavior of changing\n                      ownership and permission of the volume before being exposed\n                      inside Pod. This field will only apply to volume types which\n                      support fsGroup based ownership(and permissions). It will have\n                      no effect on ephemeral volume types such as: secret, configmaps\n                      and emptydir. Valid values are \"OnRootMismatch\" and \"Always\".\n                      If not specified defaults to \"Always\".'\n                    type: string\n                  runAsGroup:\n                    description: The GID to run the entrypoint of the container process.\n                      Uses runtime default if unset. May also be set in SecurityContext.  If\n                      set in both SecurityContext and PodSecurityContext, the value\n                      specified in SecurityContext takes precedence for that container.\n                    format: int64\n                    type: integer\n                  runAsNonRoot:\n                    description: Indicates that the container must run as a non-root\n                      user. If true, the Kubelet will validate the image at runtime\n                      to ensure that it does not run as UID 0 (root) and fail to start\n                      the container if it does. If unset or false, no such validation\n                      will be performed. May also be set in SecurityContext.  If set\n                      in both SecurityContext and PodSecurityContext, the value specified\n                      in SecurityContext takes precedence.\n                    type: boolean\n                  runAsUser:\n                    description: The UID to run the entrypoint of the container process.\n                      Defaults to user specified in image metadata if unspecified.\n                      May also be set in SecurityContext.  If set in both SecurityContext\n                      and PodSecurityContext, the value specified in SecurityContext\n                      takes precedence for that container.\n                    format: int64\n                    type: integer\n                  seLinuxOptions:\n                    description: The SELinux context to be applied to all containers.\n                      If unspecified, the container runtime will allocate a random\n                      SELinux context for each container.  May also be set in SecurityContext.  If\n                      set in both SecurityContext and PodSecurityContext, the value\n                      specified in SecurityContext takes precedence for that container.\n                    properties:\n                      level:\n                        description: Level is SELinux level label that applies to\n                          the container.\n                        type: string\n                      role:\n                        description: Role is a SELinux role label that applies to\n                          the container.\n                        type: string\n                      type:\n                        description: Type is a SELinux type label that applies to\n                          the container.\n                        type: string\n                      user:\n                        description: User is a SELinux user label that applies to\n                          the container.\n                        type: string\n                    type: object\n                  supplementalGroups:\n                    description: A list of groups applied to the first process run\n                      in each container, in addition to the container's primary GID.  If\n                      unspecified, no groups will be added to any container.\n                    items:\n                      format: int64\n                      type: integer\n                    type: array\n                  sysctls:\n                    description: Sysctls hold a list of namespaced sysctls used for\n                      the pod. Pods with unsupported sysctls (by the container runtime)\n                      might fail to launch.\n                    items:\n                      description: Sysctl defines a kernel parameter to be set\n                      properties:\n                        name:\n                          description: Name of a property to set\n                          type: string\n                        value:\n                          description: Value of a property to set\n                          type: string\n                      required:\n                      - name\n                      - value\n                      type: object\n                    type: array\n                  windowsOptions:\n                    description: The Windows specific settings applied to all containers.\n                      If unspecified, the options within a container's SecurityContext\n                      will be used. If set in both SecurityContext and PodSecurityContext,\n                      the value specified in SecurityContext takes precedence.\n                    properties:\n                      gmsaCredentialSpec:\n                        description: GMSACredentialSpec is where the GMSA admission\n                          webhook (https://github.com/kubernetes-sigs/windows-gmsa)\n                          inlines the contents of the GMSA credential spec named by\n                          the GMSACredentialSpecName field.\n                        type: string\n                      gmsaCredentialSpecName:\n                        description: GMSACredentialSpecName is the name of the GMSA\n                          credential spec to use.\n                        type: string\n                      runAsUserName:\n                        description: The UserName in Windows to run the entrypoint\n                          of the container process. Defaults to the user specified\n                          in image metadata if unspecified. May also be set in PodSecurityContext.\n                          If set in both SecurityContext and PodSecurityContext, the\n                          value specified in SecurityContext takes precedence.\n                        type: string\n                    type: object\n                type: object\n              serviceAccountName:\n                description: ServiceAccountName is the name of the ServiceAccount\n                  to use to run the Prometheus Pods.\n                type: string\n              sha:\n                description: 'SHA of Alertmanager container image to be deployed.\n                  Defaults to the value of `version`. Similar to a tag, but the SHA\n                  explicitly deploys an immutable container image. Version and Tag\n                  are ignored if SHA is set. Deprecated: use ''image'' instead.  The\n                  image digest can be specified as part of the image URL.'\n                type: string\n              storage:\n                description: Storage is the definition of how storage will be used\n                  by the Alertmanager instances.\n                properties:\n                  disableMountSubPath:\n                    description: 'Deprecated: subPath usage will be disabled by default\n                      in a future release, this option will become unnecessary. DisableMountSubPath\n                      allows to remove any subPath usage in volume mounts.'\n                    type: boolean\n                  emptyDir:\n                    description: 'EmptyDirVolumeSource to be used by the Prometheus\n                      StatefulSets. If specified, used in place of any volumeClaimTemplate.\n                      More info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir'\n                    properties:\n                      medium:\n                        description: 'What type of storage medium should back this\n                          directory. The default is \"\" which means to use the node''s\n                          default medium. Must be an empty string (default) or Memory.\n                          More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir'\n                        type: string\n                      sizeLimit:\n                        anyOf:\n                        - type: integer\n                        - type: string\n                        description: 'Total amount of local storage required for this\n                          EmptyDir volume. The size limit is also applicable for memory\n                          medium. The maximum usage on memory medium EmptyDir would\n                          be the minimum value between the SizeLimit specified here\n                          and the sum of memory limits of all containers in a pod.\n                          The default is nil which means that the limit is undefined.\n                          More info: http://kubernetes.io/docs/user-guide/volumes#emptydir'\n                        pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                        x-kubernetes-int-or-string: true\n                    type: object\n                  volumeClaimTemplate:\n                    description: A PVC spec to be used by the Prometheus StatefulSets.\n                    properties:\n                      apiVersion:\n                        description: 'APIVersion defines the versioned schema of this\n                          representation of an object. Servers should convert recognized\n                          schemas to the latest internal value, and may reject unrecognized\n                          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\n                          resource this object represents. Servers may infer this\n                          from the endpoint the client submits requests to. Cannot\n                          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                        description: EmbeddedMetadata contains metadata relevant to\n                          an EmbeddedResource.\n                        properties:\n                          annotations:\n                            additionalProperties:\n                              type: string\n                            description: 'Annotations is an unstructured key value\n                              map stored with a resource that may be set by external\n                              tools to store and retrieve arbitrary metadata. They\n                              are not queryable and should be preserved when modifying\n                              objects. More info: http://kubernetes.io/docs/user-guide/annotations'\n                            type: object\n                          labels:\n                            additionalProperties:\n                              type: string\n                            description: 'Map of string keys and values that can be\n                              used to organize and categorize (scope and select) objects.\n                              May match selectors of replication controllers and services.\n                              More info: http://kubernetes.io/docs/user-guide/labels'\n                            type: object\n                          name:\n                            description: 'Name must be unique within a namespace.\n                              Is required when creating resources, although some resources\n                              may allow a client to request the generation of an appropriate\n                              name automatically. Name is primarily intended for creation\n                              idempotence and configuration definition. Cannot be\n                              updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names'\n                            type: string\n                        type: object\n                      spec:\n                        description: 'Spec defines the desired characteristics of\n                          a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'\n                        properties:\n                          accessModes:\n                            description: 'AccessModes contains the desired access\n                              modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'\n                            items:\n                              type: string\n                            type: array\n                          dataSource:\n                            description: 'This field can be used to specify either:\n                              * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot\n                              - Beta) * An existing PVC (PersistentVolumeClaim) *\n                              An existing custom resource/object that implements data\n                              population (Alpha) In order to use VolumeSnapshot object\n                              types, the appropriate feature gate must be enabled\n                              (VolumeSnapshotDataSource or AnyVolumeDataSource) If\n                              the provisioner or an external controller can support\n                              the specified data source, it will create a new volume\n                              based on the contents of the specified data source.\n                              If the specified data source is not supported, the volume\n                              will not be created and the failure will be reported\n                              as an event. In the future, we plan to support more\n                              data source types and the behavior of the provisioner\n                              may change.'\n                            properties:\n                              apiGroup:\n                                description: APIGroup is the group for the resource\n                                  being referenced. If APIGroup is not specified,\n                                  the specified Kind must be in the core API group.\n                                  For any other third-party types, APIGroup is required.\n                                type: string\n                              kind:\n                                description: Kind is the type of resource being referenced\n                                type: string\n                              name:\n                                description: Name is the name of resource being referenced\n                                type: string\n                            required:\n                            - kind\n                            - name\n                            type: object\n                          resources:\n                            description: 'Resources represents the minimum resources\n                              the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources'\n                            properties:\n                              limits:\n                                additionalProperties:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                  x-kubernetes-int-or-string: true\n                                description: 'Limits describes the maximum amount\n                                  of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                                type: object\n                              requests:\n                                additionalProperties:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                  x-kubernetes-int-or-string: true\n                                description: 'Requests describes the minimum amount\n                                  of compute resources required. If Requests is omitted\n                                  for a container, it defaults to Limits if that is\n                                  explicitly specified, otherwise to an implementation-defined\n                                  value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                                type: object\n                            type: object\n                          selector:\n                            description: A label query over volumes to consider for\n                              binding.\n                            properties:\n                              matchExpressions:\n                                description: matchExpressions is a list of label selector\n                                  requirements. The requirements are ANDed.\n                                items:\n                                  description: A label selector requirement is a selector\n                                    that contains values, a key, and an operator that\n                                    relates the key and values.\n                                  properties:\n                                    key:\n                                      description: key is the label key that the selector\n                                        applies to.\n                                      type: string\n                                    operator:\n                                      description: operator represents a key's relationship\n                                        to a set of values. Valid operators are In,\n                                        NotIn, Exists and DoesNotExist.\n                                      type: string\n                                    values:\n                                      description: values is an array of string values.\n                                        If the operator is In or NotIn, the values\n                                        array must be non-empty. If the operator is\n                                        Exists or DoesNotExist, the values array must\n                                        be empty. This array is replaced during a\n                                        strategic merge patch.\n                                      items:\n                                        type: string\n                                      type: array\n                                  required:\n                                  - key\n                                  - operator\n                                  type: object\n                                type: array\n                              matchLabels:\n                                additionalProperties:\n                                  type: string\n                                description: matchLabels is a map of {key,value} pairs.\n                                  A single {key,value} in the matchLabels map is equivalent\n                                  to an element of matchExpressions, whose key field\n                                  is \"key\", the operator is \"In\", and the values array\n                                  contains only \"value\". The requirements are ANDed.\n                                type: object\n                            type: object\n                          storageClassName:\n                            description: 'Name of the StorageClass required by the\n                              claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1'\n                            type: string\n                          volumeMode:\n                            description: volumeMode defines what type of volume is\n                              required by the claim. Value of Filesystem is implied\n                              when not included in claim spec.\n                            type: string\n                          volumeName:\n                            description: VolumeName is the binding reference to the\n                              PersistentVolume backing this claim.\n                            type: string\n                        type: object\n                      status:\n                        description: 'Status represents the current information/status\n                          of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'\n                        properties:\n                          accessModes:\n                            description: 'AccessModes contains the actual access modes\n                              the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'\n                            items:\n                              type: string\n                            type: array\n                          capacity:\n                            additionalProperties:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                              x-kubernetes-int-or-string: true\n                            description: Represents the actual resources of the underlying\n                              volume.\n                            type: object\n                          conditions:\n                            description: Current Condition of persistent volume claim.\n                              If underlying persistent volume is being resized then\n                              the Condition will be set to 'ResizeStarted'.\n                            items:\n                              description: PersistentVolumeClaimCondition contails\n                                details about state of pvc\n                              properties:\n                                lastProbeTime:\n                                  description: Last time we probed the condition.\n                                  format: date-time\n                                  type: string\n                                lastTransitionTime:\n                                  description: Last time the condition transitioned\n                                    from one status to another.\n                                  format: date-time\n                                  type: string\n                                message:\n                                  description: Human-readable message indicating details\n                                    about last transition.\n                                  type: string\n                                reason:\n                                  description: Unique, this should be a short, machine\n                                    understandable string that gives the reason for\n                                    condition's last transition. If it reports \"ResizeStarted\"\n                                    that means the underlying persistent volume is\n                                    being resized.\n                                  type: string\n                                status:\n                                  type: string\n                                type:\n                                  description: PersistentVolumeClaimConditionType\n                                    is a valid value of PersistentVolumeClaimCondition.Type\n                                  type: string\n                              required:\n                              - status\n                              - type\n                              type: object\n                            type: array\n                          phase:\n                            description: Phase represents the current phase of PersistentVolumeClaim.\n                            type: string\n                        type: object\n                    type: object\n                type: object\n              tag:\n                description: 'Tag of Alertmanager container image to be deployed.\n                  Defaults to the value of `version`. Version is ignored if Tag is\n                  set. Deprecated: use ''image'' instead.  The image tag can be specified\n                  as part of the image URL.'\n                type: string\n              tolerations:\n                description: If specified, the pod's tolerations.\n                items:\n                  description: The pod this Toleration is attached to tolerates any\n                    taint that matches the triple <key,value,effect> using the matching\n                    operator <operator>.\n                  properties:\n                    effect:\n                      description: Effect indicates the taint effect to match. Empty\n                        means match all taint effects. When specified, allowed values\n                        are NoSchedule, PreferNoSchedule and NoExecute.\n                      type: string\n                    key:\n                      description: Key is the taint key that the toleration applies\n                        to. Empty means match all taint keys. If the key is empty,\n                        operator must be Exists; this combination means to match all\n                        values and all keys.\n                      type: string\n                    operator:\n                      description: Operator represents a key's relationship to the\n                        value. Valid operators are Exists and Equal. Defaults to Equal.\n                        Exists is equivalent to wildcard for value, so that a pod\n                        can tolerate all taints of a particular category.\n                      type: string\n                    tolerationSeconds:\n                      description: TolerationSeconds represents the period of time\n                        the toleration (which must be of effect NoExecute, otherwise\n                        this field is ignored) tolerates the taint. By default, it\n                        is not set, which means tolerate the taint forever (do not\n                        evict). Zero and negative values will be treated as 0 (evict\n                        immediately) by the system.\n                      format: int64\n                      type: integer\n                    value:\n                      description: Value is the taint value the toleration matches\n                        to. If the operator is Exists, the value should be empty,\n                        otherwise just a regular string.\n                      type: string\n                  type: object\n                type: array\n              topologySpreadConstraints:\n                description: If specified, the pod's topology spread constraints.\n                items:\n                  description: TopologySpreadConstraint specifies how to spread matching\n                    pods among the given topology.\n                  properties:\n                    labelSelector:\n                      description: LabelSelector is used to find matching pods. Pods\n                        that match this label selector are counted to determine the\n                        number of pods in their corresponding topology domain.\n                      properties:\n                        matchExpressions:\n                          description: matchExpressions is a list of label selector\n                            requirements. The requirements are ANDed.\n                          items:\n                            description: A label selector requirement is a selector\n                              that contains values, a key, and an operator that relates\n                              the key and values.\n                            properties:\n                              key:\n                                description: key is the label key that the selector\n                                  applies to.\n                                type: string\n                              operator:\n                                description: operator represents a key's relationship\n                                  to a set of values. Valid operators are In, NotIn,\n                                  Exists and DoesNotExist.\n                                type: string\n                              values:\n                                description: values is an array of string values.\n                                  If the operator is In or NotIn, the values array\n                                  must be non-empty. If the operator is Exists or\n                                  DoesNotExist, the values array must be empty. This\n                                  array is replaced during a strategic merge patch.\n                                items:\n                                  type: string\n                                type: array\n                            required:\n                            - key\n                            - operator\n                            type: object\n                          type: array\n                        matchLabels:\n                          additionalProperties:\n                            type: string\n                          description: matchLabels is a map of {key,value} pairs.\n                            A single {key,value} in the matchLabels map is equivalent\n                            to an element of matchExpressions, whose key field is\n                            \"key\", the operator is \"In\", and the values array contains\n                            only \"value\". The requirements are ANDed.\n                          type: object\n                      type: object\n                    maxSkew:\n                      description: 'MaxSkew describes the degree to which pods may\n                        be unevenly distributed. It''s the maximum permitted difference\n                        between the number of matching pods in any two topology domains\n                        of a given topology type. For example, in a 3-zone cluster,\n                        MaxSkew is set to 1, and pods with the same labelSelector\n                        spread as 1/1/0: | zone1 | zone2 | zone3 | |   P   |   P   |       |\n                        - if MaxSkew is 1, incoming pod can only be scheduled to zone3\n                        to become 1/1/1; scheduling it onto zone1(zone2) would make\n                        the ActualSkew(2-0) on zone1(zone2) violate MaxSkew(1). -\n                        if MaxSkew is 2, incoming pod can be scheduled onto any zone.\n                        It''s a required field. Default value is 1 and 0 is not allowed.'\n                      format: int32\n                      type: integer\n                    topologyKey:\n                      description: TopologyKey is the key of node labels. Nodes that\n                        have a label with this key and identical values are considered\n                        to be in the same topology. We consider each <key, value>\n                        as a \"bucket\", and try to put balanced number of pods into\n                        each bucket. It's a required field.\n                      type: string\n                    whenUnsatisfiable:\n                      description: 'WhenUnsatisfiable indicates how to deal with a\n                        pod if it doesn''t satisfy the spread constraint. - DoNotSchedule\n                        (default) tells the scheduler not to schedule it - ScheduleAnyway\n                        tells the scheduler to still schedule it It''s considered\n                        as \"Unsatisfiable\" if and only if placing incoming pod on\n                        any topology violates \"MaxSkew\". For example, in a 3-zone\n                        cluster, MaxSkew is set to 1, and pods with the same labelSelector\n                        spread as 3/1/1: | zone1 | zone2 | zone3 | | P P P |   P   |   P   |\n                        If WhenUnsatisfiable is set to DoNotSchedule, incoming pod\n                        can only be scheduled to zone2(zone3) to become 3/2/1(3/1/2)\n                        as ActualSkew(2-1) on zone2(zone3) satisfies MaxSkew(1). In\n                        other words, the cluster can still be imbalanced, but scheduler\n                        won''t make it *more* imbalanced. It''s a required field.'\n                      type: string\n                  required:\n                  - maxSkew\n                  - topologyKey\n                  - whenUnsatisfiable\n                  type: object\n                type: array\n              version:\n                description: Version the cluster should be on.\n                type: string\n              volumeMounts:\n                description: VolumeMounts allows configuration of additional VolumeMounts\n                  on the output StatefulSet definition. VolumeMounts specified will\n                  be appended to other VolumeMounts in the alertmanager container,\n                  that are generated as a result of StorageSpec objects.\n                items:\n                  description: VolumeMount describes a mounting of a Volume within\n                    a container.\n                  properties:\n                    mountPath:\n                      description: Path within the container at which the volume should\n                        be mounted.  Must not contain ':'.\n                      type: string\n                    mountPropagation:\n                      description: mountPropagation determines how mounts are propagated\n                        from the host to container and the other way around. When\n                        not set, MountPropagationNone is used. This field is beta\n                        in 1.10.\n                      type: string\n                    name:\n                      description: This must match the Name of a Volume.\n                      type: string\n                    readOnly:\n                      description: Mounted read-only if true, read-write otherwise\n                        (false or unspecified). Defaults to false.\n                      type: boolean\n                    subPath:\n                      description: Path within the volume from which the container's\n                        volume should be mounted. Defaults to \"\" (volume's root).\n                      type: string\n                    subPathExpr:\n                      description: Expanded path within the volume from which the\n                        container's volume should be mounted. Behaves similarly to\n                        SubPath but environment variable references $(VAR_NAME) are\n                        expanded using the container's environment. Defaults to \"\"\n                        (volume's root). SubPathExpr and SubPath are mutually exclusive.\n                      type: string\n                  required:\n                  - mountPath\n                  - name\n                  type: object\n                type: array\n              volumes:\n                description: Volumes allows configuration of additional volumes on\n                  the output StatefulSet definition. Volumes specified will be appended\n                  to other volumes that are generated as a result of StorageSpec objects.\n                items:\n                  description: Volume represents a named volume in a pod that may\n                    be accessed by any container in the pod.\n                  properties:\n                    awsElasticBlockStore:\n                      description: 'AWSElasticBlockStore represents an AWS Disk resource\n                        that is attached to a kubelet''s host machine and then exposed\n                        to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore'\n                      properties:\n                        fsType:\n                          description: 'Filesystem type of the volume that you want\n                            to mount. Tip: Ensure that the filesystem type is supported\n                            by the host operating system. Examples: \"ext4\", \"xfs\",\n                            \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore\n                            TODO: how do we prevent errors in the filesystem from\n                            compromising the machine'\n                          type: string\n                        partition:\n                          description: 'The partition in the volume that you want\n                            to mount. If omitted, the default is to mount by volume\n                            name. Examples: For volume /dev/sda1, you specify the\n                            partition as \"1\". Similarly, the volume partition for\n                            /dev/sda is \"0\" (or you can leave the property empty).'\n                          format: int32\n                          type: integer\n                        readOnly:\n                          description: 'Specify \"true\" to force and set the ReadOnly\n                            property in VolumeMounts to \"true\". If omitted, the default\n                            is \"false\". More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore'\n                          type: boolean\n                        volumeID:\n                          description: 'Unique ID of the persistent disk resource\n                            in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore'\n                          type: string\n                      required:\n                      - volumeID\n                      type: object\n                    azureDisk:\n                      description: AzureDisk represents an Azure Data Disk mount on\n                        the host and bind mount to the pod.\n                      properties:\n                        cachingMode:\n                          description: 'Host Caching mode: None, Read Only, Read Write.'\n                          type: string\n                        diskName:\n                          description: The Name of the data disk in the blob storage\n                          type: string\n                        diskURI:\n                          description: The URI the data disk in the blob storage\n                          type: string\n                        fsType:\n                          description: Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                          type: string\n                        kind:\n                          description: 'Expected values Shared: multiple blob disks\n                            per storage account  Dedicated: single blob disk per storage\n                            account  Managed: azure managed data disk (only in managed\n                            availability set). defaults to shared'\n                          type: string\n                        readOnly:\n                          description: Defaults to false (read/write). ReadOnly here\n                            will force the ReadOnly setting in VolumeMounts.\n                          type: boolean\n                      required:\n                      - diskName\n                      - diskURI\n                      type: object\n                    azureFile:\n                      description: AzureFile represents an Azure File Service mount\n                        on the host and bind mount to the pod.\n                      properties:\n                        readOnly:\n                          description: Defaults to false (read/write). ReadOnly here\n                            will force the ReadOnly setting in VolumeMounts.\n                          type: boolean\n                        secretName:\n                          description: the name of secret that contains Azure Storage\n                            Account Name and Key\n                          type: string\n                        shareName:\n                          description: Share Name\n                          type: string\n                      required:\n                      - secretName\n                      - shareName\n                      type: object\n                    cephfs:\n                      description: CephFS represents a Ceph FS mount on the host that\n                        shares a pod's lifetime\n                      properties:\n                        monitors:\n                          description: 'Required: Monitors is a collection of Ceph\n                            monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it'\n                          items:\n                            type: string\n                          type: array\n                        path:\n                          description: 'Optional: Used as the mounted root, rather\n                            than the full Ceph tree, default is /'\n                          type: string\n                        readOnly:\n                          description: 'Optional: Defaults to false (read/write).\n                            ReadOnly here will force the ReadOnly setting in VolumeMounts.\n                            More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it'\n                          type: boolean\n                        secretFile:\n                          description: 'Optional: SecretFile is the path to key ring\n                            for User, default is /etc/ceph/user.secret More info:\n                            https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it'\n                          type: string\n                        secretRef:\n                          description: 'Optional: SecretRef is reference to the authentication\n                            secret for User, default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it'\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        user:\n                          description: 'Optional: User is the rados user name, default\n                            is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it'\n                          type: string\n                      required:\n                      - monitors\n                      type: object\n                    cinder:\n                      description: 'Cinder represents a cinder volume attached and\n                        mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md'\n                      properties:\n                        fsType:\n                          description: 'Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Examples:\n                            \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\"\n                            if unspecified. More info: https://examples.k8s.io/mysql-cinder-pd/README.md'\n                          type: string\n                        readOnly:\n                          description: 'Optional: Defaults to false (read/write).\n                            ReadOnly here will force the ReadOnly setting in VolumeMounts.\n                            More info: https://examples.k8s.io/mysql-cinder-pd/README.md'\n                          type: boolean\n                        secretRef:\n                          description: 'Optional: points to a secret object containing\n                            parameters used to connect to OpenStack.'\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        volumeID:\n                          description: 'volume id used to identify the volume in cinder.\n                            More info: https://examples.k8s.io/mysql-cinder-pd/README.md'\n                          type: string\n                      required:\n                      - volumeID\n                      type: object\n                    configMap:\n                      description: ConfigMap represents a configMap that should populate\n                        this volume\n                      properties:\n                        defaultMode:\n                          description: 'Optional: mode bits to use on created files\n                            by default. Must be a value between 0 and 0777. Defaults\n                            to 0644. Directories within the path are not affected\n                            by this setting. This might be in conflict with other\n                            options that affect the file mode, like fsGroup, and the\n                            result can be other mode bits set.'\n                          format: int32\n                          type: integer\n                        items:\n                          description: If unspecified, each key-value pair in the\n                            Data field of the referenced ConfigMap will be projected\n                            into the volume as a file whose name is the key and content\n                            is the value. If specified, the listed keys will be projected\n                            into the specified paths, and unlisted keys will not be\n                            present. If a key is specified which is not present in\n                            the ConfigMap, the volume setup will error unless it is\n                            marked optional. Paths must be relative and may not contain\n                            the '..' path or start with '..'.\n                          items:\n                            description: Maps a string key to a path within a volume.\n                            properties:\n                              key:\n                                description: The key to project.\n                                type: string\n                              mode:\n                                description: 'Optional: mode bits to use on this file,\n                                  must be a value between 0 and 0777. If not specified,\n                                  the volume defaultMode will be used. This might\n                                  be in conflict with other options that affect the\n                                  file mode, like fsGroup, and the result can be other\n                                  mode bits set.'\n                                format: int32\n                                type: integer\n                              path:\n                                description: The relative path of the file to map\n                                  the key to. May not be an absolute path. May not\n                                  contain the path element '..'. May not start with\n                                  the string '..'.\n                                type: string\n                            required:\n                            - key\n                            - path\n                            type: object\n                          type: array\n                        name:\n                          description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                            TODO: Add other useful fields. apiVersion, kind, uid?'\n                          type: string\n                        optional:\n                          description: Specify whether the ConfigMap or its keys must\n                            be defined\n                          type: boolean\n                      type: object\n                    csi:\n                      description: CSI (Container Storage Interface) represents storage\n                        that is handled by an external CSI driver (Alpha feature).\n                      properties:\n                        driver:\n                          description: Driver is the name of the CSI driver that handles\n                            this volume. Consult with your admin for the correct name\n                            as registered in the cluster.\n                          type: string\n                        fsType:\n                          description: Filesystem type to mount. Ex. \"ext4\", \"xfs\",\n                            \"ntfs\". If not provided, the empty value is passed to\n                            the associated CSI driver which will determine the default\n                            filesystem to apply.\n                          type: string\n                        nodePublishSecretRef:\n                          description: NodePublishSecretRef is a reference to the\n                            secret object containing sensitive information to pass\n                            to the CSI driver to complete the CSI NodePublishVolume\n                            and NodeUnpublishVolume calls. This field is optional,\n                            and  may be empty if no secret is required. If the secret\n                            object contains more than one secret, all secret references\n                            are passed.\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        readOnly:\n                          description: Specifies a read-only configuration for the\n                            volume. Defaults to false (read/write).\n                          type: boolean\n                        volumeAttributes:\n                          additionalProperties:\n                            type: string\n                          description: VolumeAttributes stores driver-specific properties\n                            that are passed to the CSI driver. Consult your driver's\n                            documentation for supported values.\n                          type: object\n                      required:\n                      - driver\n                      type: object\n                    downwardAPI:\n                      description: DownwardAPI represents downward API about the pod\n                        that should populate this volume\n                      properties:\n                        defaultMode:\n                          description: 'Optional: mode bits to use on created files\n                            by default. Must be a value between 0 and 0777. Defaults\n                            to 0644. Directories within the path are not affected\n                            by this setting. This might be in conflict with other\n                            options that affect the file mode, like fsGroup, and the\n                            result can be other mode bits set.'\n                          format: int32\n                          type: integer\n                        items:\n                          description: Items is a list of downward API volume file\n                          items:\n                            description: DownwardAPIVolumeFile represents information\n                              to create the file containing the pod field\n                            properties:\n                              fieldRef:\n                                description: 'Required: Selects a field of the pod:\n                                  only annotations, labels, name and namespace are\n                                  supported.'\n                                properties:\n                                  apiVersion:\n                                    description: Version of the schema the FieldPath\n                                      is written in terms of, defaults to \"v1\".\n                                    type: string\n                                  fieldPath:\n                                    description: Path of the field to select in the\n                                      specified API version.\n                                    type: string\n                                required:\n                                - fieldPath\n                                type: object\n                              mode:\n                                description: 'Optional: mode bits to use on this file,\n                                  must be a value between 0 and 0777. If not specified,\n                                  the volume defaultMode will be used. This might\n                                  be in conflict with other options that affect the\n                                  file mode, like fsGroup, and the result can be other\n                                  mode bits set.'\n                                format: int32\n                                type: integer\n                              path:\n                                description: 'Required: Path is  the relative path\n                                  name of the file to be created. Must not be absolute\n                                  or contain the ''..'' path. Must be utf-8 encoded.\n                                  The first item of the relative path must not start\n                                  with ''..'''\n                                type: string\n                              resourceFieldRef:\n                                description: 'Selects a resource of the container:\n                                  only resources limits and requests (limits.cpu,\n                                  limits.memory, requests.cpu and requests.memory)\n                                  are currently supported.'\n                                properties:\n                                  containerName:\n                                    description: 'Container name: required for volumes,\n                                      optional for env vars'\n                                    type: string\n                                  divisor:\n                                    anyOf:\n                                    - type: integer\n                                    - type: string\n                                    description: Specifies the output format of the\n                                      exposed resources, defaults to \"1\"\n                                    pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                    x-kubernetes-int-or-string: true\n                                  resource:\n                                    description: 'Required: resource to select'\n                                    type: string\n                                required:\n                                - resource\n                                type: object\n                            required:\n                            - path\n                            type: object\n                          type: array\n                      type: object\n                    emptyDir:\n                      description: 'EmptyDir represents a temporary directory that\n                        shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir'\n                      properties:\n                        medium:\n                          description: 'What type of storage medium should back this\n                            directory. The default is \"\" which means to use the node''s\n                            default medium. Must be an empty string (default) or Memory.\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir'\n                          type: string\n                        sizeLimit:\n                          anyOf:\n                          - type: integer\n                          - type: string\n                          description: 'Total amount of local storage required for\n                            this EmptyDir volume. The size limit is also applicable\n                            for memory medium. The maximum usage on memory medium\n                            EmptyDir would be the minimum value between the SizeLimit\n                            specified here and the sum of memory limits of all containers\n                            in a pod. The default is nil which means that the limit\n                            is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir'\n                          pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                          x-kubernetes-int-or-string: true\n                      type: object\n                    fc:\n                      description: FC represents a Fibre Channel resource that is\n                        attached to a kubelet's host machine and then exposed to the\n                        pod.\n                      properties:\n                        fsType:\n                          description: 'Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                            TODO: how do we prevent errors in the filesystem from\n                            compromising the machine'\n                          type: string\n                        lun:\n                          description: 'Optional: FC target lun number'\n                          format: int32\n                          type: integer\n                        readOnly:\n                          description: 'Optional: Defaults to false (read/write).\n                            ReadOnly here will force the ReadOnly setting in VolumeMounts.'\n                          type: boolean\n                        targetWWNs:\n                          description: 'Optional: FC target worldwide names (WWNs)'\n                          items:\n                            type: string\n                          type: array\n                        wwids:\n                          description: 'Optional: FC volume world wide identifiers\n                            (wwids) Either wwids or combination of targetWWNs and\n                            lun must be set, but not both simultaneously.'\n                          items:\n                            type: string\n                          type: array\n                      type: object\n                    flexVolume:\n                      description: FlexVolume represents a generic volume resource\n                        that is provisioned/attached using an exec based plugin.\n                      properties:\n                        driver:\n                          description: Driver is the name of the driver to use for\n                            this volume.\n                          type: string\n                        fsType:\n                          description: Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". The default filesystem depends on FlexVolume\n                            script.\n                          type: string\n                        options:\n                          additionalProperties:\n                            type: string\n                          description: 'Optional: Extra command options if any.'\n                          type: object\n                        readOnly:\n                          description: 'Optional: Defaults to false (read/write).\n                            ReadOnly here will force the ReadOnly setting in VolumeMounts.'\n                          type: boolean\n                        secretRef:\n                          description: 'Optional: SecretRef is reference to the secret\n                            object containing sensitive information to pass to the\n                            plugin scripts. This may be empty if no secret object\n                            is specified. If the secret object contains more than\n                            one secret, all secrets are passed to the plugin scripts.'\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                      required:\n                      - driver\n                      type: object\n                    flocker:\n                      description: Flocker represents a Flocker volume attached to\n                        a kubelet's host machine. This depends on the Flocker control\n                        service being running\n                      properties:\n                        datasetName:\n                          description: Name of the dataset stored as metadata -> name\n                            on the dataset for Flocker should be considered as deprecated\n                          type: string\n                        datasetUUID:\n                          description: UUID of the dataset. This is unique identifier\n                            of a Flocker dataset\n                          type: string\n                      type: object\n                    gcePersistentDisk:\n                      description: 'GCEPersistentDisk represents a GCE Disk resource\n                        that is attached to a kubelet''s host machine and then exposed\n                        to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk'\n                      properties:\n                        fsType:\n                          description: 'Filesystem type of the volume that you want\n                            to mount. Tip: Ensure that the filesystem type is supported\n                            by the host operating system. Examples: \"ext4\", \"xfs\",\n                            \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk\n                            TODO: how do we prevent errors in the filesystem from\n                            compromising the machine'\n                          type: string\n                        partition:\n                          description: 'The partition in the volume that you want\n                            to mount. If omitted, the default is to mount by volume\n                            name. Examples: For volume /dev/sda1, you specify the\n                            partition as \"1\". Similarly, the volume partition for\n                            /dev/sda is \"0\" (or you can leave the property empty).\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk'\n                          format: int32\n                          type: integer\n                        pdName:\n                          description: 'Unique name of the PD resource in GCE. Used\n                            to identify the disk in GCE. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk'\n                          type: string\n                        readOnly:\n                          description: 'ReadOnly here will force the ReadOnly setting\n                            in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk'\n                          type: boolean\n                      required:\n                      - pdName\n                      type: object\n                    gitRepo:\n                      description: 'GitRepo represents a git repository at a particular\n                        revision. DEPRECATED: GitRepo is deprecated. To provision\n                        a container with a git repo, mount an EmptyDir into an InitContainer\n                        that clones the repo using git, then mount the EmptyDir into\n                        the Pod''s container.'\n                      properties:\n                        directory:\n                          description: Target directory name. Must not contain or\n                            start with '..'.  If '.' is supplied, the volume directory\n                            will be the git repository.  Otherwise, if specified,\n                            the volume will contain the git repository in the subdirectory\n                            with the given name.\n                          type: string\n                        repository:\n                          description: Repository URL\n                          type: string\n                        revision:\n                          description: Commit hash for the specified revision.\n                          type: string\n                      required:\n                      - repository\n                      type: object\n                    glusterfs:\n                      description: 'Glusterfs represents a Glusterfs mount on the\n                        host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md'\n                      properties:\n                        endpoints:\n                          description: 'EndpointsName is the endpoint name that details\n                            Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod'\n                          type: string\n                        path:\n                          description: 'Path is the Glusterfs volume path. More info:\n                            https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod'\n                          type: string\n                        readOnly:\n                          description: 'ReadOnly here will force the Glusterfs volume\n                            to be mounted with read-only permissions. Defaults to\n                            false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod'\n                          type: boolean\n                      required:\n                      - endpoints\n                      - path\n                      type: object\n                    hostPath:\n                      description: 'HostPath represents a pre-existing file or directory\n                        on the host machine that is directly exposed to the container.\n                        This is generally used for system agents or other privileged\n                        things that are allowed to see the host machine. Most containers\n                        will NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath\n                        --- TODO(jonesdl) We need to restrict who can use host directory\n                        mounts and who can/can not mount host directories as read/write.'\n                      properties:\n                        path:\n                          description: 'Path of the directory on the host. If the\n                            path is a symlink, it will follow the link to the real\n                            path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath'\n                          type: string\n                        type:\n                          description: 'Type for HostPath Volume Defaults to \"\" More\n                            info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath'\n                          type: string\n                      required:\n                      - path\n                      type: object\n                    iscsi:\n                      description: 'ISCSI represents an ISCSI Disk resource that is\n                        attached to a kubelet''s host machine and then exposed to\n                        the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md'\n                      properties:\n                        chapAuthDiscovery:\n                          description: whether support iSCSI Discovery CHAP authentication\n                          type: boolean\n                        chapAuthSession:\n                          description: whether support iSCSI Session CHAP authentication\n                          type: boolean\n                        fsType:\n                          description: 'Filesystem type of the volume that you want\n                            to mount. Tip: Ensure that the filesystem type is supported\n                            by the host operating system. Examples: \"ext4\", \"xfs\",\n                            \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi\n                            TODO: how do we prevent errors in the filesystem from\n                            compromising the machine'\n                          type: string\n                        initiatorName:\n                          description: Custom iSCSI Initiator Name. If initiatorName\n                            is specified with iscsiInterface simultaneously, new iSCSI\n                            interface <target portal>:<volume name> will be created\n                            for the connection.\n                          type: string\n                        iqn:\n                          description: Target iSCSI Qualified Name.\n                          type: string\n                        iscsiInterface:\n                          description: iSCSI Interface Name that uses an iSCSI transport.\n                            Defaults to 'default' (tcp).\n                          type: string\n                        lun:\n                          description: iSCSI Target Lun number.\n                          format: int32\n                          type: integer\n                        portals:\n                          description: iSCSI Target Portal List. The portal is either\n                            an IP or ip_addr:port if the port is other than default\n                            (typically TCP ports 860 and 3260).\n                          items:\n                            type: string\n                          type: array\n                        readOnly:\n                          description: ReadOnly here will force the ReadOnly setting\n                            in VolumeMounts. Defaults to false.\n                          type: boolean\n                        secretRef:\n                          description: CHAP Secret for iSCSI target and initiator\n                            authentication\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        targetPortal:\n                          description: iSCSI Target Portal. The Portal is either an\n                            IP or ip_addr:port if the port is other than default (typically\n                            TCP ports 860 and 3260).\n                          type: string\n                      required:\n                      - iqn\n                      - lun\n                      - targetPortal\n                      type: object\n                    name:\n                      description: 'Volume''s name. Must be a DNS_LABEL and unique\n                        within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'\n                      type: string\n                    nfs:\n                      description: 'NFS represents an NFS mount on the host that shares\n                        a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs'\n                      properties:\n                        path:\n                          description: 'Path that is exported by the NFS server. More\n                            info: https://kubernetes.io/docs/concepts/storage/volumes#nfs'\n                          type: string\n                        readOnly:\n                          description: 'ReadOnly here will force the NFS export to\n                            be mounted with read-only permissions. Defaults to false.\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs'\n                          type: boolean\n                        server:\n                          description: 'Server is the hostname or IP address of the\n                            NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs'\n                          type: string\n                      required:\n                      - path\n                      - server\n                      type: object\n                    persistentVolumeClaim:\n                      description: 'PersistentVolumeClaimVolumeSource represents a\n                        reference to a PersistentVolumeClaim in the same namespace.\n                        More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'\n                      properties:\n                        claimName:\n                          description: 'ClaimName is the name of a PersistentVolumeClaim\n                            in the same namespace as the pod using this volume. More\n                            info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'\n                          type: string\n                        readOnly:\n                          description: Will force the ReadOnly setting in VolumeMounts.\n                            Default false.\n                          type: boolean\n                      required:\n                      - claimName\n                      type: object\n                    photonPersistentDisk:\n                      description: PhotonPersistentDisk represents a PhotonController\n                        persistent disk attached and mounted on kubelets host machine\n                      properties:\n                        fsType:\n                          description: Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                          type: string\n                        pdID:\n                          description: ID that identifies Photon Controller persistent\n                            disk\n                          type: string\n                      required:\n                      - pdID\n                      type: object\n                    portworxVolume:\n                      description: PortworxVolume represents a portworx volume attached\n                        and mounted on kubelets host machine\n                      properties:\n                        fsType:\n                          description: FSType represents the filesystem type to mount\n                            Must be a filesystem type supported by the host operating\n                            system. Ex. \"ext4\", \"xfs\". Implicitly inferred to be \"ext4\"\n                            if unspecified.\n                          type: string\n                        readOnly:\n                          description: Defaults to false (read/write). ReadOnly here\n                            will force the ReadOnly setting in VolumeMounts.\n                          type: boolean\n                        volumeID:\n                          description: VolumeID uniquely identifies a Portworx volume\n                          type: string\n                      required:\n                      - volumeID\n                      type: object\n                    projected:\n                      description: Items for all in one resources secrets, configmaps,\n                        and downward API\n                      properties:\n                        defaultMode:\n                          description: Mode bits to use on created files by default.\n                            Must be a value between 0 and 0777. Directories within\n                            the path are not affected by this setting. This might\n                            be in conflict with other options that affect the file\n                            mode, like fsGroup, and the result can be other mode bits\n                            set.\n                          format: int32\n                          type: integer\n                        sources:\n                          description: list of volume projections\n                          items:\n                            description: Projection that may be projected along with\n                              other supported volume types\n                            properties:\n                              configMap:\n                                description: information about the configMap data\n                                  to project\n                                properties:\n                                  items:\n                                    description: If unspecified, each key-value pair\n                                      in the Data field of the referenced ConfigMap\n                                      will be projected into the volume as a file\n                                      whose name is the key and content is the value.\n                                      If specified, the listed keys will be projected\n                                      into the specified paths, and unlisted keys\n                                      will not be present. If a key is specified which\n                                      is not present in the ConfigMap, the volume\n                                      setup will error unless it is marked optional.\n                                      Paths must be relative and may not contain the\n                                      '..' path or start with '..'.\n                                    items:\n                                      description: Maps a string key to a path within\n                                        a volume.\n                                      properties:\n                                        key:\n                                          description: The key to project.\n                                          type: string\n                                        mode:\n                                          description: 'Optional: mode bits to use\n                                            on this file, must be a value between\n                                            0 and 0777. If not specified, the volume\n                                            defaultMode will be used. This might be\n                                            in conflict with other options that affect\n                                            the file mode, like fsGroup, and the result\n                                            can be other mode bits set.'\n                                          format: int32\n                                          type: integer\n                                        path:\n                                          description: The relative path of the file\n                                            to map the key to. May not be an absolute\n                                            path. May not contain the path element\n                                            '..'. May not start with the string '..'.\n                                          type: string\n                                      required:\n                                      - key\n                                      - path\n                                      type: object\n                                    type: array\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the ConfigMap or\n                                      its keys must be defined\n                                    type: boolean\n                                type: object\n                              downwardAPI:\n                                description: information about the downwardAPI data\n                                  to project\n                                properties:\n                                  items:\n                                    description: Items is a list of DownwardAPIVolume\n                                      file\n                                    items:\n                                      description: DownwardAPIVolumeFile represents\n                                        information to create the file containing\n                                        the pod field\n                                      properties:\n                                        fieldRef:\n                                          description: 'Required: Selects a field\n                                            of the pod: only annotations, labels,\n                                            name and namespace are supported.'\n                                          properties:\n                                            apiVersion:\n                                              description: Version of the schema the\n                                                FieldPath is written in terms of,\n                                                defaults to \"v1\".\n                                              type: string\n                                            fieldPath:\n                                              description: Path of the field to select\n                                                in the specified API version.\n                                              type: string\n                                          required:\n                                          - fieldPath\n                                          type: object\n                                        mode:\n                                          description: 'Optional: mode bits to use\n                                            on this file, must be a value between\n                                            0 and 0777. If not specified, the volume\n                                            defaultMode will be used. This might be\n                                            in conflict with other options that affect\n                                            the file mode, like fsGroup, and the result\n                                            can be other mode bits set.'\n                                          format: int32\n                                          type: integer\n                                        path:\n                                          description: 'Required: Path is  the relative\n                                            path name of the file to be created. Must\n                                            not be absolute or contain the ''..''\n                                            path. Must be utf-8 encoded. The first\n                                            item of the relative path must not start\n                                            with ''..'''\n                                          type: string\n                                        resourceFieldRef:\n                                          description: 'Selects a resource of the\n                                            container: only resources limits and requests\n                                            (limits.cpu, limits.memory, requests.cpu\n                                            and requests.memory) are currently supported.'\n                                          properties:\n                                            containerName:\n                                              description: 'Container name: required\n                                                for volumes, optional for env vars'\n                                              type: string\n                                            divisor:\n                                              anyOf:\n                                              - type: integer\n                                              - type: string\n                                              description: Specifies the output format\n                                                of the exposed resources, defaults\n                                                to \"1\"\n                                              pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                              x-kubernetes-int-or-string: true\n                                            resource:\n                                              description: 'Required: resource to\n                                                select'\n                                              type: string\n                                          required:\n                                          - resource\n                                          type: object\n                                      required:\n                                      - path\n                                      type: object\n                                    type: array\n                                type: object\n                              secret:\n                                description: information about the secret data to\n                                  project\n                                properties:\n                                  items:\n                                    description: If unspecified, each key-value pair\n                                      in the Data field of the referenced Secret will\n                                      be projected into the volume as a file whose\n                                      name is the key and content is the value. If\n                                      specified, the listed keys will be projected\n                                      into the specified paths, and unlisted keys\n                                      will not be present. If a key is specified which\n                                      is not present in the Secret, the volume setup\n                                      will error unless it is marked optional. Paths\n                                      must be relative and may not contain the '..'\n                                      path or start with '..'.\n                                    items:\n                                      description: Maps a string key to a path within\n                                        a volume.\n                                      properties:\n                                        key:\n                                          description: The key to project.\n                                          type: string\n                                        mode:\n                                          description: 'Optional: mode bits to use\n                                            on this file, must be a value between\n                                            0 and 0777. If not specified, the volume\n                                            defaultMode will be used. This might be\n                                            in conflict with other options that affect\n                                            the file mode, like fsGroup, and the result\n                                            can be other mode bits set.'\n                                          format: int32\n                                          type: integer\n                                        path:\n                                          description: The relative path of the file\n                                            to map the key to. May not be an absolute\n                                            path. May not contain the path element\n                                            '..'. May not start with the string '..'.\n                                          type: string\n                                      required:\n                                      - key\n                                      - path\n                                      type: object\n                                    type: array\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the Secret or its\n                                      key must be defined\n                                    type: boolean\n                                type: object\n                              serviceAccountToken:\n                                description: information about the serviceAccountToken\n                                  data to project\n                                properties:\n                                  audience:\n                                    description: Audience is the intended audience\n                                      of the token. A recipient of a token must identify\n                                      itself with an identifier specified in the audience\n                                      of the token, and otherwise should reject the\n                                      token. The audience defaults to the identifier\n                                      of the apiserver.\n                                    type: string\n                                  expirationSeconds:\n                                    description: ExpirationSeconds is the requested\n                                      duration of validity of the service account\n                                      token. As the token approaches expiration, the\n                                      kubelet volume plugin will proactively rotate\n                                      the service account token. The kubelet will\n                                      start trying to rotate the token if the token\n                                      is older than 80 percent of its time to live\n                                      or if the token is older than 24 hours.Defaults\n                                      to 1 hour and must be at least 10 minutes.\n                                    format: int64\n                                    type: integer\n                                  path:\n                                    description: Path is the path relative to the\n                                      mount point of the file to project the token\n                                      into.\n                                    type: string\n                                required:\n                                - path\n                                type: object\n                            type: object\n                          type: array\n                      required:\n                      - sources\n                      type: object\n                    quobyte:\n                      description: Quobyte represents a Quobyte mount on the host\n                        that shares a pod's lifetime\n                      properties:\n                        group:\n                          description: Group to map volume access to Default is no\n                            group\n                          type: string\n                        readOnly:\n                          description: ReadOnly here will force the Quobyte volume\n                            to be mounted with read-only permissions. Defaults to\n                            false.\n                          type: boolean\n                        registry:\n                          description: Registry represents a single or multiple Quobyte\n                            Registry services specified as a string as host:port pair\n                            (multiple entries are separated with commas) which acts\n                            as the central registry for volumes\n                          type: string\n                        tenant:\n                          description: Tenant owning the given Quobyte volume in the\n                            Backend Used with dynamically provisioned Quobyte volumes,\n                            value is set by the plugin\n                          type: string\n                        user:\n                          description: User to map volume access to Defaults to serivceaccount\n                            user\n                          type: string\n                        volume:\n                          description: Volume is a string that references an already\n                            created Quobyte volume by name.\n                          type: string\n                      required:\n                      - registry\n                      - volume\n                      type: object\n                    rbd:\n                      description: 'RBD represents a Rados Block Device mount on the\n                        host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md'\n                      properties:\n                        fsType:\n                          description: 'Filesystem type of the volume that you want\n                            to mount. Tip: Ensure that the filesystem type is supported\n                            by the host operating system. Examples: \"ext4\", \"xfs\",\n                            \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd\n                            TODO: how do we prevent errors in the filesystem from\n                            compromising the machine'\n                          type: string\n                        image:\n                          description: 'The rados image name. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          type: string\n                        keyring:\n                          description: 'Keyring is the path to key ring for RBDUser.\n                            Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          type: string\n                        monitors:\n                          description: 'A collection of Ceph monitors. More info:\n                            https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          items:\n                            type: string\n                          type: array\n                        pool:\n                          description: 'The rados pool name. Default is rbd. More\n                            info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          type: string\n                        readOnly:\n                          description: 'ReadOnly here will force the ReadOnly setting\n                            in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          type: boolean\n                        secretRef:\n                          description: 'SecretRef is name of the authentication secret\n                            for RBDUser. If provided overrides keyring. Default is\n                            nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        user:\n                          description: 'The rados user name. Default is admin. More\n                            info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          type: string\n                      required:\n                      - image\n                      - monitors\n                      type: object\n                    scaleIO:\n                      description: ScaleIO represents a ScaleIO persistent volume\n                        attached and mounted on Kubernetes nodes.\n                      properties:\n                        fsType:\n                          description: Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". Default is \"xfs\".\n                          type: string\n                        gateway:\n                          description: The host address of the ScaleIO API Gateway.\n                          type: string\n                        protectionDomain:\n                          description: The name of the ScaleIO Protection Domain for\n                            the configured storage.\n                          type: string\n                        readOnly:\n                          description: Defaults to false (read/write). ReadOnly here\n                            will force the ReadOnly setting in VolumeMounts.\n                          type: boolean\n                        secretRef:\n                          description: SecretRef references to the secret for ScaleIO\n                            user and other sensitive information. If this is not provided,\n                            Login operation will fail.\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        sslEnabled:\n                          description: Flag to enable/disable SSL communication with\n                            Gateway, default false\n                          type: boolean\n                        storageMode:\n                          description: Indicates whether the storage for a volume\n                            should be ThickProvisioned or ThinProvisioned. Default\n                            is ThinProvisioned.\n                          type: string\n                        storagePool:\n                          description: The ScaleIO Storage Pool associated with the\n                            protection domain.\n                          type: string\n                        system:\n                          description: The name of the storage system as configured\n                            in ScaleIO.\n                          type: string\n                        volumeName:\n                          description: The name of a volume already created in the\n                            ScaleIO system that is associated with this volume source.\n                          type: string\n                      required:\n                      - gateway\n                      - secretRef\n                      - system\n                      type: object\n                    secret:\n                      description: 'Secret represents a secret that should populate\n                        this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret'\n                      properties:\n                        defaultMode:\n                          description: 'Optional: mode bits to use on created files\n                            by default. Must be a value between 0 and 0777. Defaults\n                            to 0644. Directories within the path are not affected\n                            by this setting. This might be in conflict with other\n                            options that affect the file mode, like fsGroup, and the\n                            result can be other mode bits set.'\n                          format: int32\n                          type: integer\n                        items:\n                          description: If unspecified, each key-value pair in the\n                            Data field of the referenced Secret will be projected\n                            into the volume as a file whose name is the key and content\n                            is the value. If specified, the listed keys will be projected\n                            into the specified paths, and unlisted keys will not be\n                            present. If a key is specified which is not present in\n                            the Secret, the volume setup will error unless it is marked\n                            optional. Paths must be relative and may not contain the\n                            '..' path or start with '..'.\n                          items:\n                            description: Maps a string key to a path within a volume.\n                            properties:\n                              key:\n                                description: The key to project.\n                                type: string\n                              mode:\n                                description: 'Optional: mode bits to use on this file,\n                                  must be a value between 0 and 0777. If not specified,\n                                  the volume defaultMode will be used. This might\n                                  be in conflict with other options that affect the\n                                  file mode, like fsGroup, and the result can be other\n                                  mode bits set.'\n                                format: int32\n                                type: integer\n                              path:\n                                description: The relative path of the file to map\n                                  the key to. May not be an absolute path. May not\n                                  contain the path element '..'. May not start with\n                                  the string '..'.\n                                type: string\n                            required:\n                            - key\n                            - path\n                            type: object\n                          type: array\n                        optional:\n                          description: Specify whether the Secret or its keys must\n                            be defined\n                          type: boolean\n                        secretName:\n                          description: 'Name of the secret in the pod''s namespace\n                            to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret'\n                          type: string\n                      type: object\n                    storageos:\n                      description: StorageOS represents a StorageOS volume attached\n                        and mounted on Kubernetes nodes.\n                      properties:\n                        fsType:\n                          description: Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                          type: string\n                        readOnly:\n                          description: Defaults to false (read/write). ReadOnly here\n                            will force the ReadOnly setting in VolumeMounts.\n                          type: boolean\n                        secretRef:\n                          description: SecretRef specifies the secret to use for obtaining\n                            the StorageOS API credentials.  If not specified, default\n                            values will be attempted.\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        volumeName:\n                          description: VolumeName is the human-readable name of the\n                            StorageOS volume.  Volume names are only unique within\n                            a namespace.\n                          type: string\n                        volumeNamespace:\n                          description: VolumeNamespace specifies the scope of the\n                            volume within StorageOS.  If no namespace is specified\n                            then the Pod's namespace will be used.  This allows the\n                            Kubernetes name scoping to be mirrored within StorageOS\n                            for tighter integration. Set VolumeName to any name to\n                            override the default behaviour. Set to \"default\" if you\n                            are not using namespaces within StorageOS. Namespaces\n                            that do not pre-exist within StorageOS will be created.\n                          type: string\n                      type: object\n                    vsphereVolume:\n                      description: VsphereVolume represents a vSphere volume attached\n                        and mounted on kubelets host machine\n                      properties:\n                        fsType:\n                          description: Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                          type: string\n                        storagePolicyID:\n                          description: Storage Policy Based Management (SPBM) profile\n                            ID associated with the StoragePolicyName.\n                          type: string\n                        storagePolicyName:\n                          description: Storage Policy Based Management (SPBM) profile\n                            name.\n                          type: string\n                        volumePath:\n                          description: Path that identifies vSphere volume vmdk\n                          type: string\n                      required:\n                      - volumePath\n                      type: object\n                  required:\n                  - name\n                  type: object\n                type: array\n            type: object\n          status:\n            description: 'Most recent observed status of the Alertmanager cluster.\n              Read-only. Not included when requesting from the apiserver, only from\n              the Prometheus Operator API itself. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status'\n            properties:\n              availableReplicas:\n                description: Total number of available pods (ready for at least minReadySeconds)\n                  targeted by this Alertmanager cluster.\n                format: int32\n                type: integer\n              paused:\n                description: Represents whether any actions on the underlying managed\n                  objects are being performed. Only delete actions will be performed.\n                type: boolean\n              replicas:\n                description: Total number of non-terminated pods targeted by this\n                  Alertmanager cluster (their labels match the selector).\n                format: int32\n                type: integer\n              unavailableReplicas:\n                description: Total number of unavailable pods targeted by this Alertmanager\n                  cluster.\n                format: int32\n                type: integer\n              updatedReplicas:\n                description: Total number of non-terminated pods targeted by this\n                  Alertmanager cluster that have the desired version spec.\n                format: int32\n                type: integer\n            required:\n            - availableReplicas\n            - paused\n            - replicas\n            - unavailableReplicas\n            - updatedReplicas\n            type: object\n        required:\n        - spec\n        type: object\n    served: true\n    storage: true\n    subresources: {}\nstatus:\n  acceptedNames:\n    kind: \"\"\n    plural: \"\"\n  conditions: []\n  storedVersions: []\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/crds/crd-podmonitors.yaml",
    "content": "# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml\n\n---\napiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.4.1\n  creationTimestamp: null\n  name: podmonitors.monitoring.coreos.com\nspec:\n  group: monitoring.coreos.com\n  names:\n    categories:\n    - prometheus-operator\n    kind: PodMonitor\n    listKind: PodMonitorList\n    plural: podmonitors\n    singular: podmonitor\n  scope: Namespaced\n  versions:\n  - name: v1\n    schema:\n      openAPIV3Schema:\n        description: PodMonitor defines monitoring for a set of pods.\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: Specification of desired Pod selection for target discovery\n              by Prometheus.\n            properties:\n              jobLabel:\n                description: The label to use to retrieve the job name from.\n                type: string\n              namespaceSelector:\n                description: Selector to select which namespaces the Endpoints objects\n                  are discovered from.\n                properties:\n                  any:\n                    description: Boolean describing whether all namespaces are selected\n                      in contrast to a list restricting them.\n                    type: boolean\n                  matchNames:\n                    description: List of namespace names.\n                    items:\n                      type: string\n                    type: array\n                type: object\n              podMetricsEndpoints:\n                description: A list of endpoints allowed as part of this PodMonitor.\n                items:\n                  description: PodMetricsEndpoint defines a scrapeable endpoint of\n                    a Kubernetes Pod serving Prometheus metrics.\n                  properties:\n                    basicAuth:\n                      description: 'BasicAuth allow an endpoint to authenticate over\n                        basic authentication. More info: https://prometheus.io/docs/operating/configuration/#endpoint'\n                      properties:\n                        password:\n                          description: The secret in the service monitor namespace\n                            that contains the password for authentication.\n                          properties:\n                            key:\n                              description: The key of the secret to select from.  Must\n                                be a valid secret key.\n                              type: string\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                            optional:\n                              description: Specify whether the Secret or its key must\n                                be defined\n                              type: boolean\n                          required:\n                          - key\n                          type: object\n                        username:\n                          description: The secret in the service monitor namespace\n                            that contains the username for authentication.\n                          properties:\n                            key:\n                              description: The key of the secret to select from.  Must\n                                be a valid secret key.\n                              type: string\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                            optional:\n                              description: Specify whether the Secret or its key must\n                                be defined\n                              type: boolean\n                          required:\n                          - key\n                          type: object\n                      type: object\n                    bearerTokenSecret:\n                      description: Secret to mount to read bearer token for scraping\n                        targets. The secret needs to be in the same namespace as the\n                        pod monitor and accessible by the Prometheus Operator.\n                      properties:\n                        key:\n                          description: The key of the secret to select from.  Must\n                            be a valid secret key.\n                          type: string\n                        name:\n                          description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                            TODO: Add other useful fields. apiVersion, kind, uid?'\n                          type: string\n                        optional:\n                          description: Specify whether the Secret or its key must\n                            be defined\n                          type: boolean\n                      required:\n                      - key\n                      type: object\n                    honorLabels:\n                      description: HonorLabels chooses the metric's labels on collisions\n                        with target labels.\n                      type: boolean\n                    honorTimestamps:\n                      description: HonorTimestamps controls whether Prometheus respects\n                        the timestamps present in scraped data.\n                      type: boolean\n                    interval:\n                      description: Interval at which metrics should be scraped\n                      type: string\n                    metricRelabelings:\n                      description: MetricRelabelConfigs to apply to samples before\n                        ingestion.\n                      items:\n                        description: 'RelabelConfig allows dynamic rewriting of the\n                          label set, being applied to samples before ingestion. It\n                          defines `<metric_relabel_configs>`-section of Prometheus\n                          configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs'\n                        properties:\n                          action:\n                            description: Action to perform based on regex matching.\n                              Default is 'replace'\n                            type: string\n                          modulus:\n                            description: Modulus to take of the hash of the source\n                              label values.\n                            format: int64\n                            type: integer\n                          regex:\n                            description: Regular expression against which the extracted\n                              value is matched. Default is '(.*)'\n                            type: string\n                          replacement:\n                            description: Replacement value against which a regex replace\n                              is performed if the regular expression matches. Regex\n                              capture groups are available. Default is '$1'\n                            type: string\n                          separator:\n                            description: Separator placed between concatenated source\n                              label values. default is ';'.\n                            type: string\n                          sourceLabels:\n                            description: The source labels select values from existing\n                              labels. Their content is concatenated using the configured\n                              separator and matched against the configured regular\n                              expression for the replace, keep, and drop actions.\n                            items:\n                              type: string\n                            type: array\n                          targetLabel:\n                            description: Label to which the resulting value is written\n                              in a replace action. It is mandatory for replace actions.\n                              Regex capture groups are available.\n                            type: string\n                        type: object\n                      type: array\n                    params:\n                      additionalProperties:\n                        items:\n                          type: string\n                        type: array\n                      description: Optional HTTP URL parameters\n                      type: object\n                    path:\n                      description: HTTP path to scrape for metrics.\n                      type: string\n                    port:\n                      description: Name of the pod port this endpoint refers to. Mutually\n                        exclusive with targetPort.\n                      type: string\n                    proxyUrl:\n                      description: ProxyURL eg http://proxyserver:2195 Directs scrapes\n                        to proxy through this endpoint.\n                      type: string\n                    relabelings:\n                      description: 'RelabelConfigs to apply to samples before scraping.\n                        Prometheus Operator automatically adds relabelings for a few\n                        standard Kubernetes fields and replaces original scrape job\n                        name with __tmp_prometheus_job_name. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config'\n                      items:\n                        description: 'RelabelConfig allows dynamic rewriting of the\n                          label set, being applied to samples before ingestion. It\n                          defines `<metric_relabel_configs>`-section of Prometheus\n                          configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs'\n                        properties:\n                          action:\n                            description: Action to perform based on regex matching.\n                              Default is 'replace'\n                            type: string\n                          modulus:\n                            description: Modulus to take of the hash of the source\n                              label values.\n                            format: int64\n                            type: integer\n                          regex:\n                            description: Regular expression against which the extracted\n                              value is matched. Default is '(.*)'\n                            type: string\n                          replacement:\n                            description: Replacement value against which a regex replace\n                              is performed if the regular expression matches. Regex\n                              capture groups are available. Default is '$1'\n                            type: string\n                          separator:\n                            description: Separator placed between concatenated source\n                              label values. default is ';'.\n                            type: string\n                          sourceLabels:\n                            description: The source labels select values from existing\n                              labels. Their content is concatenated using the configured\n                              separator and matched against the configured regular\n                              expression for the replace, keep, and drop actions.\n                            items:\n                              type: string\n                            type: array\n                          targetLabel:\n                            description: Label to which the resulting value is written\n                              in a replace action. It is mandatory for replace actions.\n                              Regex capture groups are available.\n                            type: string\n                        type: object\n                      type: array\n                    scheme:\n                      description: HTTP scheme to use for scraping.\n                      type: string\n                    scrapeTimeout:\n                      description: Timeout after which the scrape is ended\n                      type: string\n                    targetPort:\n                      anyOf:\n                      - type: integer\n                      - type: string\n                      description: 'Deprecated: Use ''port'' instead.'\n                      x-kubernetes-int-or-string: true\n                    tlsConfig:\n                      description: TLS configuration to use when scraping the endpoint.\n                      properties:\n                        ca:\n                          description: Struct containing the CA cert to use for the\n                            targets.\n                          properties:\n                            configMap:\n                              description: ConfigMap containing data to use for the\n                                targets.\n                              properties:\n                                key:\n                                  description: The key to select.\n                                  type: string\n                                name:\n                                  description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                    TODO: Add other useful fields. apiVersion, kind,\n                                    uid?'\n                                  type: string\n                                optional:\n                                  description: Specify whether the ConfigMap or its\n                                    key must be defined\n                                  type: boolean\n                              required:\n                              - key\n                              type: object\n                            secret:\n                              description: Secret containing data to use for the targets.\n                              properties:\n                                key:\n                                  description: The key of the secret to select from.  Must\n                                    be a valid secret key.\n                                  type: string\n                                name:\n                                  description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                    TODO: Add other useful fields. apiVersion, kind,\n                                    uid?'\n                                  type: string\n                                optional:\n                                  description: Specify whether the Secret or its key\n                                    must be defined\n                                  type: boolean\n                              required:\n                              - key\n                              type: object\n                          type: object\n                        cert:\n                          description: Struct containing the client cert file for\n                            the targets.\n                          properties:\n                            configMap:\n                              description: ConfigMap containing data to use for the\n                                targets.\n                              properties:\n                                key:\n                                  description: The key to select.\n                                  type: string\n                                name:\n                                  description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                    TODO: Add other useful fields. apiVersion, kind,\n                                    uid?'\n                                  type: string\n                                optional:\n                                  description: Specify whether the ConfigMap or its\n                                    key must be defined\n                                  type: boolean\n                              required:\n                              - key\n                              type: object\n                            secret:\n                              description: Secret containing data to use for the targets.\n                              properties:\n                                key:\n                                  description: The key of the secret to select from.  Must\n                                    be a valid secret key.\n                                  type: string\n                                name:\n                                  description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                    TODO: Add other useful fields. apiVersion, kind,\n                                    uid?'\n                                  type: string\n                                optional:\n                                  description: Specify whether the Secret or its key\n                                    must be defined\n                                  type: boolean\n                              required:\n                              - key\n                              type: object\n                          type: object\n                        insecureSkipVerify:\n                          description: Disable target certificate validation.\n                          type: boolean\n                        keySecret:\n                          description: Secret containing the client key file for the\n                            targets.\n                          properties:\n                            key:\n                              description: The key of the secret to select from.  Must\n                                be a valid secret key.\n                              type: string\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                            optional:\n                              description: Specify whether the Secret or its key must\n                                be defined\n                              type: boolean\n                          required:\n                          - key\n                          type: object\n                        serverName:\n                          description: Used to verify the hostname for the targets.\n                          type: string\n                      type: object\n                  type: object\n                type: array\n              podTargetLabels:\n                description: PodTargetLabels transfers labels on the Kubernetes Pod\n                  onto the target.\n                items:\n                  type: string\n                type: array\n              sampleLimit:\n                description: SampleLimit defines per-scrape limit on number of scraped\n                  samples that will be accepted.\n                format: int64\n                type: integer\n              selector:\n                description: Selector to select Pod objects.\n                properties:\n                  matchExpressions:\n                    description: matchExpressions is a list of label selector requirements.\n                      The requirements are ANDed.\n                    items:\n                      description: A label selector requirement is a selector that\n                        contains values, a key, and an operator that relates the key\n                        and values.\n                      properties:\n                        key:\n                          description: key is the label key that the selector applies\n                            to.\n                          type: string\n                        operator:\n                          description: operator represents a key's relationship to\n                            a set of values. Valid operators are In, NotIn, Exists\n                            and DoesNotExist.\n                          type: string\n                        values:\n                          description: values is an array of string values. If the\n                            operator is In or NotIn, the values array must be non-empty.\n                            If the operator is Exists or DoesNotExist, the values\n                            array must be empty. This array is replaced during a strategic\n                            merge patch.\n                          items:\n                            type: string\n                          type: array\n                      required:\n                      - key\n                      - operator\n                      type: object\n                    type: array\n                  matchLabels:\n                    additionalProperties:\n                      type: string\n                    description: matchLabels is a map of {key,value} pairs. A single\n                      {key,value} in the matchLabels map is equivalent to an element\n                      of matchExpressions, whose key field is \"key\", the operator\n                      is \"In\", and the values array contains only \"value\". The requirements\n                      are ANDed.\n                    type: object\n                type: object\n              targetLimit:\n                description: TargetLimit defines a limit on the number of scraped\n                  targets that will be accepted.\n                format: int64\n                type: integer\n            required:\n            - podMetricsEndpoints\n            - selector\n            type: object\n        required:\n        - spec\n        type: object\n    served: true\n    storage: true\nstatus:\n  acceptedNames:\n    kind: \"\"\n    plural: \"\"\n  conditions: []\n  storedVersions: []\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/crds/crd-probes.yaml",
    "content": "# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml\n\n---\napiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.4.1\n  creationTimestamp: null\n  name: probes.monitoring.coreos.com\nspec:\n  group: monitoring.coreos.com\n  names:\n    categories:\n    - prometheus-operator\n    kind: Probe\n    listKind: ProbeList\n    plural: probes\n    singular: probe\n  scope: Namespaced\n  versions:\n  - name: v1\n    schema:\n      openAPIV3Schema:\n        description: Probe defines monitoring for a set of static targets or ingresses.\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: Specification of desired Ingress selection for target discovery\n              by Prometheus.\n            properties:\n              basicAuth:\n                description: 'BasicAuth allow an endpoint to authenticate over basic\n                  authentication. More info: https://prometheus.io/docs/operating/configuration/#endpoint'\n                properties:\n                  password:\n                    description: The secret in the service monitor namespace that\n                      contains the password for authentication.\n                    properties:\n                      key:\n                        description: The key of the secret to select from.  Must be\n                          a valid secret key.\n                        type: string\n                      name:\n                        description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                          TODO: Add other useful fields. apiVersion, kind, uid?'\n                        type: string\n                      optional:\n                        description: Specify whether the Secret or its key must be\n                          defined\n                        type: boolean\n                    required:\n                    - key\n                    type: object\n                  username:\n                    description: The secret in the service monitor namespace that\n                      contains the username for authentication.\n                    properties:\n                      key:\n                        description: The key of the secret to select from.  Must be\n                          a valid secret key.\n                        type: string\n                      name:\n                        description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                          TODO: Add other useful fields. apiVersion, kind, uid?'\n                        type: string\n                      optional:\n                        description: Specify whether the Secret or its key must be\n                          defined\n                        type: boolean\n                    required:\n                    - key\n                    type: object\n                type: object\n              bearerTokenSecret:\n                description: Secret to mount to read bearer token for scraping targets.\n                  The secret needs to be in the same namespace as the probe and accessible\n                  by the Prometheus Operator.\n                properties:\n                  key:\n                    description: The key of the secret to select from.  Must be a\n                      valid secret key.\n                    type: string\n                  name:\n                    description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                      TODO: Add other useful fields. apiVersion, kind, uid?'\n                    type: string\n                  optional:\n                    description: Specify whether the Secret or its key must be defined\n                    type: boolean\n                required:\n                - key\n                type: object\n              interval:\n                description: Interval at which targets are probed using the configured\n                  prober. If not specified Prometheus' global scrape interval is used.\n                type: string\n              jobName:\n                description: The job name assigned to scraped metrics by default.\n                type: string\n              module:\n                description: 'The module to use for probing specifying how to probe\n                  the target. Example module configuring in the blackbox exporter:\n                  https://github.com/prometheus/blackbox_exporter/blob/master/example.yml'\n                type: string\n              prober:\n                description: Specification for the prober to use for probing targets.\n                  The prober.URL parameter is required. Targets cannot be probed if\n                  left empty.\n                properties:\n                  path:\n                    description: Path to collect metrics from. Defaults to `/probe`.\n                    type: string\n                  proxyUrl:\n                    description: Optional ProxyURL.\n                    type: string\n                  scheme:\n                    description: HTTP scheme to use for scraping. Defaults to `http`.\n                    type: string\n                  url:\n                    description: Mandatory URL of the prober.\n                    type: string\n                required:\n                - url\n                type: object\n              scrapeTimeout:\n                description: Timeout for scraping metrics from the Prometheus exporter.\n                type: string\n              targets:\n                description: Targets defines a set of static and/or dynamically discovered\n                  targets to be probed using the prober.\n                properties:\n                  ingress:\n                    description: Ingress defines the set of dynamically discovered\n                      ingress objects which hosts are considered for probing.\n                    properties:\n                      namespaceSelector:\n                        description: Select Ingress objects by namespace.\n                        properties:\n                          any:\n                            description: Boolean describing whether all namespaces\n                              are selected in contrast to a list restricting them.\n                            type: boolean\n                          matchNames:\n                            description: List of namespace names.\n                            items:\n                              type: string\n                            type: array\n                        type: object\n                      relabelingConfigs:\n                        description: 'RelabelConfigs to apply to samples before ingestion.\n                          More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config'\n                        items:\n                          description: 'RelabelConfig allows dynamic rewriting of\n                            the label set, being applied to samples before ingestion.\n                            It defines `<metric_relabel_configs>`-section of Prometheus\n                            configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs'\n                          properties:\n                            action:\n                              description: Action to perform based on regex matching.\n                                Default is 'replace'\n                              type: string\n                            modulus:\n                              description: Modulus to take of the hash of the source\n                                label values.\n                              format: int64\n                              type: integer\n                            regex:\n                              description: Regular expression against which the extracted\n                                value is matched. Default is '(.*)'\n                              type: string\n                            replacement:\n                              description: Replacement value against which a regex\n                                replace is performed if the regular expression matches.\n                                Regex capture groups are available. Default is '$1'\n                              type: string\n                            separator:\n                              description: Separator placed between concatenated source\n                                label values. default is ';'.\n                              type: string\n                            sourceLabels:\n                              description: The source labels select values from existing\n                                labels. Their content is concatenated using the configured\n                                separator and matched against the configured regular\n                                expression for the replace, keep, and drop actions.\n                              items:\n                                type: string\n                              type: array\n                            targetLabel:\n                              description: Label to which the resulting value is written\n                                in a replace action. It is mandatory for replace actions.\n                                Regex capture groups are available.\n                              type: string\n                          type: object\n                        type: array\n                      selector:\n                        description: Select Ingress objects by labels.\n                        properties:\n                          matchExpressions:\n                            description: matchExpressions is a list of label selector\n                              requirements. The requirements are ANDed.\n                            items:\n                              description: A label selector requirement is a selector\n                                that contains values, a key, and an operator that\n                                relates the key and values.\n                              properties:\n                                key:\n                                  description: key is the label key that the selector\n                                    applies to.\n                                  type: string\n                                operator:\n                                  description: operator represents a key's relationship\n                                    to a set of values. Valid operators are In, NotIn,\n                                    Exists and DoesNotExist.\n                                  type: string\n                                values:\n                                  description: values is an array of string values.\n                                    If the operator is In or NotIn, the values array\n                                    must be non-empty. If the operator is Exists or\n                                    DoesNotExist, the values array must be empty.\n                                    This array is replaced during a strategic merge\n                                    patch.\n                                  items:\n                                    type: string\n                                  type: array\n                              required:\n                              - key\n                              - operator\n                              type: object\n                            type: array\n                          matchLabels:\n                            additionalProperties:\n                              type: string\n                            description: matchLabels is a map of {key,value} pairs.\n                              A single {key,value} in the matchLabels map is equivalent\n                              to an element of matchExpressions, whose key field is\n                              \"key\", the operator is \"In\", and the values array contains\n                              only \"value\". The requirements are ANDed.\n                            type: object\n                        type: object\n                    type: object\n                  staticConfig:\n                    description: 'StaticConfig defines static targets which are considers\n                      for probing. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#static_config.'\n                    properties:\n                      labels:\n                        additionalProperties:\n                          type: string\n                        description: Labels assigned to all metrics scraped from the\n                          targets.\n                        type: object\n                      relabelingConfigs:\n                        description: 'RelabelConfigs to apply to samples before ingestion.\n                          More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config'\n                        items:\n                          description: 'RelabelConfig allows dynamic rewriting of\n                            the label set, being applied to samples before ingestion.\n                            It defines `<metric_relabel_configs>`-section of Prometheus\n                            configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs'\n                          properties:\n                            action:\n                              description: Action to perform based on regex matching.\n                                Default is 'replace'\n                              type: string\n                            modulus:\n                              description: Modulus to take of the hash of the source\n                                label values.\n                              format: int64\n                              type: integer\n                            regex:\n                              description: Regular expression against which the extracted\n                                value is matched. Default is '(.*)'\n                              type: string\n                            replacement:\n                              description: Replacement value against which a regex\n                                replace is performed if the regular expression matches.\n                                Regex capture groups are available. Default is '$1'\n                              type: string\n                            separator:\n                              description: Separator placed between concatenated source\n                                label values. default is ';'.\n                              type: string\n                            sourceLabels:\n                              description: The source labels select values from existing\n                                labels. Their content is concatenated using the configured\n                                separator and matched against the configured regular\n                                expression for the replace, keep, and drop actions.\n                              items:\n                                type: string\n                              type: array\n                            targetLabel:\n                              description: Label to which the resulting value is written\n                                in a replace action. It is mandatory for replace actions.\n                                Regex capture groups are available.\n                              type: string\n                          type: object\n                        type: array\n                      static:\n                        description: Targets is a list of URLs to probe using the\n                          configured prober.\n                        items:\n                          type: string\n                        type: array\n                    type: object\n                type: object\n              tlsConfig:\n                description: TLS configuration to use when scraping the endpoint.\n                properties:\n                  ca:\n                    description: Struct containing the CA cert to use for the targets.\n                    properties:\n                      configMap:\n                        description: ConfigMap containing data to use for the targets.\n                        properties:\n                          key:\n                            description: The key to select.\n                            type: string\n                          name:\n                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                              TODO: Add other useful fields. apiVersion, kind, uid?'\n                            type: string\n                          optional:\n                            description: Specify whether the ConfigMap or its key\n                              must be defined\n                            type: boolean\n                        required:\n                        - key\n                        type: object\n                      secret:\n                        description: Secret containing data to use for the targets.\n                        properties:\n                          key:\n                            description: The key of the secret to select from.  Must\n                              be a valid secret key.\n                            type: string\n                          name:\n                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                              TODO: Add other useful fields. apiVersion, kind, uid?'\n                            type: string\n                          optional:\n                            description: Specify whether the Secret or its key must\n                              be defined\n                            type: boolean\n                        required:\n                        - key\n                        type: object\n                    type: object\n                  cert:\n                    description: Struct containing the client cert file for the targets.\n                    properties:\n                      configMap:\n                        description: ConfigMap containing data to use for the targets.\n                        properties:\n                          key:\n                            description: The key to select.\n                            type: string\n                          name:\n                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                              TODO: Add other useful fields. apiVersion, kind, uid?'\n                            type: string\n                          optional:\n                            description: Specify whether the ConfigMap or its key\n                              must be defined\n                            type: boolean\n                        required:\n                        - key\n                        type: object\n                      secret:\n                        description: Secret containing data to use for the targets.\n                        properties:\n                          key:\n                            description: The key of the secret to select from.  Must\n                              be a valid secret key.\n                            type: string\n                          name:\n                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                              TODO: Add other useful fields. apiVersion, kind, uid?'\n                            type: string\n                          optional:\n                            description: Specify whether the Secret or its key must\n                              be defined\n                            type: boolean\n                        required:\n                        - key\n                        type: object\n                    type: object\n                  insecureSkipVerify:\n                    description: Disable target certificate validation.\n                    type: boolean\n                  keySecret:\n                    description: Secret containing the client key file for the targets.\n                    properties:\n                      key:\n                        description: The key of the secret to select from.  Must be\n                          a valid secret key.\n                        type: string\n                      name:\n                        description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                          TODO: Add other useful fields. apiVersion, kind, uid?'\n                        type: string\n                      optional:\n                        description: Specify whether the Secret or its key must be\n                          defined\n                        type: boolean\n                    required:\n                    - key\n                    type: object\n                  serverName:\n                    description: Used to verify the hostname for the targets.\n                    type: string\n                type: object\n            type: object\n        required:\n        - spec\n        type: object\n    served: true\n    storage: true\nstatus:\n  acceptedNames:\n    kind: \"\"\n    plural: \"\"\n  conditions: []\n  storedVersions: []\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/crds/crd-prometheuses.yaml",
    "content": "# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml\n\n---\napiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.4.1\n  creationTimestamp: null\n  name: prometheuses.monitoring.coreos.com\nspec:\n  group: monitoring.coreos.com\n  names:\n    categories:\n    - prometheus-operator\n    kind: Prometheus\n    listKind: PrometheusList\n    plural: prometheuses\n    singular: prometheus\n  scope: Namespaced\n  versions:\n  - additionalPrinterColumns:\n    - description: The version of Prometheus\n      jsonPath: .spec.version\n      name: Version\n      type: string\n    - description: The desired replicas number of Prometheuses\n      jsonPath: .spec.replicas\n      name: Replicas\n      type: integer\n    - jsonPath: .metadata.creationTimestamp\n      name: Age\n      type: date\n    name: v1\n    schema:\n      openAPIV3Schema:\n        description: Prometheus defines a Prometheus deployment.\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: 'Specification of the desired behavior of the Prometheus\n              cluster. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status'\n            properties:\n              additionalAlertManagerConfigs:\n                description: 'AdditionalAlertManagerConfigs allows specifying a key\n                  of a Secret containing additional Prometheus AlertManager configurations.\n                  AlertManager configurations specified are appended to the configurations\n                  generated by the Prometheus Operator. Job configurations specified\n                  must have the form as specified in the official Prometheus documentation:\n                  https://prometheus.io/docs/prometheus/latest/configuration/configuration/#alertmanager_config.\n                  As AlertManager configs are appended, the user is responsible to\n                  make sure it is valid. Note that using this feature may expose the\n                  possibility to break upgrades of Prometheus. It is advised to review\n                  Prometheus release notes to ensure that no incompatible AlertManager\n                  configs are going to break Prometheus after the upgrade.'\n                properties:\n                  key:\n                    description: The key of the secret to select from.  Must be a\n                      valid secret key.\n                    type: string\n                  name:\n                    description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                      TODO: Add other useful fields. apiVersion, kind, uid?'\n                    type: string\n                  optional:\n                    description: Specify whether the Secret or its key must be defined\n                    type: boolean\n                required:\n                - key\n                type: object\n              additionalAlertRelabelConfigs:\n                description: 'AdditionalAlertRelabelConfigs allows specifying a key\n                  of a Secret containing additional Prometheus alert relabel configurations.\n                  Alert relabel configurations specified are appended to the configurations\n                  generated by the Prometheus Operator. Alert relabel configurations\n                  specified must have the form as specified in the official Prometheus\n                  documentation: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#alert_relabel_configs.\n                  As alert relabel configs are appended, the user is responsible to\n                  make sure it is valid. Note that using this feature may expose the\n                  possibility to break upgrades of Prometheus. It is advised to review\n                  Prometheus release notes to ensure that no incompatible alert relabel\n                  configs are going to break Prometheus after the upgrade.'\n                properties:\n                  key:\n                    description: The key of the secret to select from.  Must be a\n                      valid secret key.\n                    type: string\n                  name:\n                    description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                      TODO: Add other useful fields. apiVersion, kind, uid?'\n                    type: string\n                  optional:\n                    description: Specify whether the Secret or its key must be defined\n                    type: boolean\n                required:\n                - key\n                type: object\n              additionalScrapeConfigs:\n                description: 'AdditionalScrapeConfigs allows specifying a key of a\n                  Secret containing additional Prometheus scrape configurations. Scrape\n                  configurations specified are appended to the configurations generated\n                  by the Prometheus Operator. Job configurations specified must have\n                  the form as specified in the official Prometheus documentation:\n                  https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config.\n                  As scrape configs are appended, the user is responsible to make\n                  sure it is valid. Note that using this feature may expose the possibility\n                  to break upgrades of Prometheus. It is advised to review Prometheus\n                  release notes to ensure that no incompatible scrape configs are\n                  going to break Prometheus after the upgrade.'\n                properties:\n                  key:\n                    description: The key of the secret to select from.  Must be a\n                      valid secret key.\n                    type: string\n                  name:\n                    description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                      TODO: Add other useful fields. apiVersion, kind, uid?'\n                    type: string\n                  optional:\n                    description: Specify whether the Secret or its key must be defined\n                    type: boolean\n                required:\n                - key\n                type: object\n              affinity:\n                description: If specified, the pod's scheduling constraints.\n                properties:\n                  nodeAffinity:\n                    description: Describes node affinity scheduling rules for the\n                      pod.\n                    properties:\n                      preferredDuringSchedulingIgnoredDuringExecution:\n                        description: The scheduler will prefer to schedule pods to\n                          nodes that satisfy the affinity expressions specified by\n                          this field, but it may choose a node that violates one or\n                          more of the expressions. The node that is most preferred\n                          is the one with the greatest sum of weights, i.e. for each\n                          node that meets all of the scheduling requirements (resource\n                          request, requiredDuringScheduling affinity expressions,\n                          etc.), compute a sum by iterating through the elements of\n                          this field and adding \"weight\" to the sum if the node matches\n                          the corresponding matchExpressions; the node(s) with the\n                          highest sum are the most preferred.\n                        items:\n                          description: An empty preferred scheduling term matches\n                            all objects with implicit weight 0 (i.e. it's a no-op).\n                            A null preferred scheduling term matches no objects (i.e.\n                            is also a no-op).\n                          properties:\n                            preference:\n                              description: A node selector term, associated with the\n                                corresponding weight.\n                              properties:\n                                matchExpressions:\n                                  description: A list of node selector requirements\n                                    by node's labels.\n                                  items:\n                                    description: A node selector requirement is a\n                                      selector that contains values, a key, and an\n                                      operator that relates the key and values.\n                                    properties:\n                                      key:\n                                        description: The label key that the selector\n                                          applies to.\n                                        type: string\n                                      operator:\n                                        description: Represents a key's relationship\n                                          to a set of values. Valid operators are\n                                          In, NotIn, Exists, DoesNotExist. Gt, and\n                                          Lt.\n                                        type: string\n                                      values:\n                                        description: An array of string values. If\n                                          the operator is In or NotIn, the values\n                                          array must be non-empty. If the operator\n                                          is Exists or DoesNotExist, the values array\n                                          must be empty. If the operator is Gt or\n                                          Lt, the values array must have a single\n                                          element, which will be interpreted as an\n                                          integer. This array is replaced during a\n                                          strategic merge patch.\n                                        items:\n                                          type: string\n                                        type: array\n                                    required:\n                                    - key\n                                    - operator\n                                    type: object\n                                  type: array\n                                matchFields:\n                                  description: A list of node selector requirements\n                                    by node's fields.\n                                  items:\n                                    description: A node selector requirement is a\n                                      selector that contains values, a key, and an\n                                      operator that relates the key and values.\n                                    properties:\n                                      key:\n                                        description: The label key that the selector\n                                          applies to.\n                                        type: string\n                                      operator:\n                                        description: Represents a key's relationship\n                                          to a set of values. Valid operators are\n                                          In, NotIn, Exists, DoesNotExist. Gt, and\n                                          Lt.\n                                        type: string\n                                      values:\n                                        description: An array of string values. If\n                                          the operator is In or NotIn, the values\n                                          array must be non-empty. If the operator\n                                          is Exists or DoesNotExist, the values array\n                                          must be empty. If the operator is Gt or\n                                          Lt, the values array must have a single\n                                          element, which will be interpreted as an\n                                          integer. This array is replaced during a\n                                          strategic merge patch.\n                                        items:\n                                          type: string\n                                        type: array\n                                    required:\n                                    - key\n                                    - operator\n                                    type: object\n                                  type: array\n                              type: object\n                            weight:\n                              description: Weight associated with matching the corresponding\n                                nodeSelectorTerm, in the range 1-100.\n                              format: int32\n                              type: integer\n                          required:\n                          - preference\n                          - weight\n                          type: object\n                        type: array\n                      requiredDuringSchedulingIgnoredDuringExecution:\n                        description: If the affinity requirements specified by this\n                          field are not met at scheduling time, the pod will not be\n                          scheduled onto the node. If the affinity requirements specified\n                          by this field cease to be met at some point during pod execution\n                          (e.g. due to an update), the system may or may not try to\n                          eventually evict the pod from its node.\n                        properties:\n                          nodeSelectorTerms:\n                            description: Required. A list of node selector terms.\n                              The terms are ORed.\n                            items:\n                              description: A null or empty node selector term matches\n                                no objects. The requirements of them are ANDed. The\n                                TopologySelectorTerm type implements a subset of the\n                                NodeSelectorTerm.\n                              properties:\n                                matchExpressions:\n                                  description: A list of node selector requirements\n                                    by node's labels.\n                                  items:\n                                    description: A node selector requirement is a\n                                      selector that contains values, a key, and an\n                                      operator that relates the key and values.\n                                    properties:\n                                      key:\n                                        description: The label key that the selector\n                                          applies to.\n                                        type: string\n                                      operator:\n                                        description: Represents a key's relationship\n                                          to a set of values. Valid operators are\n                                          In, NotIn, Exists, DoesNotExist. Gt, and\n                                          Lt.\n                                        type: string\n                                      values:\n                                        description: An array of string values. If\n                                          the operator is In or NotIn, the values\n                                          array must be non-empty. If the operator\n                                          is Exists or DoesNotExist, the values array\n                                          must be empty. If the operator is Gt or\n                                          Lt, the values array must have a single\n                                          element, which will be interpreted as an\n                                          integer. This array is replaced during a\n                                          strategic merge patch.\n                                        items:\n                                          type: string\n                                        type: array\n                                    required:\n                                    - key\n                                    - operator\n                                    type: object\n                                  type: array\n                                matchFields:\n                                  description: A list of node selector requirements\n                                    by node's fields.\n                                  items:\n                                    description: A node selector requirement is a\n                                      selector that contains values, a key, and an\n                                      operator that relates the key and values.\n                                    properties:\n                                      key:\n                                        description: The label key that the selector\n                                          applies to.\n                                        type: string\n                                      operator:\n                                        description: Represents a key's relationship\n                                          to a set of values. Valid operators are\n                                          In, NotIn, Exists, DoesNotExist. Gt, and\n                                          Lt.\n                                        type: string\n                                      values:\n                                        description: An array of string values. If\n                                          the operator is In or NotIn, the values\n                                          array must be non-empty. If the operator\n                                          is Exists or DoesNotExist, the values array\n                                          must be empty. If the operator is Gt or\n                                          Lt, the values array must have a single\n                                          element, which will be interpreted as an\n                                          integer. This array is replaced during a\n                                          strategic merge patch.\n                                        items:\n                                          type: string\n                                        type: array\n                                    required:\n                                    - key\n                                    - operator\n                                    type: object\n                                  type: array\n                              type: object\n                            type: array\n                        required:\n                        - nodeSelectorTerms\n                        type: object\n                    type: object\n                  podAffinity:\n                    description: Describes pod affinity scheduling rules (e.g. co-locate\n                      this pod in the same node, zone, etc. as some other pod(s)).\n                    properties:\n                      preferredDuringSchedulingIgnoredDuringExecution:\n                        description: The scheduler will prefer to schedule pods to\n                          nodes that satisfy the affinity expressions specified by\n                          this field, but it may choose a node that violates one or\n                          more of the expressions. The node that is most preferred\n                          is the one with the greatest sum of weights, i.e. for each\n                          node that meets all of the scheduling requirements (resource\n                          request, requiredDuringScheduling affinity expressions,\n                          etc.), compute a sum by iterating through the elements of\n                          this field and adding \"weight\" to the sum if the node has\n                          pods which matches the corresponding podAffinityTerm; the\n                          node(s) with the highest sum are the most preferred.\n                        items:\n                          description: The weights of all of the matched WeightedPodAffinityTerm\n                            fields are added per-node to find the most preferred node(s)\n                          properties:\n                            podAffinityTerm:\n                              description: Required. A pod affinity term, associated\n                                with the corresponding weight.\n                              properties:\n                                labelSelector:\n                                  description: A label query over a set of resources,\n                                    in this case pods.\n                                  properties:\n                                    matchExpressions:\n                                      description: matchExpressions is a list of label\n                                        selector requirements. The requirements are\n                                        ANDed.\n                                      items:\n                                        description: A label selector requirement\n                                          is a selector that contains values, a key,\n                                          and an operator that relates the key and\n                                          values.\n                                        properties:\n                                          key:\n                                            description: key is the label key that\n                                              the selector applies to.\n                                            type: string\n                                          operator:\n                                            description: operator represents a key's\n                                              relationship to a set of values. Valid\n                                              operators are In, NotIn, Exists and\n                                              DoesNotExist.\n                                            type: string\n                                          values:\n                                            description: values is an array of string\n                                              values. If the operator is In or NotIn,\n                                              the values array must be non-empty.\n                                              If the operator is Exists or DoesNotExist,\n                                              the values array must be empty. This\n                                              array is replaced during a strategic\n                                              merge patch.\n                                            items:\n                                              type: string\n                                            type: array\n                                        required:\n                                        - key\n                                        - operator\n                                        type: object\n                                      type: array\n                                    matchLabels:\n                                      additionalProperties:\n                                        type: string\n                                      description: matchLabels is a map of {key,value}\n                                        pairs. A single {key,value} in the matchLabels\n                                        map is equivalent to an element of matchExpressions,\n                                        whose key field is \"key\", the operator is\n                                        \"In\", and the values array contains only \"value\".\n                                        The requirements are ANDed.\n                                      type: object\n                                  type: object\n                                namespaces:\n                                  description: namespaces specifies which namespaces\n                                    the labelSelector applies to (matches against);\n                                    null or empty list means \"this pod's namespace\"\n                                  items:\n                                    type: string\n                                  type: array\n                                topologyKey:\n                                  description: This pod should be co-located (affinity)\n                                    or not co-located (anti-affinity) with the pods\n                                    matching the labelSelector in the specified namespaces,\n                                    where co-located is defined as running on a node\n                                    whose value of the label with key topologyKey\n                                    matches that of any node on which any of the selected\n                                    pods is running. Empty topologyKey is not allowed.\n                                  type: string\n                              required:\n                              - topologyKey\n                              type: object\n                            weight:\n                              description: weight associated with matching the corresponding\n                                podAffinityTerm, in the range 1-100.\n                              format: int32\n                              type: integer\n                          required:\n                          - podAffinityTerm\n                          - weight\n                          type: object\n                        type: array\n                      requiredDuringSchedulingIgnoredDuringExecution:\n                        description: If the affinity requirements specified by this\n                          field are not met at scheduling time, the pod will not be\n                          scheduled onto the node. If the affinity requirements specified\n                          by this field cease to be met at some point during pod execution\n                          (e.g. due to a pod label update), the system may or may\n                          not try to eventually evict the pod from its node. When\n                          there are multiple elements, the lists of nodes corresponding\n                          to each podAffinityTerm are intersected, i.e. all terms\n                          must be satisfied.\n                        items:\n                          description: Defines a set of pods (namely those matching\n                            the labelSelector relative to the given namespace(s))\n                            that this pod should be co-located (affinity) or not co-located\n                            (anti-affinity) with, where co-located is defined as running\n                            on a node whose value of the label with key <topologyKey>\n                            matches that of any node on which a pod of the set of\n                            pods is running\n                          properties:\n                            labelSelector:\n                              description: A label query over a set of resources,\n                                in this case pods.\n                              properties:\n                                matchExpressions:\n                                  description: matchExpressions is a list of label\n                                    selector requirements. The requirements are ANDed.\n                                  items:\n                                    description: A label selector requirement is a\n                                      selector that contains values, a key, and an\n                                      operator that relates the key and values.\n                                    properties:\n                                      key:\n                                        description: key is the label key that the\n                                          selector applies to.\n                                        type: string\n                                      operator:\n                                        description: operator represents a key's relationship\n                                          to a set of values. Valid operators are\n                                          In, NotIn, Exists and DoesNotExist.\n                                        type: string\n                                      values:\n                                        description: values is an array of string\n                                          values. If the operator is In or NotIn,\n                                          the values array must be non-empty. If the\n                                          operator is Exists or DoesNotExist, the\n                                          values array must be empty. This array is\n                                          replaced during a strategic merge patch.\n                                        items:\n                                          type: string\n                                        type: array\n                                    required:\n                                    - key\n                                    - operator\n                                    type: object\n                                  type: array\n                                matchLabels:\n                                  additionalProperties:\n                                    type: string\n                                  description: matchLabels is a map of {key,value}\n                                    pairs. A single {key,value} in the matchLabels\n                                    map is equivalent to an element of matchExpressions,\n                                    whose key field is \"key\", the operator is \"In\",\n                                    and the values array contains only \"value\". The\n                                    requirements are ANDed.\n                                  type: object\n                              type: object\n                            namespaces:\n                              description: namespaces specifies which namespaces the\n                                labelSelector applies to (matches against); null or\n                                empty list means \"this pod's namespace\"\n                              items:\n                                type: string\n                              type: array\n                            topologyKey:\n                              description: This pod should be co-located (affinity)\n                                or not co-located (anti-affinity) with the pods matching\n                                the labelSelector in the specified namespaces, where\n                                co-located is defined as running on a node whose value\n                                of the label with key topologyKey matches that of\n                                any node on which any of the selected pods is running.\n                                Empty topologyKey is not allowed.\n                              type: string\n                          required:\n                          - topologyKey\n                          type: object\n                        type: array\n                    type: object\n                  podAntiAffinity:\n                    description: Describes pod anti-affinity scheduling rules (e.g.\n                      avoid putting this pod in the same node, zone, etc. as some\n                      other pod(s)).\n                    properties:\n                      preferredDuringSchedulingIgnoredDuringExecution:\n                        description: The scheduler will prefer to schedule pods to\n                          nodes that satisfy the anti-affinity expressions specified\n                          by this field, but it may choose a node that violates one\n                          or more of the expressions. The node that is most preferred\n                          is the one with the greatest sum of weights, i.e. for each\n                          node that meets all of the scheduling requirements (resource\n                          request, requiredDuringScheduling anti-affinity expressions,\n                          etc.), compute a sum by iterating through the elements of\n                          this field and adding \"weight\" to the sum if the node has\n                          pods which matches the corresponding podAffinityTerm; the\n                          node(s) with the highest sum are the most preferred.\n                        items:\n                          description: The weights of all of the matched WeightedPodAffinityTerm\n                            fields are added per-node to find the most preferred node(s)\n                          properties:\n                            podAffinityTerm:\n                              description: Required. A pod affinity term, associated\n                                with the corresponding weight.\n                              properties:\n                                labelSelector:\n                                  description: A label query over a set of resources,\n                                    in this case pods.\n                                  properties:\n                                    matchExpressions:\n                                      description: matchExpressions is a list of label\n                                        selector requirements. The requirements are\n                                        ANDed.\n                                      items:\n                                        description: A label selector requirement\n                                          is a selector that contains values, a key,\n                                          and an operator that relates the key and\n                                          values.\n                                        properties:\n                                          key:\n                                            description: key is the label key that\n                                              the selector applies to.\n                                            type: string\n                                          operator:\n                                            description: operator represents a key's\n                                              relationship to a set of values. Valid\n                                              operators are In, NotIn, Exists and\n                                              DoesNotExist.\n                                            type: string\n                                          values:\n                                            description: values is an array of string\n                                              values. If the operator is In or NotIn,\n                                              the values array must be non-empty.\n                                              If the operator is Exists or DoesNotExist,\n                                              the values array must be empty. This\n                                              array is replaced during a strategic\n                                              merge patch.\n                                            items:\n                                              type: string\n                                            type: array\n                                        required:\n                                        - key\n                                        - operator\n                                        type: object\n                                      type: array\n                                    matchLabels:\n                                      additionalProperties:\n                                        type: string\n                                      description: matchLabels is a map of {key,value}\n                                        pairs. A single {key,value} in the matchLabels\n                                        map is equivalent to an element of matchExpressions,\n                                        whose key field is \"key\", the operator is\n                                        \"In\", and the values array contains only \"value\".\n                                        The requirements are ANDed.\n                                      type: object\n                                  type: object\n                                namespaces:\n                                  description: namespaces specifies which namespaces\n                                    the labelSelector applies to (matches against);\n                                    null or empty list means \"this pod's namespace\"\n                                  items:\n                                    type: string\n                                  type: array\n                                topologyKey:\n                                  description: This pod should be co-located (affinity)\n                                    or not co-located (anti-affinity) with the pods\n                                    matching the labelSelector in the specified namespaces,\n                                    where co-located is defined as running on a node\n                                    whose value of the label with key topologyKey\n                                    matches that of any node on which any of the selected\n                                    pods is running. Empty topologyKey is not allowed.\n                                  type: string\n                              required:\n                              - topologyKey\n                              type: object\n                            weight:\n                              description: weight associated with matching the corresponding\n                                podAffinityTerm, in the range 1-100.\n                              format: int32\n                              type: integer\n                          required:\n                          - podAffinityTerm\n                          - weight\n                          type: object\n                        type: array\n                      requiredDuringSchedulingIgnoredDuringExecution:\n                        description: If the anti-affinity requirements specified by\n                          this field are not met at scheduling time, the pod will\n                          not be scheduled onto the node. If the anti-affinity requirements\n                          specified by this field cease to be met at some point during\n                          pod execution (e.g. due to a pod label update), the system\n                          may or may not try to eventually evict the pod from its\n                          node. When there are multiple elements, the lists of nodes\n                          corresponding to each podAffinityTerm are intersected, i.e.\n                          all terms must be satisfied.\n                        items:\n                          description: Defines a set of pods (namely those matching\n                            the labelSelector relative to the given namespace(s))\n                            that this pod should be co-located (affinity) or not co-located\n                            (anti-affinity) with, where co-located is defined as running\n                            on a node whose value of the label with key <topologyKey>\n                            matches that of any node on which a pod of the set of\n                            pods is running\n                          properties:\n                            labelSelector:\n                              description: A label query over a set of resources,\n                                in this case pods.\n                              properties:\n                                matchExpressions:\n                                  description: matchExpressions is a list of label\n                                    selector requirements. The requirements are ANDed.\n                                  items:\n                                    description: A label selector requirement is a\n                                      selector that contains values, a key, and an\n                                      operator that relates the key and values.\n                                    properties:\n                                      key:\n                                        description: key is the label key that the\n                                          selector applies to.\n                                        type: string\n                                      operator:\n                                        description: operator represents a key's relationship\n                                          to a set of values. Valid operators are\n                                          In, NotIn, Exists and DoesNotExist.\n                                        type: string\n                                      values:\n                                        description: values is an array of string\n                                          values. If the operator is In or NotIn,\n                                          the values array must be non-empty. If the\n                                          operator is Exists or DoesNotExist, the\n                                          values array must be empty. This array is\n                                          replaced during a strategic merge patch.\n                                        items:\n                                          type: string\n                                        type: array\n                                    required:\n                                    - key\n                                    - operator\n                                    type: object\n                                  type: array\n                                matchLabels:\n                                  additionalProperties:\n                                    type: string\n                                  description: matchLabels is a map of {key,value}\n                                    pairs. A single {key,value} in the matchLabels\n                                    map is equivalent to an element of matchExpressions,\n                                    whose key field is \"key\", the operator is \"In\",\n                                    and the values array contains only \"value\". The\n                                    requirements are ANDed.\n                                  type: object\n                              type: object\n                            namespaces:\n                              description: namespaces specifies which namespaces the\n                                labelSelector applies to (matches against); null or\n                                empty list means \"this pod's namespace\"\n                              items:\n                                type: string\n                              type: array\n                            topologyKey:\n                              description: This pod should be co-located (affinity)\n                                or not co-located (anti-affinity) with the pods matching\n                                the labelSelector in the specified namespaces, where\n                                co-located is defined as running on a node whose value\n                                of the label with key topologyKey matches that of\n                                any node on which any of the selected pods is running.\n                                Empty topologyKey is not allowed.\n                              type: string\n                          required:\n                          - topologyKey\n                          type: object\n                        type: array\n                    type: object\n                type: object\n              alerting:\n                description: Define details regarding alerting.\n                properties:\n                  alertmanagers:\n                    description: AlertmanagerEndpoints Prometheus should fire alerts\n                      against.\n                    items:\n                      description: AlertmanagerEndpoints defines a selection of a\n                        single Endpoints object containing alertmanager IPs to fire\n                        alerts against.\n                      properties:\n                        apiVersion:\n                          description: Version of the Alertmanager API that Prometheus\n                            uses to send alerts. It can be \"v1\" or \"v2\".\n                          type: string\n                        bearerTokenFile:\n                          description: BearerTokenFile to read from filesystem to\n                            use when authenticating to Alertmanager.\n                          type: string\n                        name:\n                          description: Name of Endpoints object in Namespace.\n                          type: string\n                        namespace:\n                          description: Namespace of Endpoints object.\n                          type: string\n                        pathPrefix:\n                          description: Prefix for the HTTP path alerts are pushed\n                            to.\n                          type: string\n                        port:\n                          anyOf:\n                          - type: integer\n                          - type: string\n                          description: Port the Alertmanager API is exposed on.\n                          x-kubernetes-int-or-string: true\n                        scheme:\n                          description: Scheme to use when firing alerts.\n                          type: string\n                        timeout:\n                          description: Timeout is a per-target Alertmanager timeout\n                            when pushing alerts.\n                          type: string\n                        tlsConfig:\n                          description: TLS Config to use for alertmanager connection.\n                          properties:\n                            ca:\n                              description: Struct containing the CA cert to use for\n                                the targets.\n                              properties:\n                                configMap:\n                                  description: ConfigMap containing data to use for\n                                    the targets.\n                                  properties:\n                                    key:\n                                      description: The key to select.\n                                      type: string\n                                    name:\n                                      description: 'Name of the referent. More info:\n                                        https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                        TODO: Add other useful fields. apiVersion,\n                                        kind, uid?'\n                                      type: string\n                                    optional:\n                                      description: Specify whether the ConfigMap or\n                                        its key must be defined\n                                      type: boolean\n                                  required:\n                                  - key\n                                  type: object\n                                secret:\n                                  description: Secret containing data to use for the\n                                    targets.\n                                  properties:\n                                    key:\n                                      description: The key of the secret to select\n                                        from.  Must be a valid secret key.\n                                      type: string\n                                    name:\n                                      description: 'Name of the referent. More info:\n                                        https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                        TODO: Add other useful fields. apiVersion,\n                                        kind, uid?'\n                                      type: string\n                                    optional:\n                                      description: Specify whether the Secret or its\n                                        key must be defined\n                                      type: boolean\n                                  required:\n                                  - key\n                                  type: object\n                              type: object\n                            caFile:\n                              description: Path to the CA cert in the Prometheus container\n                                to use for the targets.\n                              type: string\n                            cert:\n                              description: Struct containing the client cert file\n                                for the targets.\n                              properties:\n                                configMap:\n                                  description: ConfigMap containing data to use for\n                                    the targets.\n                                  properties:\n                                    key:\n                                      description: The key to select.\n                                      type: string\n                                    name:\n                                      description: 'Name of the referent. More info:\n                                        https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                        TODO: Add other useful fields. apiVersion,\n                                        kind, uid?'\n                                      type: string\n                                    optional:\n                                      description: Specify whether the ConfigMap or\n                                        its key must be defined\n                                      type: boolean\n                                  required:\n                                  - key\n                                  type: object\n                                secret:\n                                  description: Secret containing data to use for the\n                                    targets.\n                                  properties:\n                                    key:\n                                      description: The key of the secret to select\n                                        from.  Must be a valid secret key.\n                                      type: string\n                                    name:\n                                      description: 'Name of the referent. More info:\n                                        https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                        TODO: Add other useful fields. apiVersion,\n                                        kind, uid?'\n                                      type: string\n                                    optional:\n                                      description: Specify whether the Secret or its\n                                        key must be defined\n                                      type: boolean\n                                  required:\n                                  - key\n                                  type: object\n                              type: object\n                            certFile:\n                              description: Path to the client cert file in the Prometheus\n                                container for the targets.\n                              type: string\n                            insecureSkipVerify:\n                              description: Disable target certificate validation.\n                              type: boolean\n                            keyFile:\n                              description: Path to the client key file in the Prometheus\n                                container for the targets.\n                              type: string\n                            keySecret:\n                              description: Secret containing the client key file for\n                                the targets.\n                              properties:\n                                key:\n                                  description: The key of the secret to select from.  Must\n                                    be a valid secret key.\n                                  type: string\n                                name:\n                                  description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                    TODO: Add other useful fields. apiVersion, kind,\n                                    uid?'\n                                  type: string\n                                optional:\n                                  description: Specify whether the Secret or its key\n                                    must be defined\n                                  type: boolean\n                              required:\n                              - key\n                              type: object\n                            serverName:\n                              description: Used to verify the hostname for the targets.\n                              type: string\n                          type: object\n                      required:\n                      - name\n                      - namespace\n                      - port\n                      type: object\n                    type: array\n                required:\n                - alertmanagers\n                type: object\n              allowOverlappingBlocks:\n                description: AllowOverlappingBlocks enables vertical compaction and\n                  vertical query merge in Prometheus. This is still experimental in\n                  Prometheus so it may change in any upcoming release.\n                type: boolean\n              apiserverConfig:\n                description: APIServerConfig allows specifying a host and auth methods\n                  to access apiserver. If left empty, Prometheus is assumed to run\n                  inside of the cluster and will discover API servers automatically\n                  and use the pod's CA certificate and bearer token file at /var/run/secrets/kubernetes.io/serviceaccount/.\n                properties:\n                  basicAuth:\n                    description: BasicAuth allow an endpoint to authenticate over\n                      basic authentication\n                    properties:\n                      password:\n                        description: The secret in the service monitor namespace that\n                          contains the password for authentication.\n                        properties:\n                          key:\n                            description: The key of the secret to select from.  Must\n                              be a valid secret key.\n                            type: string\n                          name:\n                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                              TODO: Add other useful fields. apiVersion, kind, uid?'\n                            type: string\n                          optional:\n                            description: Specify whether the Secret or its key must\n                              be defined\n                            type: boolean\n                        required:\n                        - key\n                        type: object\n                      username:\n                        description: The secret in the service monitor namespace that\n                          contains the username for authentication.\n                        properties:\n                          key:\n                            description: The key of the secret to select from.  Must\n                              be a valid secret key.\n                            type: string\n                          name:\n                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                              TODO: Add other useful fields. apiVersion, kind, uid?'\n                            type: string\n                          optional:\n                            description: Specify whether the Secret or its key must\n                              be defined\n                            type: boolean\n                        required:\n                        - key\n                        type: object\n                    type: object\n                  bearerToken:\n                    description: Bearer token for accessing apiserver.\n                    type: string\n                  bearerTokenFile:\n                    description: File to read bearer token for accessing apiserver.\n                    type: string\n                  host:\n                    description: Host of apiserver. A valid string consisting of a\n                      hostname or IP followed by an optional port number\n                    type: string\n                  tlsConfig:\n                    description: TLS Config to use for accessing apiserver.\n                    properties:\n                      ca:\n                        description: Struct containing the CA cert to use for the\n                          targets.\n                        properties:\n                          configMap:\n                            description: ConfigMap containing data to use for the\n                              targets.\n                            properties:\n                              key:\n                                description: The key to select.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the ConfigMap or its\n                                  key must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                          secret:\n                            description: Secret containing data to use for the targets.\n                            properties:\n                              key:\n                                description: The key of the secret to select from.  Must\n                                  be a valid secret key.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret or its key\n                                  must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                        type: object\n                      caFile:\n                        description: Path to the CA cert in the Prometheus container\n                          to use for the targets.\n                        type: string\n                      cert:\n                        description: Struct containing the client cert file for the\n                          targets.\n                        properties:\n                          configMap:\n                            description: ConfigMap containing data to use for the\n                              targets.\n                            properties:\n                              key:\n                                description: The key to select.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the ConfigMap or its\n                                  key must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                          secret:\n                            description: Secret containing data to use for the targets.\n                            properties:\n                              key:\n                                description: The key of the secret to select from.  Must\n                                  be a valid secret key.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret or its key\n                                  must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                        type: object\n                      certFile:\n                        description: Path to the client cert file in the Prometheus\n                          container for the targets.\n                        type: string\n                      insecureSkipVerify:\n                        description: Disable target certificate validation.\n                        type: boolean\n                      keyFile:\n                        description: Path to the client key file in the Prometheus\n                          container for the targets.\n                        type: string\n                      keySecret:\n                        description: Secret containing the client key file for the\n                          targets.\n                        properties:\n                          key:\n                            description: The key of the secret to select from.  Must\n                              be a valid secret key.\n                            type: string\n                          name:\n                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                              TODO: Add other useful fields. apiVersion, kind, uid?'\n                            type: string\n                          optional:\n                            description: Specify whether the Secret or its key must\n                              be defined\n                            type: boolean\n                        required:\n                        - key\n                        type: object\n                      serverName:\n                        description: Used to verify the hostname for the targets.\n                        type: string\n                    type: object\n                required:\n                - host\n                type: object\n              arbitraryFSAccessThroughSMs:\n                description: ArbitraryFSAccessThroughSMs configures whether configuration\n                  based on a service monitor can access arbitrary files on the file\n                  system of the Prometheus container e.g. bearer token files.\n                properties:\n                  deny:\n                    type: boolean\n                type: object\n              baseImage:\n                description: 'Base image to use for a Prometheus deployment. Deprecated:\n                  use ''image'' instead'\n                type: string\n              configMaps:\n                description: ConfigMaps is a list of ConfigMaps in the same namespace\n                  as the Prometheus object, which shall be mounted into the Prometheus\n                  Pods. The ConfigMaps are mounted into /etc/prometheus/configmaps/<configmap-name>.\n                items:\n                  type: string\n                type: array\n              containers:\n                description: 'Containers allows injecting additional containers or\n                  modifying operator generated containers. This can be used to allow\n                  adding an authentication proxy to a Prometheus pod or to change\n                  the behavior of an operator generated container. Containers described\n                  here modify an operator generated container if they share the same\n                  name and modifications are done via a strategic merge patch. The\n                  current container names are: `prometheus`, `config-reloader`, and\n                  `thanos-sidecar`. Overriding containers is entirely outside the\n                  scope of what the maintainers will support and by doing so, you\n                  accept that this behaviour may break at any time without notice.'\n                items:\n                  description: A single application container that you want to run\n                    within a pod.\n                  properties:\n                    args:\n                      description: 'Arguments to the entrypoint. The docker image''s\n                        CMD is used if this is not provided. Variable references $(VAR_NAME)\n                        are expanded using the container''s environment. If a variable\n                        cannot be resolved, the reference in the input string will\n                        be unchanged. The $(VAR_NAME) syntax can be escaped with a\n                        double $$, ie: $$(VAR_NAME). Escaped references will never\n                        be expanded, regardless of whether the variable exists or\n                        not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell'\n                      items:\n                        type: string\n                      type: array\n                    command:\n                      description: 'Entrypoint array. Not executed within a shell.\n                        The docker image''s ENTRYPOINT is used if this is not provided.\n                        Variable references $(VAR_NAME) are expanded using the container''s\n                        environment. If a variable cannot be resolved, the reference\n                        in the input string will be unchanged. The $(VAR_NAME) syntax\n                        can be escaped with a double $$, ie: $$(VAR_NAME). Escaped\n                        references will never be expanded, regardless of whether the\n                        variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell'\n                      items:\n                        type: string\n                      type: array\n                    env:\n                      description: List of environment variables to set in the container.\n                        Cannot be updated.\n                      items:\n                        description: EnvVar represents an environment variable present\n                          in a Container.\n                        properties:\n                          name:\n                            description: Name of the environment variable. Must be\n                              a C_IDENTIFIER.\n                            type: string\n                          value:\n                            description: 'Variable references $(VAR_NAME) are expanded\n                              using the previous defined environment variables in\n                              the container and any service environment variables.\n                              If a variable cannot be resolved, the reference in the\n                              input string will be unchanged. The $(VAR_NAME) syntax\n                              can be escaped with a double $$, ie: $$(VAR_NAME). Escaped\n                              references will never be expanded, regardless of whether\n                              the variable exists or not. Defaults to \"\".'\n                            type: string\n                          valueFrom:\n                            description: Source for the environment variable's value.\n                              Cannot be used if value is not empty.\n                            properties:\n                              configMapKeyRef:\n                                description: Selects a key of a ConfigMap.\n                                properties:\n                                  key:\n                                    description: The key to select.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the ConfigMap or\n                                      its key must be defined\n                                    type: boolean\n                                required:\n                                - key\n                                type: object\n                              fieldRef:\n                                description: 'Selects a field of the pod: supports\n                                  metadata.name, metadata.namespace, metadata.labels,\n                                  metadata.annotations, spec.nodeName, spec.serviceAccountName,\n                                  status.hostIP, status.podIP, status.podIPs.'\n                                properties:\n                                  apiVersion:\n                                    description: Version of the schema the FieldPath\n                                      is written in terms of, defaults to \"v1\".\n                                    type: string\n                                  fieldPath:\n                                    description: Path of the field to select in the\n                                      specified API version.\n                                    type: string\n                                required:\n                                - fieldPath\n                                type: object\n                              resourceFieldRef:\n                                description: 'Selects a resource of the container:\n                                  only resources limits and requests (limits.cpu,\n                                  limits.memory, limits.ephemeral-storage, requests.cpu,\n                                  requests.memory and requests.ephemeral-storage)\n                                  are currently supported.'\n                                properties:\n                                  containerName:\n                                    description: 'Container name: required for volumes,\n                                      optional for env vars'\n                                    type: string\n                                  divisor:\n                                    anyOf:\n                                    - type: integer\n                                    - type: string\n                                    description: Specifies the output format of the\n                                      exposed resources, defaults to \"1\"\n                                    pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                    x-kubernetes-int-or-string: true\n                                  resource:\n                                    description: 'Required: resource to select'\n                                    type: string\n                                required:\n                                - resource\n                                type: object\n                              secretKeyRef:\n                                description: Selects a key of a secret in the pod's\n                                  namespace\n                                properties:\n                                  key:\n                                    description: The key of the secret to select from.  Must\n                                      be a valid secret key.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the Secret or its\n                                      key must be defined\n                                    type: boolean\n                                required:\n                                - key\n                                type: object\n                            type: object\n                        required:\n                        - name\n                        type: object\n                      type: array\n                    envFrom:\n                      description: List of sources to populate environment variables\n                        in the container. The keys defined within a source must be\n                        a C_IDENTIFIER. All invalid keys will be reported as an event\n                        when the container is starting. When a key exists in multiple\n                        sources, the value associated with the last source will take\n                        precedence. Values defined by an Env with a duplicate key\n                        will take precedence. Cannot be updated.\n                      items:\n                        description: EnvFromSource represents the source of a set\n                          of ConfigMaps\n                        properties:\n                          configMapRef:\n                            description: The ConfigMap to select from\n                            properties:\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the ConfigMap must be\n                                  defined\n                                type: boolean\n                            type: object\n                          prefix:\n                            description: An optional identifier to prepend to each\n                              key in the ConfigMap. Must be a C_IDENTIFIER.\n                            type: string\n                          secretRef:\n                            description: The Secret to select from\n                            properties:\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret must be defined\n                                type: boolean\n                            type: object\n                        type: object\n                      type: array\n                    image:\n                      description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images\n                        This field is optional to allow higher level config management\n                        to default or override container images in workload controllers\n                        like Deployments and StatefulSets.'\n                      type: string\n                    imagePullPolicy:\n                      description: 'Image pull policy. One of Always, Never, IfNotPresent.\n                        Defaults to Always if :latest tag is specified, or IfNotPresent\n                        otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images'\n                      type: string\n                    lifecycle:\n                      description: Actions that the management system should take\n                        in response to container lifecycle events. Cannot be updated.\n                      properties:\n                        postStart:\n                          description: 'PostStart is called immediately after a container\n                            is created. If the handler fails, the container is terminated\n                            and restarted according to its restart policy. Other management\n                            of the container blocks until the hook completes. More\n                            info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks'\n                          properties:\n                            exec:\n                              description: One and only one of the following should\n                                be specified. Exec specifies the action to take.\n                              properties:\n                                command:\n                                  description: Command is the command line to execute\n                                    inside the container, the working directory for\n                                    the command  is root ('/') in the container's\n                                    filesystem. The command is simply exec'd, it is\n                                    not run inside a shell, so traditional shell instructions\n                                    ('|', etc) won't work. To use a shell, you need\n                                    to explicitly call out to that shell. Exit status\n                                    of 0 is treated as live/healthy and non-zero is\n                                    unhealthy.\n                                  items:\n                                    type: string\n                                  type: array\n                              type: object\n                            httpGet:\n                              description: HTTPGet specifies the http request to perform.\n                              properties:\n                                host:\n                                  description: Host name to connect to, defaults to\n                                    the pod IP. You probably want to set \"Host\" in\n                                    httpHeaders instead.\n                                  type: string\n                                httpHeaders:\n                                  description: Custom headers to set in the request.\n                                    HTTP allows repeated headers.\n                                  items:\n                                    description: HTTPHeader describes a custom header\n                                      to be used in HTTP probes\n                                    properties:\n                                      name:\n                                        description: The header field name\n                                        type: string\n                                      value:\n                                        description: The header field value\n                                        type: string\n                                    required:\n                                    - name\n                                    - value\n                                    type: object\n                                  type: array\n                                path:\n                                  description: Path to access on the HTTP server.\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Name or number of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                                scheme:\n                                  description: Scheme to use for connecting to the\n                                    host. Defaults to HTTP.\n                                  type: string\n                              required:\n                              - port\n                              type: object\n                            tcpSocket:\n                              description: 'TCPSocket specifies an action involving\n                                a TCP port. TCP hooks not yet supported TODO: implement\n                                a realistic TCP lifecycle hook'\n                              properties:\n                                host:\n                                  description: 'Optional: Host name to connect to,\n                                    defaults to the pod IP.'\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Number or name of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                              required:\n                              - port\n                              type: object\n                          type: object\n                        preStop:\n                          description: 'PreStop is called immediately before a container\n                            is terminated due to an API request or management event\n                            such as liveness/startup probe failure, preemption, resource\n                            contention, etc. The handler is not called if the container\n                            crashes or exits. The reason for termination is passed\n                            to the handler. The Pod''s termination grace period countdown\n                            begins before the PreStop hooked is executed. Regardless\n                            of the outcome of the handler, the container will eventually\n                            terminate within the Pod''s termination grace period.\n                            Other management of the container blocks until the hook\n                            completes or until the termination grace period is reached.\n                            More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks'\n                          properties:\n                            exec:\n                              description: One and only one of the following should\n                                be specified. Exec specifies the action to take.\n                              properties:\n                                command:\n                                  description: Command is the command line to execute\n                                    inside the container, the working directory for\n                                    the command  is root ('/') in the container's\n                                    filesystem. The command is simply exec'd, it is\n                                    not run inside a shell, so traditional shell instructions\n                                    ('|', etc) won't work. To use a shell, you need\n                                    to explicitly call out to that shell. Exit status\n                                    of 0 is treated as live/healthy and non-zero is\n                                    unhealthy.\n                                  items:\n                                    type: string\n                                  type: array\n                              type: object\n                            httpGet:\n                              description: HTTPGet specifies the http request to perform.\n                              properties:\n                                host:\n                                  description: Host name to connect to, defaults to\n                                    the pod IP. You probably want to set \"Host\" in\n                                    httpHeaders instead.\n                                  type: string\n                                httpHeaders:\n                                  description: Custom headers to set in the request.\n                                    HTTP allows repeated headers.\n                                  items:\n                                    description: HTTPHeader describes a custom header\n                                      to be used in HTTP probes\n                                    properties:\n                                      name:\n                                        description: The header field name\n                                        type: string\n                                      value:\n                                        description: The header field value\n                                        type: string\n                                    required:\n                                    - name\n                                    - value\n                                    type: object\n                                  type: array\n                                path:\n                                  description: Path to access on the HTTP server.\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Name or number of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                                scheme:\n                                  description: Scheme to use for connecting to the\n                                    host. Defaults to HTTP.\n                                  type: string\n                              required:\n                              - port\n                              type: object\n                            tcpSocket:\n                              description: 'TCPSocket specifies an action involving\n                                a TCP port. TCP hooks not yet supported TODO: implement\n                                a realistic TCP lifecycle hook'\n                              properties:\n                                host:\n                                  description: 'Optional: Host name to connect to,\n                                    defaults to the pod IP.'\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Number or name of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                              required:\n                              - port\n                              type: object\n                          type: object\n                      type: object\n                    livenessProbe:\n                      description: 'Periodic probe of container liveness. Container\n                        will be restarted if the probe fails. Cannot be updated. More\n                        info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                      properties:\n                        exec:\n                          description: One and only one of the following should be\n                            specified. Exec specifies the action to take.\n                          properties:\n                            command:\n                              description: Command is the command line to execute\n                                inside the container, the working directory for the\n                                command  is root ('/') in the container's filesystem.\n                                The command is simply exec'd, it is not run inside\n                                a shell, so traditional shell instructions ('|', etc)\n                                won't work. To use a shell, you need to explicitly\n                                call out to that shell. Exit status of 0 is treated\n                                as live/healthy and non-zero is unhealthy.\n                              items:\n                                type: string\n                              type: array\n                          type: object\n                        failureThreshold:\n                          description: Minimum consecutive failures for the probe\n                            to be considered failed after having succeeded. Defaults\n                            to 3. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        httpGet:\n                          description: HTTPGet specifies the http request to perform.\n                          properties:\n                            host:\n                              description: Host name to connect to, defaults to the\n                                pod IP. You probably want to set \"Host\" in httpHeaders\n                                instead.\n                              type: string\n                            httpHeaders:\n                              description: Custom headers to set in the request. HTTP\n                                allows repeated headers.\n                              items:\n                                description: HTTPHeader describes a custom header\n                                  to be used in HTTP probes\n                                properties:\n                                  name:\n                                    description: The header field name\n                                    type: string\n                                  value:\n                                    description: The header field value\n                                    type: string\n                                required:\n                                - name\n                                - value\n                                type: object\n                              type: array\n                            path:\n                              description: Path to access on the HTTP server.\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Name or number of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                            scheme:\n                              description: Scheme to use for connecting to the host.\n                                Defaults to HTTP.\n                              type: string\n                          required:\n                          - port\n                          type: object\n                        initialDelaySeconds:\n                          description: 'Number of seconds after the container has\n                            started before liveness probes are initiated. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                        periodSeconds:\n                          description: How often (in seconds) to perform the probe.\n                            Default to 10 seconds. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        successThreshold:\n                          description: Minimum consecutive successes for the probe\n                            to be considered successful after having failed. Defaults\n                            to 1. Must be 1 for liveness and startup. Minimum value\n                            is 1.\n                          format: int32\n                          type: integer\n                        tcpSocket:\n                          description: 'TCPSocket specifies an action involving a\n                            TCP port. TCP hooks not yet supported TODO: implement\n                            a realistic TCP lifecycle hook'\n                          properties:\n                            host:\n                              description: 'Optional: Host name to connect to, defaults\n                                to the pod IP.'\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Number or name of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                          required:\n                          - port\n                          type: object\n                        timeoutSeconds:\n                          description: 'Number of seconds after which the probe times\n                            out. Defaults to 1 second. Minimum value is 1. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                      type: object\n                    name:\n                      description: Name of the container specified as a DNS_LABEL.\n                        Each container in a pod must have a unique name (DNS_LABEL).\n                        Cannot be updated.\n                      type: string\n                    ports:\n                      description: List of ports to expose from the container. Exposing\n                        a port here gives the system additional information about\n                        the network connections a container uses, but is primarily\n                        informational. Not specifying a port here DOES NOT prevent\n                        that port from being exposed. Any port which is listening\n                        on the default \"0.0.0.0\" address inside a container will be\n                        accessible from the network. Cannot be updated.\n                      items:\n                        description: ContainerPort represents a network port in a\n                          single container.\n                        properties:\n                          containerPort:\n                            description: Number of port to expose on the pod's IP\n                              address. This must be a valid port number, 0 < x < 65536.\n                            format: int32\n                            type: integer\n                          hostIP:\n                            description: What host IP to bind the external port to.\n                            type: string\n                          hostPort:\n                            description: Number of port to expose on the host. If\n                              specified, this must be a valid port number, 0 < x <\n                              65536. If HostNetwork is specified, this must match\n                              ContainerPort. Most containers do not need this.\n                            format: int32\n                            type: integer\n                          name:\n                            description: If specified, this must be an IANA_SVC_NAME\n                              and unique within the pod. Each named port in a pod\n                              must have a unique name. Name for the port that can\n                              be referred to by services.\n                            type: string\n                          protocol:\n                            default: TCP\n                            description: Protocol for port. Must be UDP, TCP, or SCTP.\n                              Defaults to \"TCP\".\n                            type: string\n                        required:\n                        - containerPort\n                        type: object\n                      type: array\n                      x-kubernetes-list-map-keys:\n                      - containerPort\n                      - protocol\n                      x-kubernetes-list-type: map\n                    readinessProbe:\n                      description: 'Periodic probe of container service readiness.\n                        Container will be removed from service endpoints if the probe\n                        fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                      properties:\n                        exec:\n                          description: One and only one of the following should be\n                            specified. Exec specifies the action to take.\n                          properties:\n                            command:\n                              description: Command is the command line to execute\n                                inside the container, the working directory for the\n                                command  is root ('/') in the container's filesystem.\n                                The command is simply exec'd, it is not run inside\n                                a shell, so traditional shell instructions ('|', etc)\n                                won't work. To use a shell, you need to explicitly\n                                call out to that shell. Exit status of 0 is treated\n                                as live/healthy and non-zero is unhealthy.\n                              items:\n                                type: string\n                              type: array\n                          type: object\n                        failureThreshold:\n                          description: Minimum consecutive failures for the probe\n                            to be considered failed after having succeeded. Defaults\n                            to 3. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        httpGet:\n                          description: HTTPGet specifies the http request to perform.\n                          properties:\n                            host:\n                              description: Host name to connect to, defaults to the\n                                pod IP. You probably want to set \"Host\" in httpHeaders\n                                instead.\n                              type: string\n                            httpHeaders:\n                              description: Custom headers to set in the request. HTTP\n                                allows repeated headers.\n                              items:\n                                description: HTTPHeader describes a custom header\n                                  to be used in HTTP probes\n                                properties:\n                                  name:\n                                    description: The header field name\n                                    type: string\n                                  value:\n                                    description: The header field value\n                                    type: string\n                                required:\n                                - name\n                                - value\n                                type: object\n                              type: array\n                            path:\n                              description: Path to access on the HTTP server.\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Name or number of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                            scheme:\n                              description: Scheme to use for connecting to the host.\n                                Defaults to HTTP.\n                              type: string\n                          required:\n                          - port\n                          type: object\n                        initialDelaySeconds:\n                          description: 'Number of seconds after the container has\n                            started before liveness probes are initiated. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                        periodSeconds:\n                          description: How often (in seconds) to perform the probe.\n                            Default to 10 seconds. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        successThreshold:\n                          description: Minimum consecutive successes for the probe\n                            to be considered successful after having failed. Defaults\n                            to 1. Must be 1 for liveness and startup. Minimum value\n                            is 1.\n                          format: int32\n                          type: integer\n                        tcpSocket:\n                          description: 'TCPSocket specifies an action involving a\n                            TCP port. TCP hooks not yet supported TODO: implement\n                            a realistic TCP lifecycle hook'\n                          properties:\n                            host:\n                              description: 'Optional: Host name to connect to, defaults\n                                to the pod IP.'\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Number or name of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                          required:\n                          - port\n                          type: object\n                        timeoutSeconds:\n                          description: 'Number of seconds after which the probe times\n                            out. Defaults to 1 second. Minimum value is 1. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                      type: object\n                    resources:\n                      description: 'Compute Resources required by this container.\n                        Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                      properties:\n                        limits:\n                          additionalProperties:\n                            anyOf:\n                            - type: integer\n                            - type: string\n                            pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                            x-kubernetes-int-or-string: true\n                          description: 'Limits describes the maximum amount of compute\n                            resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                          type: object\n                        requests:\n                          additionalProperties:\n                            anyOf:\n                            - type: integer\n                            - type: string\n                            pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                            x-kubernetes-int-or-string: true\n                          description: 'Requests describes the minimum amount of compute\n                            resources required. If Requests is omitted for a container,\n                            it defaults to Limits if that is explicitly specified,\n                            otherwise to an implementation-defined value. More info:\n                            https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                          type: object\n                      type: object\n                    securityContext:\n                      description: 'Security options the pod should run with. More\n                        info: https://kubernetes.io/docs/concepts/policy/security-context/\n                        More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/'\n                      properties:\n                        allowPrivilegeEscalation:\n                          description: 'AllowPrivilegeEscalation controls whether\n                            a process can gain more privileges than its parent process.\n                            This bool directly controls if the no_new_privs flag will\n                            be set on the container process. AllowPrivilegeEscalation\n                            is true always when the container is: 1) run as Privileged\n                            2) has CAP_SYS_ADMIN'\n                          type: boolean\n                        capabilities:\n                          description: The capabilities to add/drop when running containers.\n                            Defaults to the default set of capabilities granted by\n                            the container runtime.\n                          properties:\n                            add:\n                              description: Added capabilities\n                              items:\n                                description: Capability represent POSIX capabilities\n                                  type\n                                type: string\n                              type: array\n                            drop:\n                              description: Removed capabilities\n                              items:\n                                description: Capability represent POSIX capabilities\n                                  type\n                                type: string\n                              type: array\n                          type: object\n                        privileged:\n                          description: Run container in privileged mode. Processes\n                            in privileged containers are essentially equivalent to\n                            root on the host. Defaults to false.\n                          type: boolean\n                        procMount:\n                          description: procMount denotes the type of proc mount to\n                            use for the containers. The default is DefaultProcMount\n                            which uses the container runtime defaults for readonly\n                            paths and masked paths. This requires the ProcMountType\n                            feature flag to be enabled.\n                          type: string\n                        readOnlyRootFilesystem:\n                          description: Whether this container has a read-only root\n                            filesystem. Default is false.\n                          type: boolean\n                        runAsGroup:\n                          description: The GID to run the entrypoint of the container\n                            process. Uses runtime default if unset. May also be set\n                            in PodSecurityContext.  If set in both SecurityContext\n                            and PodSecurityContext, the value specified in SecurityContext\n                            takes precedence.\n                          format: int64\n                          type: integer\n                        runAsNonRoot:\n                          description: Indicates that the container must run as a\n                            non-root user. If true, the Kubelet will validate the\n                            image at runtime to ensure that it does not run as UID\n                            0 (root) and fail to start the container if it does. If\n                            unset or false, no such validation will be performed.\n                            May also be set in PodSecurityContext.  If set in both\n                            SecurityContext and PodSecurityContext, the value specified\n                            in SecurityContext takes precedence.\n                          type: boolean\n                        runAsUser:\n                          description: The UID to run the entrypoint of the container\n                            process. Defaults to user specified in image metadata\n                            if unspecified. May also be set in PodSecurityContext.  If\n                            set in both SecurityContext and PodSecurityContext, the\n                            value specified in SecurityContext takes precedence.\n                          format: int64\n                          type: integer\n                        seLinuxOptions:\n                          description: The SELinux context to be applied to the container.\n                            If unspecified, the container runtime will allocate a\n                            random SELinux context for each container.  May also be\n                            set in PodSecurityContext.  If set in both SecurityContext\n                            and PodSecurityContext, the value specified in SecurityContext\n                            takes precedence.\n                          properties:\n                            level:\n                              description: Level is SELinux level label that applies\n                                to the container.\n                              type: string\n                            role:\n                              description: Role is a SELinux role label that applies\n                                to the container.\n                              type: string\n                            type:\n                              description: Type is a SELinux type label that applies\n                                to the container.\n                              type: string\n                            user:\n                              description: User is a SELinux user label that applies\n                                to the container.\n                              type: string\n                          type: object\n                        windowsOptions:\n                          description: The Windows specific settings applied to all\n                            containers. If unspecified, the options from the PodSecurityContext\n                            will be used. If set in both SecurityContext and PodSecurityContext,\n                            the value specified in SecurityContext takes precedence.\n                          properties:\n                            gmsaCredentialSpec:\n                              description: GMSACredentialSpec is where the GMSA admission\n                                webhook (https://github.com/kubernetes-sigs/windows-gmsa)\n                                inlines the contents of the GMSA credential spec named\n                                by the GMSACredentialSpecName field.\n                              type: string\n                            gmsaCredentialSpecName:\n                              description: GMSACredentialSpecName is the name of the\n                                GMSA credential spec to use.\n                              type: string\n                            runAsUserName:\n                              description: The UserName in Windows to run the entrypoint\n                                of the container process. Defaults to the user specified\n                                in image metadata if unspecified. May also be set\n                                in PodSecurityContext. If set in both SecurityContext\n                                and PodSecurityContext, the value specified in SecurityContext\n                                takes precedence.\n                              type: string\n                          type: object\n                      type: object\n                    startupProbe:\n                      description: 'StartupProbe indicates that the Pod has successfully\n                        initialized. If specified, no other probes are executed until\n                        this completes successfully. If this probe fails, the Pod\n                        will be restarted, just as if the livenessProbe failed. This\n                        can be used to provide different probe parameters at the beginning\n                        of a Pod''s lifecycle, when it might take a long time to load\n                        data or warm a cache, than during steady-state operation.\n                        This cannot be updated. This is a beta feature enabled by\n                        the StartupProbe feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                      properties:\n                        exec:\n                          description: One and only one of the following should be\n                            specified. Exec specifies the action to take.\n                          properties:\n                            command:\n                              description: Command is the command line to execute\n                                inside the container, the working directory for the\n                                command  is root ('/') in the container's filesystem.\n                                The command is simply exec'd, it is not run inside\n                                a shell, so traditional shell instructions ('|', etc)\n                                won't work. To use a shell, you need to explicitly\n                                call out to that shell. Exit status of 0 is treated\n                                as live/healthy and non-zero is unhealthy.\n                              items:\n                                type: string\n                              type: array\n                          type: object\n                        failureThreshold:\n                          description: Minimum consecutive failures for the probe\n                            to be considered failed after having succeeded. Defaults\n                            to 3. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        httpGet:\n                          description: HTTPGet specifies the http request to perform.\n                          properties:\n                            host:\n                              description: Host name to connect to, defaults to the\n                                pod IP. You probably want to set \"Host\" in httpHeaders\n                                instead.\n                              type: string\n                            httpHeaders:\n                              description: Custom headers to set in the request. HTTP\n                                allows repeated headers.\n                              items:\n                                description: HTTPHeader describes a custom header\n                                  to be used in HTTP probes\n                                properties:\n                                  name:\n                                    description: The header field name\n                                    type: string\n                                  value:\n                                    description: The header field value\n                                    type: string\n                                required:\n                                - name\n                                - value\n                                type: object\n                              type: array\n                            path:\n                              description: Path to access on the HTTP server.\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Name or number of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                            scheme:\n                              description: Scheme to use for connecting to the host.\n                                Defaults to HTTP.\n                              type: string\n                          required:\n                          - port\n                          type: object\n                        initialDelaySeconds:\n                          description: 'Number of seconds after the container has\n                            started before liveness probes are initiated. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                        periodSeconds:\n                          description: How often (in seconds) to perform the probe.\n                            Default to 10 seconds. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        successThreshold:\n                          description: Minimum consecutive successes for the probe\n                            to be considered successful after having failed. Defaults\n                            to 1. Must be 1 for liveness and startup. Minimum value\n                            is 1.\n                          format: int32\n                          type: integer\n                        tcpSocket:\n                          description: 'TCPSocket specifies an action involving a\n                            TCP port. TCP hooks not yet supported TODO: implement\n                            a realistic TCP lifecycle hook'\n                          properties:\n                            host:\n                              description: 'Optional: Host name to connect to, defaults\n                                to the pod IP.'\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Number or name of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                          required:\n                          - port\n                          type: object\n                        timeoutSeconds:\n                          description: 'Number of seconds after which the probe times\n                            out. Defaults to 1 second. Minimum value is 1. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                      type: object\n                    stdin:\n                      description: Whether this container should allocate a buffer\n                        for stdin in the container runtime. If this is not set, reads\n                        from stdin in the container will always result in EOF. Default\n                        is false.\n                      type: boolean\n                    stdinOnce:\n                      description: Whether the container runtime should close the\n                        stdin channel after it has been opened by a single attach.\n                        When stdin is true the stdin stream will remain open across\n                        multiple attach sessions. If stdinOnce is set to true, stdin\n                        is opened on container start, is empty until the first client\n                        attaches to stdin, and then remains open and accepts data\n                        until the client disconnects, at which time stdin is closed\n                        and remains closed until the container is restarted. If this\n                        flag is false, a container processes that reads from stdin\n                        will never receive an EOF. Default is false\n                      type: boolean\n                    terminationMessagePath:\n                      description: 'Optional: Path at which the file to which the\n                        container''s termination message will be written is mounted\n                        into the container''s filesystem. Message written is intended\n                        to be brief final status, such as an assertion failure message.\n                        Will be truncated by the node if greater than 4096 bytes.\n                        The total message length across all containers will be limited\n                        to 12kb. Defaults to /dev/termination-log. Cannot be updated.'\n                      type: string\n                    terminationMessagePolicy:\n                      description: Indicate how the termination message should be\n                        populated. File will use the contents of terminationMessagePath\n                        to populate the container status message on both success and\n                        failure. FallbackToLogsOnError will use the last chunk of\n                        container log output if the termination message file is empty\n                        and the container exited with an error. The log output is\n                        limited to 2048 bytes or 80 lines, whichever is smaller. Defaults\n                        to File. Cannot be updated.\n                      type: string\n                    tty:\n                      description: Whether this container should allocate a TTY for\n                        itself, also requires 'stdin' to be true. Default is false.\n                      type: boolean\n                    volumeDevices:\n                      description: volumeDevices is the list of block devices to be\n                        used by the container.\n                      items:\n                        description: volumeDevice describes a mapping of a raw block\n                          device within a container.\n                        properties:\n                          devicePath:\n                            description: devicePath is the path inside of the container\n                              that the device will be mapped to.\n                            type: string\n                          name:\n                            description: name must match the name of a persistentVolumeClaim\n                              in the pod\n                            type: string\n                        required:\n                        - devicePath\n                        - name\n                        type: object\n                      type: array\n                    volumeMounts:\n                      description: Pod volumes to mount into the container's filesystem.\n                        Cannot be updated.\n                      items:\n                        description: VolumeMount describes a mounting of a Volume\n                          within a container.\n                        properties:\n                          mountPath:\n                            description: Path within the container at which the volume\n                              should be mounted.  Must not contain ':'.\n                            type: string\n                          mountPropagation:\n                            description: mountPropagation determines how mounts are\n                              propagated from the host to container and the other\n                              way around. When not set, MountPropagationNone is used.\n                              This field is beta in 1.10.\n                            type: string\n                          name:\n                            description: This must match the Name of a Volume.\n                            type: string\n                          readOnly:\n                            description: Mounted read-only if true, read-write otherwise\n                              (false or unspecified). Defaults to false.\n                            type: boolean\n                          subPath:\n                            description: Path within the volume from which the container's\n                              volume should be mounted. Defaults to \"\" (volume's root).\n                            type: string\n                          subPathExpr:\n                            description: Expanded path within the volume from which\n                              the container's volume should be mounted. Behaves similarly\n                              to SubPath but environment variable references $(VAR_NAME)\n                              are expanded using the container's environment. Defaults\n                              to \"\" (volume's root). SubPathExpr and SubPath are mutually\n                              exclusive.\n                            type: string\n                        required:\n                        - mountPath\n                        - name\n                        type: object\n                      type: array\n                    workingDir:\n                      description: Container's working directory. If not specified,\n                        the container runtime's default will be used, which might\n                        be configured in the container image. Cannot be updated.\n                      type: string\n                  required:\n                  - name\n                  type: object\n                type: array\n              disableCompaction:\n                description: Disable prometheus compaction.\n                type: boolean\n              enableAdminAPI:\n                description: 'Enable access to prometheus web admin API. Defaults\n                  to the value of `false`. WARNING: Enabling the admin APIs enables\n                  mutating endpoints, to delete data, shutdown Prometheus, and more.\n                  Enabling this should be done with care and the user is advised to\n                  add additional authentication authorization via a proxy to ensure\n                  only clients authorized to perform these actions can do so. For\n                  more information see https://prometheus.io/docs/prometheus/latest/querying/api/#tsdb-admin-apis'\n                type: boolean\n              enableFeatures:\n                description: Enable access to Prometheus disabled features. By default,\n                  no features are enabled. Enabling disabled features is entirely\n                  outside the scope of what the maintainers will support and by doing\n                  so, you accept that this behaviour may break at any time without\n                  notice. For more information see https://prometheus.io/docs/prometheus/latest/disabled_features/\n                items:\n                  type: string\n                type: array\n              enforcedNamespaceLabel:\n                description: \"EnforcedNamespaceLabel If set, a label will be added\n                  to \\n 1. all user-metrics (created by `ServiceMonitor`, `PodMonitor`\n                  and `ProbeConfig` object) and 2. in all `PrometheusRule` objects\n                  (except the ones excluded in `prometheusRulesExcludedFromEnforce`)\n                  to    * alerting & recording rules and    * the metrics used in\n                  their expressions (`expr`). \\n Label name is this field's value.\n                  Label value is the namespace of the created object (mentioned above).\"\n                type: string\n              enforcedSampleLimit:\n                description: EnforcedSampleLimit defines global limit on number of\n                  scraped samples that will be accepted. This overrides any SampleLimit\n                  set per ServiceMonitor or/and PodMonitor. It is meant to be used\n                  by admins to enforce the SampleLimit to keep overall number of samples/series\n                  under the desired limit. Note that if SampleLimit is lower that\n                  value will be taken instead.\n                format: int64\n                type: integer\n              enforcedTargetLimit:\n                description: EnforcedTargetLimit defines a global limit on the number\n                  of scraped targets. This overrides any TargetLimit set per ServiceMonitor\n                  or/and PodMonitor. It is meant to be used by admins to enforce the\n                  TargetLimit to keep overall number of targets under the desired\n                  limit. Note that if TargetLimit is higher that value will be taken\n                  instead.\n                format: int64\n                type: integer\n              evaluationInterval:\n                description: 'Interval between consecutive evaluations. Default: `1m`'\n                type: string\n              externalLabels:\n                additionalProperties:\n                  type: string\n                description: The labels to add to any time series or alerts when communicating\n                  with external systems (federation, remote storage, Alertmanager).\n                type: object\n              externalUrl:\n                description: The external URL the Prometheus instances will be available\n                  under. This is necessary to generate correct URLs. This is necessary\n                  if Prometheus is not served from root of a DNS name.\n                type: string\n              ignoreNamespaceSelectors:\n                description: IgnoreNamespaceSelectors if set to true will ignore NamespaceSelector\n                  settings from the podmonitor and servicemonitor configs, and they\n                  will only discover endpoints within their current namespace.  Defaults\n                  to false.\n                type: boolean\n              image:\n                description: Image if specified has precedence over baseImage, tag\n                  and sha combinations. Specifying the version is still necessary\n                  to ensure the Prometheus Operator knows what version of Prometheus\n                  is being configured.\n                type: string\n              imagePullSecrets:\n                description: An optional list of references to secrets in the same\n                  namespace to use for pulling prometheus and alertmanager images\n                  from registries see http://kubernetes.io/docs/user-guide/images#specifying-imagepullsecrets-on-a-pod\n                items:\n                  description: LocalObjectReference contains enough information to\n                    let you locate the referenced object inside the same namespace.\n                  properties:\n                    name:\n                      description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                        TODO: Add other useful fields. apiVersion, kind, uid?'\n                      type: string\n                  type: object\n                type: array\n              initContainers:\n                description: 'InitContainers allows adding initContainers to the pod\n                  definition. Those can be used to e.g. fetch secrets for injection\n                  into the Prometheus configuration from external sources. Any errors\n                  during the execution of an initContainer will lead to a restart\n                  of the Pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/\n                  InitContainers described here modify an operator generated init\n                  containers if they share the same name and modifications are done\n                  via a strategic merge patch. The current init container name is:\n                  `init-config-reloader`. Overriding init containers is entirely outside\n                  the scope of what the maintainers will support and by doing so,\n                  you accept that this behaviour may break at any time without notice.'\n                items:\n                  description: A single application container that you want to run\n                    within a pod.\n                  properties:\n                    args:\n                      description: 'Arguments to the entrypoint. The docker image''s\n                        CMD is used if this is not provided. Variable references $(VAR_NAME)\n                        are expanded using the container''s environment. If a variable\n                        cannot be resolved, the reference in the input string will\n                        be unchanged. The $(VAR_NAME) syntax can be escaped with a\n                        double $$, ie: $$(VAR_NAME). Escaped references will never\n                        be expanded, regardless of whether the variable exists or\n                        not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell'\n                      items:\n                        type: string\n                      type: array\n                    command:\n                      description: 'Entrypoint array. Not executed within a shell.\n                        The docker image''s ENTRYPOINT is used if this is not provided.\n                        Variable references $(VAR_NAME) are expanded using the container''s\n                        environment. If a variable cannot be resolved, the reference\n                        in the input string will be unchanged. The $(VAR_NAME) syntax\n                        can be escaped with a double $$, ie: $$(VAR_NAME). Escaped\n                        references will never be expanded, regardless of whether the\n                        variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell'\n                      items:\n                        type: string\n                      type: array\n                    env:\n                      description: List of environment variables to set in the container.\n                        Cannot be updated.\n                      items:\n                        description: EnvVar represents an environment variable present\n                          in a Container.\n                        properties:\n                          name:\n                            description: Name of the environment variable. Must be\n                              a C_IDENTIFIER.\n                            type: string\n                          value:\n                            description: 'Variable references $(VAR_NAME) are expanded\n                              using the previous defined environment variables in\n                              the container and any service environment variables.\n                              If a variable cannot be resolved, the reference in the\n                              input string will be unchanged. The $(VAR_NAME) syntax\n                              can be escaped with a double $$, ie: $$(VAR_NAME). Escaped\n                              references will never be expanded, regardless of whether\n                              the variable exists or not. Defaults to \"\".'\n                            type: string\n                          valueFrom:\n                            description: Source for the environment variable's value.\n                              Cannot be used if value is not empty.\n                            properties:\n                              configMapKeyRef:\n                                description: Selects a key of a ConfigMap.\n                                properties:\n                                  key:\n                                    description: The key to select.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the ConfigMap or\n                                      its key must be defined\n                                    type: boolean\n                                required:\n                                - key\n                                type: object\n                              fieldRef:\n                                description: 'Selects a field of the pod: supports\n                                  metadata.name, metadata.namespace, metadata.labels,\n                                  metadata.annotations, spec.nodeName, spec.serviceAccountName,\n                                  status.hostIP, status.podIP, status.podIPs.'\n                                properties:\n                                  apiVersion:\n                                    description: Version of the schema the FieldPath\n                                      is written in terms of, defaults to \"v1\".\n                                    type: string\n                                  fieldPath:\n                                    description: Path of the field to select in the\n                                      specified API version.\n                                    type: string\n                                required:\n                                - fieldPath\n                                type: object\n                              resourceFieldRef:\n                                description: 'Selects a resource of the container:\n                                  only resources limits and requests (limits.cpu,\n                                  limits.memory, limits.ephemeral-storage, requests.cpu,\n                                  requests.memory and requests.ephemeral-storage)\n                                  are currently supported.'\n                                properties:\n                                  containerName:\n                                    description: 'Container name: required for volumes,\n                                      optional for env vars'\n                                    type: string\n                                  divisor:\n                                    anyOf:\n                                    - type: integer\n                                    - type: string\n                                    description: Specifies the output format of the\n                                      exposed resources, defaults to \"1\"\n                                    pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                    x-kubernetes-int-or-string: true\n                                  resource:\n                                    description: 'Required: resource to select'\n                                    type: string\n                                required:\n                                - resource\n                                type: object\n                              secretKeyRef:\n                                description: Selects a key of a secret in the pod's\n                                  namespace\n                                properties:\n                                  key:\n                                    description: The key of the secret to select from.  Must\n                                      be a valid secret key.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the Secret or its\n                                      key must be defined\n                                    type: boolean\n                                required:\n                                - key\n                                type: object\n                            type: object\n                        required:\n                        - name\n                        type: object\n                      type: array\n                    envFrom:\n                      description: List of sources to populate environment variables\n                        in the container. The keys defined within a source must be\n                        a C_IDENTIFIER. All invalid keys will be reported as an event\n                        when the container is starting. When a key exists in multiple\n                        sources, the value associated with the last source will take\n                        precedence. Values defined by an Env with a duplicate key\n                        will take precedence. Cannot be updated.\n                      items:\n                        description: EnvFromSource represents the source of a set\n                          of ConfigMaps\n                        properties:\n                          configMapRef:\n                            description: The ConfigMap to select from\n                            properties:\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the ConfigMap must be\n                                  defined\n                                type: boolean\n                            type: object\n                          prefix:\n                            description: An optional identifier to prepend to each\n                              key in the ConfigMap. Must be a C_IDENTIFIER.\n                            type: string\n                          secretRef:\n                            description: The Secret to select from\n                            properties:\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret must be defined\n                                type: boolean\n                            type: object\n                        type: object\n                      type: array\n                    image:\n                      description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images\n                        This field is optional to allow higher level config management\n                        to default or override container images in workload controllers\n                        like Deployments and StatefulSets.'\n                      type: string\n                    imagePullPolicy:\n                      description: 'Image pull policy. One of Always, Never, IfNotPresent.\n                        Defaults to Always if :latest tag is specified, or IfNotPresent\n                        otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images'\n                      type: string\n                    lifecycle:\n                      description: Actions that the management system should take\n                        in response to container lifecycle events. Cannot be updated.\n                      properties:\n                        postStart:\n                          description: 'PostStart is called immediately after a container\n                            is created. If the handler fails, the container is terminated\n                            and restarted according to its restart policy. Other management\n                            of the container blocks until the hook completes. More\n                            info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks'\n                          properties:\n                            exec:\n                              description: One and only one of the following should\n                                be specified. Exec specifies the action to take.\n                              properties:\n                                command:\n                                  description: Command is the command line to execute\n                                    inside the container, the working directory for\n                                    the command  is root ('/') in the container's\n                                    filesystem. The command is simply exec'd, it is\n                                    not run inside a shell, so traditional shell instructions\n                                    ('|', etc) won't work. To use a shell, you need\n                                    to explicitly call out to that shell. Exit status\n                                    of 0 is treated as live/healthy and non-zero is\n                                    unhealthy.\n                                  items:\n                                    type: string\n                                  type: array\n                              type: object\n                            httpGet:\n                              description: HTTPGet specifies the http request to perform.\n                              properties:\n                                host:\n                                  description: Host name to connect to, defaults to\n                                    the pod IP. You probably want to set \"Host\" in\n                                    httpHeaders instead.\n                                  type: string\n                                httpHeaders:\n                                  description: Custom headers to set in the request.\n                                    HTTP allows repeated headers.\n                                  items:\n                                    description: HTTPHeader describes a custom header\n                                      to be used in HTTP probes\n                                    properties:\n                                      name:\n                                        description: The header field name\n                                        type: string\n                                      value:\n                                        description: The header field value\n                                        type: string\n                                    required:\n                                    - name\n                                    - value\n                                    type: object\n                                  type: array\n                                path:\n                                  description: Path to access on the HTTP server.\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Name or number of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                                scheme:\n                                  description: Scheme to use for connecting to the\n                                    host. Defaults to HTTP.\n                                  type: string\n                              required:\n                              - port\n                              type: object\n                            tcpSocket:\n                              description: 'TCPSocket specifies an action involving\n                                a TCP port. TCP hooks not yet supported TODO: implement\n                                a realistic TCP lifecycle hook'\n                              properties:\n                                host:\n                                  description: 'Optional: Host name to connect to,\n                                    defaults to the pod IP.'\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Number or name of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                              required:\n                              - port\n                              type: object\n                          type: object\n                        preStop:\n                          description: 'PreStop is called immediately before a container\n                            is terminated due to an API request or management event\n                            such as liveness/startup probe failure, preemption, resource\n                            contention, etc. The handler is not called if the container\n                            crashes or exits. The reason for termination is passed\n                            to the handler. The Pod''s termination grace period countdown\n                            begins before the PreStop hooked is executed. Regardless\n                            of the outcome of the handler, the container will eventually\n                            terminate within the Pod''s termination grace period.\n                            Other management of the container blocks until the hook\n                            completes or until the termination grace period is reached.\n                            More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks'\n                          properties:\n                            exec:\n                              description: One and only one of the following should\n                                be specified. Exec specifies the action to take.\n                              properties:\n                                command:\n                                  description: Command is the command line to execute\n                                    inside the container, the working directory for\n                                    the command  is root ('/') in the container's\n                                    filesystem. The command is simply exec'd, it is\n                                    not run inside a shell, so traditional shell instructions\n                                    ('|', etc) won't work. To use a shell, you need\n                                    to explicitly call out to that shell. Exit status\n                                    of 0 is treated as live/healthy and non-zero is\n                                    unhealthy.\n                                  items:\n                                    type: string\n                                  type: array\n                              type: object\n                            httpGet:\n                              description: HTTPGet specifies the http request to perform.\n                              properties:\n                                host:\n                                  description: Host name to connect to, defaults to\n                                    the pod IP. You probably want to set \"Host\" in\n                                    httpHeaders instead.\n                                  type: string\n                                httpHeaders:\n                                  description: Custom headers to set in the request.\n                                    HTTP allows repeated headers.\n                                  items:\n                                    description: HTTPHeader describes a custom header\n                                      to be used in HTTP probes\n                                    properties:\n                                      name:\n                                        description: The header field name\n                                        type: string\n                                      value:\n                                        description: The header field value\n                                        type: string\n                                    required:\n                                    - name\n                                    - value\n                                    type: object\n                                  type: array\n                                path:\n                                  description: Path to access on the HTTP server.\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Name or number of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                                scheme:\n                                  description: Scheme to use for connecting to the\n                                    host. Defaults to HTTP.\n                                  type: string\n                              required:\n                              - port\n                              type: object\n                            tcpSocket:\n                              description: 'TCPSocket specifies an action involving\n                                a TCP port. TCP hooks not yet supported TODO: implement\n                                a realistic TCP lifecycle hook'\n                              properties:\n                                host:\n                                  description: 'Optional: Host name to connect to,\n                                    defaults to the pod IP.'\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Number or name of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                              required:\n                              - port\n                              type: object\n                          type: object\n                      type: object\n                    livenessProbe:\n                      description: 'Periodic probe of container liveness. Container\n                        will be restarted if the probe fails. Cannot be updated. More\n                        info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                      properties:\n                        exec:\n                          description: One and only one of the following should be\n                            specified. Exec specifies the action to take.\n                          properties:\n                            command:\n                              description: Command is the command line to execute\n                                inside the container, the working directory for the\n                                command  is root ('/') in the container's filesystem.\n                                The command is simply exec'd, it is not run inside\n                                a shell, so traditional shell instructions ('|', etc)\n                                won't work. To use a shell, you need to explicitly\n                                call out to that shell. Exit status of 0 is treated\n                                as live/healthy and non-zero is unhealthy.\n                              items:\n                                type: string\n                              type: array\n                          type: object\n                        failureThreshold:\n                          description: Minimum consecutive failures for the probe\n                            to be considered failed after having succeeded. Defaults\n                            to 3. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        httpGet:\n                          description: HTTPGet specifies the http request to perform.\n                          properties:\n                            host:\n                              description: Host name to connect to, defaults to the\n                                pod IP. You probably want to set \"Host\" in httpHeaders\n                                instead.\n                              type: string\n                            httpHeaders:\n                              description: Custom headers to set in the request. HTTP\n                                allows repeated headers.\n                              items:\n                                description: HTTPHeader describes a custom header\n                                  to be used in HTTP probes\n                                properties:\n                                  name:\n                                    description: The header field name\n                                    type: string\n                                  value:\n                                    description: The header field value\n                                    type: string\n                                required:\n                                - name\n                                - value\n                                type: object\n                              type: array\n                            path:\n                              description: Path to access on the HTTP server.\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Name or number of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                            scheme:\n                              description: Scheme to use for connecting to the host.\n                                Defaults to HTTP.\n                              type: string\n                          required:\n                          - port\n                          type: object\n                        initialDelaySeconds:\n                          description: 'Number of seconds after the container has\n                            started before liveness probes are initiated. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                        periodSeconds:\n                          description: How often (in seconds) to perform the probe.\n                            Default to 10 seconds. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        successThreshold:\n                          description: Minimum consecutive successes for the probe\n                            to be considered successful after having failed. Defaults\n                            to 1. Must be 1 for liveness and startup. Minimum value\n                            is 1.\n                          format: int32\n                          type: integer\n                        tcpSocket:\n                          description: 'TCPSocket specifies an action involving a\n                            TCP port. TCP hooks not yet supported TODO: implement\n                            a realistic TCP lifecycle hook'\n                          properties:\n                            host:\n                              description: 'Optional: Host name to connect to, defaults\n                                to the pod IP.'\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Number or name of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                          required:\n                          - port\n                          type: object\n                        timeoutSeconds:\n                          description: 'Number of seconds after which the probe times\n                            out. Defaults to 1 second. Minimum value is 1. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                      type: object\n                    name:\n                      description: Name of the container specified as a DNS_LABEL.\n                        Each container in a pod must have a unique name (DNS_LABEL).\n                        Cannot be updated.\n                      type: string\n                    ports:\n                      description: List of ports to expose from the container. Exposing\n                        a port here gives the system additional information about\n                        the network connections a container uses, but is primarily\n                        informational. Not specifying a port here DOES NOT prevent\n                        that port from being exposed. Any port which is listening\n                        on the default \"0.0.0.0\" address inside a container will be\n                        accessible from the network. Cannot be updated.\n                      items:\n                        description: ContainerPort represents a network port in a\n                          single container.\n                        properties:\n                          containerPort:\n                            description: Number of port to expose on the pod's IP\n                              address. This must be a valid port number, 0 < x < 65536.\n                            format: int32\n                            type: integer\n                          hostIP:\n                            description: What host IP to bind the external port to.\n                            type: string\n                          hostPort:\n                            description: Number of port to expose on the host. If\n                              specified, this must be a valid port number, 0 < x <\n                              65536. If HostNetwork is specified, this must match\n                              ContainerPort. Most containers do not need this.\n                            format: int32\n                            type: integer\n                          name:\n                            description: If specified, this must be an IANA_SVC_NAME\n                              and unique within the pod. Each named port in a pod\n                              must have a unique name. Name for the port that can\n                              be referred to by services.\n                            type: string\n                          protocol:\n                            default: TCP\n                            description: Protocol for port. Must be UDP, TCP, or SCTP.\n                              Defaults to \"TCP\".\n                            type: string\n                        required:\n                        - containerPort\n                        type: object\n                      type: array\n                      x-kubernetes-list-map-keys:\n                      - containerPort\n                      - protocol\n                      x-kubernetes-list-type: map\n                    readinessProbe:\n                      description: 'Periodic probe of container service readiness.\n                        Container will be removed from service endpoints if the probe\n                        fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                      properties:\n                        exec:\n                          description: One and only one of the following should be\n                            specified. Exec specifies the action to take.\n                          properties:\n                            command:\n                              description: Command is the command line to execute\n                                inside the container, the working directory for the\n                                command  is root ('/') in the container's filesystem.\n                                The command is simply exec'd, it is not run inside\n                                a shell, so traditional shell instructions ('|', etc)\n                                won't work. To use a shell, you need to explicitly\n                                call out to that shell. Exit status of 0 is treated\n                                as live/healthy and non-zero is unhealthy.\n                              items:\n                                type: string\n                              type: array\n                          type: object\n                        failureThreshold:\n                          description: Minimum consecutive failures for the probe\n                            to be considered failed after having succeeded. Defaults\n                            to 3. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        httpGet:\n                          description: HTTPGet specifies the http request to perform.\n                          properties:\n                            host:\n                              description: Host name to connect to, defaults to the\n                                pod IP. You probably want to set \"Host\" in httpHeaders\n                                instead.\n                              type: string\n                            httpHeaders:\n                              description: Custom headers to set in the request. HTTP\n                                allows repeated headers.\n                              items:\n                                description: HTTPHeader describes a custom header\n                                  to be used in HTTP probes\n                                properties:\n                                  name:\n                                    description: The header field name\n                                    type: string\n                                  value:\n                                    description: The header field value\n                                    type: string\n                                required:\n                                - name\n                                - value\n                                type: object\n                              type: array\n                            path:\n                              description: Path to access on the HTTP server.\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Name or number of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                            scheme:\n                              description: Scheme to use for connecting to the host.\n                                Defaults to HTTP.\n                              type: string\n                          required:\n                          - port\n                          type: object\n                        initialDelaySeconds:\n                          description: 'Number of seconds after the container has\n                            started before liveness probes are initiated. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                        periodSeconds:\n                          description: How often (in seconds) to perform the probe.\n                            Default to 10 seconds. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        successThreshold:\n                          description: Minimum consecutive successes for the probe\n                            to be considered successful after having failed. Defaults\n                            to 1. Must be 1 for liveness and startup. Minimum value\n                            is 1.\n                          format: int32\n                          type: integer\n                        tcpSocket:\n                          description: 'TCPSocket specifies an action involving a\n                            TCP port. TCP hooks not yet supported TODO: implement\n                            a realistic TCP lifecycle hook'\n                          properties:\n                            host:\n                              description: 'Optional: Host name to connect to, defaults\n                                to the pod IP.'\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Number or name of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                          required:\n                          - port\n                          type: object\n                        timeoutSeconds:\n                          description: 'Number of seconds after which the probe times\n                            out. Defaults to 1 second. Minimum value is 1. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                      type: object\n                    resources:\n                      description: 'Compute Resources required by this container.\n                        Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                      properties:\n                        limits:\n                          additionalProperties:\n                            anyOf:\n                            - type: integer\n                            - type: string\n                            pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                            x-kubernetes-int-or-string: true\n                          description: 'Limits describes the maximum amount of compute\n                            resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                          type: object\n                        requests:\n                          additionalProperties:\n                            anyOf:\n                            - type: integer\n                            - type: string\n                            pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                            x-kubernetes-int-or-string: true\n                          description: 'Requests describes the minimum amount of compute\n                            resources required. If Requests is omitted for a container,\n                            it defaults to Limits if that is explicitly specified,\n                            otherwise to an implementation-defined value. More info:\n                            https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                          type: object\n                      type: object\n                    securityContext:\n                      description: 'Security options the pod should run with. More\n                        info: https://kubernetes.io/docs/concepts/policy/security-context/\n                        More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/'\n                      properties:\n                        allowPrivilegeEscalation:\n                          description: 'AllowPrivilegeEscalation controls whether\n                            a process can gain more privileges than its parent process.\n                            This bool directly controls if the no_new_privs flag will\n                            be set on the container process. AllowPrivilegeEscalation\n                            is true always when the container is: 1) run as Privileged\n                            2) has CAP_SYS_ADMIN'\n                          type: boolean\n                        capabilities:\n                          description: The capabilities to add/drop when running containers.\n                            Defaults to the default set of capabilities granted by\n                            the container runtime.\n                          properties:\n                            add:\n                              description: Added capabilities\n                              items:\n                                description: Capability represent POSIX capabilities\n                                  type\n                                type: string\n                              type: array\n                            drop:\n                              description: Removed capabilities\n                              items:\n                                description: Capability represent POSIX capabilities\n                                  type\n                                type: string\n                              type: array\n                          type: object\n                        privileged:\n                          description: Run container in privileged mode. Processes\n                            in privileged containers are essentially equivalent to\n                            root on the host. Defaults to false.\n                          type: boolean\n                        procMount:\n                          description: procMount denotes the type of proc mount to\n                            use for the containers. The default is DefaultProcMount\n                            which uses the container runtime defaults for readonly\n                            paths and masked paths. This requires the ProcMountType\n                            feature flag to be enabled.\n                          type: string\n                        readOnlyRootFilesystem:\n                          description: Whether this container has a read-only root\n                            filesystem. Default is false.\n                          type: boolean\n                        runAsGroup:\n                          description: The GID to run the entrypoint of the container\n                            process. Uses runtime default if unset. May also be set\n                            in PodSecurityContext.  If set in both SecurityContext\n                            and PodSecurityContext, the value specified in SecurityContext\n                            takes precedence.\n                          format: int64\n                          type: integer\n                        runAsNonRoot:\n                          description: Indicates that the container must run as a\n                            non-root user. If true, the Kubelet will validate the\n                            image at runtime to ensure that it does not run as UID\n                            0 (root) and fail to start the container if it does. If\n                            unset or false, no such validation will be performed.\n                            May also be set in PodSecurityContext.  If set in both\n                            SecurityContext and PodSecurityContext, the value specified\n                            in SecurityContext takes precedence.\n                          type: boolean\n                        runAsUser:\n                          description: The UID to run the entrypoint of the container\n                            process. Defaults to user specified in image metadata\n                            if unspecified. May also be set in PodSecurityContext.  If\n                            set in both SecurityContext and PodSecurityContext, the\n                            value specified in SecurityContext takes precedence.\n                          format: int64\n                          type: integer\n                        seLinuxOptions:\n                          description: The SELinux context to be applied to the container.\n                            If unspecified, the container runtime will allocate a\n                            random SELinux context for each container.  May also be\n                            set in PodSecurityContext.  If set in both SecurityContext\n                            and PodSecurityContext, the value specified in SecurityContext\n                            takes precedence.\n                          properties:\n                            level:\n                              description: Level is SELinux level label that applies\n                                to the container.\n                              type: string\n                            role:\n                              description: Role is a SELinux role label that applies\n                                to the container.\n                              type: string\n                            type:\n                              description: Type is a SELinux type label that applies\n                                to the container.\n                              type: string\n                            user:\n                              description: User is a SELinux user label that applies\n                                to the container.\n                              type: string\n                          type: object\n                        windowsOptions:\n                          description: The Windows specific settings applied to all\n                            containers. If unspecified, the options from the PodSecurityContext\n                            will be used. If set in both SecurityContext and PodSecurityContext,\n                            the value specified in SecurityContext takes precedence.\n                          properties:\n                            gmsaCredentialSpec:\n                              description: GMSACredentialSpec is where the GMSA admission\n                                webhook (https://github.com/kubernetes-sigs/windows-gmsa)\n                                inlines the contents of the GMSA credential spec named\n                                by the GMSACredentialSpecName field.\n                              type: string\n                            gmsaCredentialSpecName:\n                              description: GMSACredentialSpecName is the name of the\n                                GMSA credential spec to use.\n                              type: string\n                            runAsUserName:\n                              description: The UserName in Windows to run the entrypoint\n                                of the container process. Defaults to the user specified\n                                in image metadata if unspecified. May also be set\n                                in PodSecurityContext. If set in both SecurityContext\n                                and PodSecurityContext, the value specified in SecurityContext\n                                takes precedence.\n                              type: string\n                          type: object\n                      type: object\n                    startupProbe:\n                      description: 'StartupProbe indicates that the Pod has successfully\n                        initialized. If specified, no other probes are executed until\n                        this completes successfully. If this probe fails, the Pod\n                        will be restarted, just as if the livenessProbe failed. This\n                        can be used to provide different probe parameters at the beginning\n                        of a Pod''s lifecycle, when it might take a long time to load\n                        data or warm a cache, than during steady-state operation.\n                        This cannot be updated. This is a beta feature enabled by\n                        the StartupProbe feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                      properties:\n                        exec:\n                          description: One and only one of the following should be\n                            specified. Exec specifies the action to take.\n                          properties:\n                            command:\n                              description: Command is the command line to execute\n                                inside the container, the working directory for the\n                                command  is root ('/') in the container's filesystem.\n                                The command is simply exec'd, it is not run inside\n                                a shell, so traditional shell instructions ('|', etc)\n                                won't work. To use a shell, you need to explicitly\n                                call out to that shell. Exit status of 0 is treated\n                                as live/healthy and non-zero is unhealthy.\n                              items:\n                                type: string\n                              type: array\n                          type: object\n                        failureThreshold:\n                          description: Minimum consecutive failures for the probe\n                            to be considered failed after having succeeded. Defaults\n                            to 3. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        httpGet:\n                          description: HTTPGet specifies the http request to perform.\n                          properties:\n                            host:\n                              description: Host name to connect to, defaults to the\n                                pod IP. You probably want to set \"Host\" in httpHeaders\n                                instead.\n                              type: string\n                            httpHeaders:\n                              description: Custom headers to set in the request. HTTP\n                                allows repeated headers.\n                              items:\n                                description: HTTPHeader describes a custom header\n                                  to be used in HTTP probes\n                                properties:\n                                  name:\n                                    description: The header field name\n                                    type: string\n                                  value:\n                                    description: The header field value\n                                    type: string\n                                required:\n                                - name\n                                - value\n                                type: object\n                              type: array\n                            path:\n                              description: Path to access on the HTTP server.\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Name or number of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                            scheme:\n                              description: Scheme to use for connecting to the host.\n                                Defaults to HTTP.\n                              type: string\n                          required:\n                          - port\n                          type: object\n                        initialDelaySeconds:\n                          description: 'Number of seconds after the container has\n                            started before liveness probes are initiated. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                        periodSeconds:\n                          description: How often (in seconds) to perform the probe.\n                            Default to 10 seconds. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        successThreshold:\n                          description: Minimum consecutive successes for the probe\n                            to be considered successful after having failed. Defaults\n                            to 1. Must be 1 for liveness and startup. Minimum value\n                            is 1.\n                          format: int32\n                          type: integer\n                        tcpSocket:\n                          description: 'TCPSocket specifies an action involving a\n                            TCP port. TCP hooks not yet supported TODO: implement\n                            a realistic TCP lifecycle hook'\n                          properties:\n                            host:\n                              description: 'Optional: Host name to connect to, defaults\n                                to the pod IP.'\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Number or name of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                          required:\n                          - port\n                          type: object\n                        timeoutSeconds:\n                          description: 'Number of seconds after which the probe times\n                            out. Defaults to 1 second. Minimum value is 1. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                      type: object\n                    stdin:\n                      description: Whether this container should allocate a buffer\n                        for stdin in the container runtime. If this is not set, reads\n                        from stdin in the container will always result in EOF. Default\n                        is false.\n                      type: boolean\n                    stdinOnce:\n                      description: Whether the container runtime should close the\n                        stdin channel after it has been opened by a single attach.\n                        When stdin is true the stdin stream will remain open across\n                        multiple attach sessions. If stdinOnce is set to true, stdin\n                        is opened on container start, is empty until the first client\n                        attaches to stdin, and then remains open and accepts data\n                        until the client disconnects, at which time stdin is closed\n                        and remains closed until the container is restarted. If this\n                        flag is false, a container processes that reads from stdin\n                        will never receive an EOF. Default is false\n                      type: boolean\n                    terminationMessagePath:\n                      description: 'Optional: Path at which the file to which the\n                        container''s termination message will be written is mounted\n                        into the container''s filesystem. Message written is intended\n                        to be brief final status, such as an assertion failure message.\n                        Will be truncated by the node if greater than 4096 bytes.\n                        The total message length across all containers will be limited\n                        to 12kb. Defaults to /dev/termination-log. Cannot be updated.'\n                      type: string\n                    terminationMessagePolicy:\n                      description: Indicate how the termination message should be\n                        populated. File will use the contents of terminationMessagePath\n                        to populate the container status message on both success and\n                        failure. FallbackToLogsOnError will use the last chunk of\n                        container log output if the termination message file is empty\n                        and the container exited with an error. The log output is\n                        limited to 2048 bytes or 80 lines, whichever is smaller. Defaults\n                        to File. Cannot be updated.\n                      type: string\n                    tty:\n                      description: Whether this container should allocate a TTY for\n                        itself, also requires 'stdin' to be true. Default is false.\n                      type: boolean\n                    volumeDevices:\n                      description: volumeDevices is the list of block devices to be\n                        used by the container.\n                      items:\n                        description: volumeDevice describes a mapping of a raw block\n                          device within a container.\n                        properties:\n                          devicePath:\n                            description: devicePath is the path inside of the container\n                              that the device will be mapped to.\n                            type: string\n                          name:\n                            description: name must match the name of a persistentVolumeClaim\n                              in the pod\n                            type: string\n                        required:\n                        - devicePath\n                        - name\n                        type: object\n                      type: array\n                    volumeMounts:\n                      description: Pod volumes to mount into the container's filesystem.\n                        Cannot be updated.\n                      items:\n                        description: VolumeMount describes a mounting of a Volume\n                          within a container.\n                        properties:\n                          mountPath:\n                            description: Path within the container at which the volume\n                              should be mounted.  Must not contain ':'.\n                            type: string\n                          mountPropagation:\n                            description: mountPropagation determines how mounts are\n                              propagated from the host to container and the other\n                              way around. When not set, MountPropagationNone is used.\n                              This field is beta in 1.10.\n                            type: string\n                          name:\n                            description: This must match the Name of a Volume.\n                            type: string\n                          readOnly:\n                            description: Mounted read-only if true, read-write otherwise\n                              (false or unspecified). Defaults to false.\n                            type: boolean\n                          subPath:\n                            description: Path within the volume from which the container's\n                              volume should be mounted. Defaults to \"\" (volume's root).\n                            type: string\n                          subPathExpr:\n                            description: Expanded path within the volume from which\n                              the container's volume should be mounted. Behaves similarly\n                              to SubPath but environment variable references $(VAR_NAME)\n                              are expanded using the container's environment. Defaults\n                              to \"\" (volume's root). SubPathExpr and SubPath are mutually\n                              exclusive.\n                            type: string\n                        required:\n                        - mountPath\n                        - name\n                        type: object\n                      type: array\n                    workingDir:\n                      description: Container's working directory. If not specified,\n                        the container runtime's default will be used, which might\n                        be configured in the container image. Cannot be updated.\n                      type: string\n                  required:\n                  - name\n                  type: object\n                type: array\n              listenLocal:\n                description: ListenLocal makes the Prometheus server listen on loopback,\n                  so that it does not bind against the Pod IP.\n                type: boolean\n              logFormat:\n                description: Log format for Prometheus to be configured with.\n                type: string\n              logLevel:\n                description: Log level for Prometheus to be configured with.\n                type: string\n              nodeSelector:\n                additionalProperties:\n                  type: string\n                description: Define which Nodes the Pods are scheduled on.\n                type: object\n              overrideHonorLabels:\n                description: OverrideHonorLabels if set to true overrides all user\n                  configured honor_labels. If HonorLabels is set in ServiceMonitor\n                  or PodMonitor to true, this overrides honor_labels to false.\n                type: boolean\n              overrideHonorTimestamps:\n                description: OverrideHonorTimestamps allows to globally enforce honoring\n                  timestamps in all scrape configs.\n                type: boolean\n              paused:\n                description: When a Prometheus deployment is paused, no actions except\n                  for deletion will be performed on the underlying objects.\n                type: boolean\n              podMetadata:\n                description: PodMetadata configures Labels and Annotations which are\n                  propagated to the prometheus pods.\n                properties:\n                  annotations:\n                    additionalProperties:\n                      type: string\n                    description: 'Annotations is an unstructured key value map stored\n                      with a resource that may be set by external tools to store and\n                      retrieve arbitrary metadata. They are not queryable and should\n                      be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations'\n                    type: object\n                  labels:\n                    additionalProperties:\n                      type: string\n                    description: 'Map of string keys and values that can be used to\n                      organize and categorize (scope and select) objects. May match\n                      selectors of replication controllers and services. More info:\n                      http://kubernetes.io/docs/user-guide/labels'\n                    type: object\n                  name:\n                    description: 'Name must be unique within a namespace. Is required\n                      when creating resources, although some resources may allow a\n                      client to request the generation of an appropriate name automatically.\n                      Name is primarily intended for creation idempotence and configuration\n                      definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names'\n                    type: string\n                type: object\n              podMonitorNamespaceSelector:\n                description: Namespace's labels to match for PodMonitor discovery.\n                  If nil, only check own namespace.\n                properties:\n                  matchExpressions:\n                    description: matchExpressions is a list of label selector requirements.\n                      The requirements are ANDed.\n                    items:\n                      description: A label selector requirement is a selector that\n                        contains values, a key, and an operator that relates the key\n                        and values.\n                      properties:\n                        key:\n                          description: key is the label key that the selector applies\n                            to.\n                          type: string\n                        operator:\n                          description: operator represents a key's relationship to\n                            a set of values. Valid operators are In, NotIn, Exists\n                            and DoesNotExist.\n                          type: string\n                        values:\n                          description: values is an array of string values. If the\n                            operator is In or NotIn, the values array must be non-empty.\n                            If the operator is Exists or DoesNotExist, the values\n                            array must be empty. This array is replaced during a strategic\n                            merge patch.\n                          items:\n                            type: string\n                          type: array\n                      required:\n                      - key\n                      - operator\n                      type: object\n                    type: array\n                  matchLabels:\n                    additionalProperties:\n                      type: string\n                    description: matchLabels is a map of {key,value} pairs. A single\n                      {key,value} in the matchLabels map is equivalent to an element\n                      of matchExpressions, whose key field is \"key\", the operator\n                      is \"In\", and the values array contains only \"value\". The requirements\n                      are ANDed.\n                    type: object\n                type: object\n              podMonitorSelector:\n                description: '*Experimental* PodMonitors to be selected for target\n                  discovery. *Deprecated:* if neither this nor serviceMonitorSelector\n                  are specified, configuration is unmanaged.'\n                properties:\n                  matchExpressions:\n                    description: matchExpressions is a list of label selector requirements.\n                      The requirements are ANDed.\n                    items:\n                      description: A label selector requirement is a selector that\n                        contains values, a key, and an operator that relates the key\n                        and values.\n                      properties:\n                        key:\n                          description: key is the label key that the selector applies\n                            to.\n                          type: string\n                        operator:\n                          description: operator represents a key's relationship to\n                            a set of values. Valid operators are In, NotIn, Exists\n                            and DoesNotExist.\n                          type: string\n                        values:\n                          description: values is an array of string values. If the\n                            operator is In or NotIn, the values array must be non-empty.\n                            If the operator is Exists or DoesNotExist, the values\n                            array must be empty. This array is replaced during a strategic\n                            merge patch.\n                          items:\n                            type: string\n                          type: array\n                      required:\n                      - key\n                      - operator\n                      type: object\n                    type: array\n                  matchLabels:\n                    additionalProperties:\n                      type: string\n                    description: matchLabels is a map of {key,value} pairs. A single\n                      {key,value} in the matchLabels map is equivalent to an element\n                      of matchExpressions, whose key field is \"key\", the operator\n                      is \"In\", and the values array contains only \"value\". The requirements\n                      are ANDed.\n                    type: object\n                type: object\n              portName:\n                description: Port name used for the pods and governing service. This\n                  defaults to web\n                type: string\n              priorityClassName:\n                description: Priority class assigned to the Pods\n                type: string\n              probeNamespaceSelector:\n                description: '*Experimental* Namespaces to be selected for Probe discovery.\n                  If nil, only check own namespace.'\n                properties:\n                  matchExpressions:\n                    description: matchExpressions is a list of label selector requirements.\n                      The requirements are ANDed.\n                    items:\n                      description: A label selector requirement is a selector that\n                        contains values, a key, and an operator that relates the key\n                        and values.\n                      properties:\n                        key:\n                          description: key is the label key that the selector applies\n                            to.\n                          type: string\n                        operator:\n                          description: operator represents a key's relationship to\n                            a set of values. Valid operators are In, NotIn, Exists\n                            and DoesNotExist.\n                          type: string\n                        values:\n                          description: values is an array of string values. If the\n                            operator is In or NotIn, the values array must be non-empty.\n                            If the operator is Exists or DoesNotExist, the values\n                            array must be empty. This array is replaced during a strategic\n                            merge patch.\n                          items:\n                            type: string\n                          type: array\n                      required:\n                      - key\n                      - operator\n                      type: object\n                    type: array\n                  matchLabels:\n                    additionalProperties:\n                      type: string\n                    description: matchLabels is a map of {key,value} pairs. A single\n                      {key,value} in the matchLabels map is equivalent to an element\n                      of matchExpressions, whose key field is \"key\", the operator\n                      is \"In\", and the values array contains only \"value\". The requirements\n                      are ANDed.\n                    type: object\n                type: object\n              probeSelector:\n                description: '*Experimental* Probes to be selected for target discovery.'\n                properties:\n                  matchExpressions:\n                    description: matchExpressions is a list of label selector requirements.\n                      The requirements are ANDed.\n                    items:\n                      description: A label selector requirement is a selector that\n                        contains values, a key, and an operator that relates the key\n                        and values.\n                      properties:\n                        key:\n                          description: key is the label key that the selector applies\n                            to.\n                          type: string\n                        operator:\n                          description: operator represents a key's relationship to\n                            a set of values. Valid operators are In, NotIn, Exists\n                            and DoesNotExist.\n                          type: string\n                        values:\n                          description: values is an array of string values. If the\n                            operator is In or NotIn, the values array must be non-empty.\n                            If the operator is Exists or DoesNotExist, the values\n                            array must be empty. This array is replaced during a strategic\n                            merge patch.\n                          items:\n                            type: string\n                          type: array\n                      required:\n                      - key\n                      - operator\n                      type: object\n                    type: array\n                  matchLabels:\n                    additionalProperties:\n                      type: string\n                    description: matchLabels is a map of {key,value} pairs. A single\n                      {key,value} in the matchLabels map is equivalent to an element\n                      of matchExpressions, whose key field is \"key\", the operator\n                      is \"In\", and the values array contains only \"value\". The requirements\n                      are ANDed.\n                    type: object\n                type: object\n              prometheusExternalLabelName:\n                description: Name of Prometheus external label used to denote Prometheus\n                  instance name. Defaults to the value of `prometheus`. External label\n                  will _not_ be added when value is set to empty string (`\"\"`).\n                type: string\n              prometheusRulesExcludedFromEnforce:\n                description: PrometheusRulesExcludedFromEnforce - list of prometheus\n                  rules to be excluded from enforcing of adding namespace labels.\n                  Works only if enforcedNamespaceLabel set to true. Make sure both\n                  ruleNamespace and ruleName are set for each pair\n                items:\n                  description: PrometheusRuleExcludeConfig enables users to configure\n                    excluded PrometheusRule names and their namespaces to be ignored\n                    while enforcing namespace label for alerts and metrics.\n                  properties:\n                    ruleName:\n                      description: RuleNamespace - name of excluded rule\n                      type: string\n                    ruleNamespace:\n                      description: RuleNamespace - namespace of excluded rule\n                      type: string\n                  required:\n                  - ruleName\n                  - ruleNamespace\n                  type: object\n                type: array\n              query:\n                description: QuerySpec defines the query command line flags when starting\n                  Prometheus.\n                properties:\n                  lookbackDelta:\n                    description: The delta difference allowed for retrieving metrics\n                      during expression evaluations.\n                    type: string\n                  maxConcurrency:\n                    description: Number of concurrent queries that can be run at once.\n                    format: int32\n                    type: integer\n                  maxSamples:\n                    description: Maximum number of samples a single query can load\n                      into memory. Note that queries will fail if they would load\n                      more samples than this into memory, so this also limits the\n                      number of samples a query can return.\n                    format: int32\n                    type: integer\n                  timeout:\n                    description: Maximum time a query may take before being aborted.\n                    type: string\n                type: object\n              queryLogFile:\n                description: QueryLogFile specifies the file to which PromQL queries\n                  are logged. Note that this location must be writable, and can be\n                  persisted using an attached volume. Alternatively, the location\n                  can be set to a stdout location such as `/dev/stdout` to log querie\n                  information to the default Prometheus log stream. This is only available\n                  in versions of Prometheus >= 2.16.0. For more details, see the Prometheus\n                  docs (https://prometheus.io/docs/guides/query-log/)\n                type: string\n              remoteRead:\n                description: If specified, the remote_read spec. This is an experimental\n                  feature, it may change in any upcoming release in a breaking way.\n                items:\n                  description: RemoteReadSpec defines the remote_read configuration\n                    for prometheus.\n                  properties:\n                    basicAuth:\n                      description: BasicAuth for the URL.\n                      properties:\n                        password:\n                          description: The secret in the service monitor namespace\n                            that contains the password for authentication.\n                          properties:\n                            key:\n                              description: The key of the secret to select from.  Must\n                                be a valid secret key.\n                              type: string\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                            optional:\n                              description: Specify whether the Secret or its key must\n                                be defined\n                              type: boolean\n                          required:\n                          - key\n                          type: object\n                        username:\n                          description: The secret in the service monitor namespace\n                            that contains the username for authentication.\n                          properties:\n                            key:\n                              description: The key of the secret to select from.  Must\n                                be a valid secret key.\n                              type: string\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                            optional:\n                              description: Specify whether the Secret or its key must\n                                be defined\n                              type: boolean\n                          required:\n                          - key\n                          type: object\n                      type: object\n                    bearerToken:\n                      description: Bearer token for remote read.\n                      type: string\n                    bearerTokenFile:\n                      description: File to read bearer token for remote read.\n                      type: string\n                    name:\n                      description: The name of the remote read queue, must be unique\n                        if specified. The name is used in metrics and logging in order\n                        to differentiate read configurations.  Only valid in Prometheus\n                        versions 2.15.0 and newer.\n                      type: string\n                    proxyUrl:\n                      description: Optional ProxyURL\n                      type: string\n                    readRecent:\n                      description: Whether reads should be made for queries for time\n                        ranges that the local storage should have complete data for.\n                      type: boolean\n                    remoteTimeout:\n                      description: Timeout for requests to the remote read endpoint.\n                      type: string\n                    requiredMatchers:\n                      additionalProperties:\n                        type: string\n                      description: An optional list of equality matchers which have\n                        to be present in a selector to query the remote read endpoint.\n                      type: object\n                    tlsConfig:\n                      description: TLS Config to use for remote read.\n                      properties:\n                        ca:\n                          description: Struct containing the CA cert to use for the\n                            targets.\n                          properties:\n                            configMap:\n                              description: ConfigMap containing data to use for the\n                                targets.\n                              properties:\n                                key:\n                                  description: The key to select.\n                                  type: string\n                                name:\n                                  description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                    TODO: Add other useful fields. apiVersion, kind,\n                                    uid?'\n                                  type: string\n                                optional:\n                                  description: Specify whether the ConfigMap or its\n                                    key must be defined\n                                  type: boolean\n                              required:\n                              - key\n                              type: object\n                            secret:\n                              description: Secret containing data to use for the targets.\n                              properties:\n                                key:\n                                  description: The key of the secret to select from.  Must\n                                    be a valid secret key.\n                                  type: string\n                                name:\n                                  description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                    TODO: Add other useful fields. apiVersion, kind,\n                                    uid?'\n                                  type: string\n                                optional:\n                                  description: Specify whether the Secret or its key\n                                    must be defined\n                                  type: boolean\n                              required:\n                              - key\n                              type: object\n                          type: object\n                        caFile:\n                          description: Path to the CA cert in the Prometheus container\n                            to use for the targets.\n                          type: string\n                        cert:\n                          description: Struct containing the client cert file for\n                            the targets.\n                          properties:\n                            configMap:\n                              description: ConfigMap containing data to use for the\n                                targets.\n                              properties:\n                                key:\n                                  description: The key to select.\n                                  type: string\n                                name:\n                                  description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                    TODO: Add other useful fields. apiVersion, kind,\n                                    uid?'\n                                  type: string\n                                optional:\n                                  description: Specify whether the ConfigMap or its\n                                    key must be defined\n                                  type: boolean\n                              required:\n                              - key\n                              type: object\n                            secret:\n                              description: Secret containing data to use for the targets.\n                              properties:\n                                key:\n                                  description: The key of the secret to select from.  Must\n                                    be a valid secret key.\n                                  type: string\n                                name:\n                                  description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                    TODO: Add other useful fields. apiVersion, kind,\n                                    uid?'\n                                  type: string\n                                optional:\n                                  description: Specify whether the Secret or its key\n                                    must be defined\n                                  type: boolean\n                              required:\n                              - key\n                              type: object\n                          type: object\n                        certFile:\n                          description: Path to the client cert file in the Prometheus\n                            container for the targets.\n                          type: string\n                        insecureSkipVerify:\n                          description: Disable target certificate validation.\n                          type: boolean\n                        keyFile:\n                          description: Path to the client key file in the Prometheus\n                            container for the targets.\n                          type: string\n                        keySecret:\n                          description: Secret containing the client key file for the\n                            targets.\n                          properties:\n                            key:\n                              description: The key of the secret to select from.  Must\n                                be a valid secret key.\n                              type: string\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                            optional:\n                              description: Specify whether the Secret or its key must\n                                be defined\n                              type: boolean\n                          required:\n                          - key\n                          type: object\n                        serverName:\n                          description: Used to verify the hostname for the targets.\n                          type: string\n                      type: object\n                    url:\n                      description: The URL of the endpoint to send samples to.\n                      type: string\n                  required:\n                  - url\n                  type: object\n                type: array\n              remoteWrite:\n                description: If specified, the remote_write spec. This is an experimental\n                  feature, it may change in any upcoming release in a breaking way.\n                items:\n                  description: RemoteWriteSpec defines the remote_write configuration\n                    for prometheus.\n                  properties:\n                    basicAuth:\n                      description: BasicAuth for the URL.\n                      properties:\n                        password:\n                          description: The secret in the service monitor namespace\n                            that contains the password for authentication.\n                          properties:\n                            key:\n                              description: The key of the secret to select from.  Must\n                                be a valid secret key.\n                              type: string\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                            optional:\n                              description: Specify whether the Secret or its key must\n                                be defined\n                              type: boolean\n                          required:\n                          - key\n                          type: object\n                        username:\n                          description: The secret in the service monitor namespace\n                            that contains the username for authentication.\n                          properties:\n                            key:\n                              description: The key of the secret to select from.  Must\n                                be a valid secret key.\n                              type: string\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                            optional:\n                              description: Specify whether the Secret or its key must\n                                be defined\n                              type: boolean\n                          required:\n                          - key\n                          type: object\n                      type: object\n                    bearerToken:\n                      description: Bearer token for remote write.\n                      type: string\n                    bearerTokenFile:\n                      description: File to read bearer token for remote write.\n                      type: string\n                    headers:\n                      additionalProperties:\n                        type: string\n                      description: Custom HTTP headers to be sent along with each\n                        remote write request. Be aware that headers that are set by\n                        Prometheus itself can't be overwritten. Only valid in Prometheus\n                        versions 2.25.0 and newer.\n                      type: object\n                    metadataConfig:\n                      description: MetadataConfig configures the sending of series\n                        metadata to remote storage.\n                      properties:\n                        send:\n                          description: Whether metric metadata is sent to remote storage\n                            or not.\n                          type: boolean\n                        sendInterval:\n                          description: How frequently metric metadata is sent to remote\n                            storage.\n                          type: string\n                      type: object\n                    name:\n                      description: The name of the remote write queue, must be unique\n                        if specified. The name is used in metrics and logging in order\n                        to differentiate queues. Only valid in Prometheus versions\n                        2.15.0 and newer.\n                      type: string\n                    proxyUrl:\n                      description: Optional ProxyURL\n                      type: string\n                    queueConfig:\n                      description: QueueConfig allows tuning of the remote write queue\n                        parameters.\n                      properties:\n                        batchSendDeadline:\n                          description: BatchSendDeadline is the maximum time a sample\n                            will wait in buffer.\n                          type: string\n                        capacity:\n                          description: Capacity is the number of samples to buffer\n                            per shard before we start dropping them.\n                          type: integer\n                        maxBackoff:\n                          description: MaxBackoff is the maximum retry delay.\n                          type: string\n                        maxRetries:\n                          description: MaxRetries is the maximum number of times to\n                            retry a batch on recoverable errors.\n                          type: integer\n                        maxSamplesPerSend:\n                          description: MaxSamplesPerSend is the maximum number of\n                            samples per send.\n                          type: integer\n                        maxShards:\n                          description: MaxShards is the maximum number of shards,\n                            i.e. amount of concurrency.\n                          type: integer\n                        minBackoff:\n                          description: MinBackoff is the initial retry delay. Gets\n                            doubled for every retry.\n                          type: string\n                        minShards:\n                          description: MinShards is the minimum number of shards,\n                            i.e. amount of concurrency.\n                          type: integer\n                      type: object\n                    remoteTimeout:\n                      description: Timeout for requests to the remote write endpoint.\n                      type: string\n                    tlsConfig:\n                      description: TLS Config to use for remote write.\n                      properties:\n                        ca:\n                          description: Struct containing the CA cert to use for the\n                            targets.\n                          properties:\n                            configMap:\n                              description: ConfigMap containing data to use for the\n                                targets.\n                              properties:\n                                key:\n                                  description: The key to select.\n                                  type: string\n                                name:\n                                  description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                    TODO: Add other useful fields. apiVersion, kind,\n                                    uid?'\n                                  type: string\n                                optional:\n                                  description: Specify whether the ConfigMap or its\n                                    key must be defined\n                                  type: boolean\n                              required:\n                              - key\n                              type: object\n                            secret:\n                              description: Secret containing data to use for the targets.\n                              properties:\n                                key:\n                                  description: The key of the secret to select from.  Must\n                                    be a valid secret key.\n                                  type: string\n                                name:\n                                  description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                    TODO: Add other useful fields. apiVersion, kind,\n                                    uid?'\n                                  type: string\n                                optional:\n                                  description: Specify whether the Secret or its key\n                                    must be defined\n                                  type: boolean\n                              required:\n                              - key\n                              type: object\n                          type: object\n                        caFile:\n                          description: Path to the CA cert in the Prometheus container\n                            to use for the targets.\n                          type: string\n                        cert:\n                          description: Struct containing the client cert file for\n                            the targets.\n                          properties:\n                            configMap:\n                              description: ConfigMap containing data to use for the\n                                targets.\n                              properties:\n                                key:\n                                  description: The key to select.\n                                  type: string\n                                name:\n                                  description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                    TODO: Add other useful fields. apiVersion, kind,\n                                    uid?'\n                                  type: string\n                                optional:\n                                  description: Specify whether the ConfigMap or its\n                                    key must be defined\n                                  type: boolean\n                              required:\n                              - key\n                              type: object\n                            secret:\n                              description: Secret containing data to use for the targets.\n                              properties:\n                                key:\n                                  description: The key of the secret to select from.  Must\n                                    be a valid secret key.\n                                  type: string\n                                name:\n                                  description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                    TODO: Add other useful fields. apiVersion, kind,\n                                    uid?'\n                                  type: string\n                                optional:\n                                  description: Specify whether the Secret or its key\n                                    must be defined\n                                  type: boolean\n                              required:\n                              - key\n                              type: object\n                          type: object\n                        certFile:\n                          description: Path to the client cert file in the Prometheus\n                            container for the targets.\n                          type: string\n                        insecureSkipVerify:\n                          description: Disable target certificate validation.\n                          type: boolean\n                        keyFile:\n                          description: Path to the client key file in the Prometheus\n                            container for the targets.\n                          type: string\n                        keySecret:\n                          description: Secret containing the client key file for the\n                            targets.\n                          properties:\n                            key:\n                              description: The key of the secret to select from.  Must\n                                be a valid secret key.\n                              type: string\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                            optional:\n                              description: Specify whether the Secret or its key must\n                                be defined\n                              type: boolean\n                          required:\n                          - key\n                          type: object\n                        serverName:\n                          description: Used to verify the hostname for the targets.\n                          type: string\n                      type: object\n                    url:\n                      description: The URL of the endpoint to send samples to.\n                      type: string\n                    writeRelabelConfigs:\n                      description: The list of remote write relabel configurations.\n                      items:\n                        description: 'RelabelConfig allows dynamic rewriting of the\n                          label set, being applied to samples before ingestion. It\n                          defines `<metric_relabel_configs>`-section of Prometheus\n                          configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs'\n                        properties:\n                          action:\n                            description: Action to perform based on regex matching.\n                              Default is 'replace'\n                            type: string\n                          modulus:\n                            description: Modulus to take of the hash of the source\n                              label values.\n                            format: int64\n                            type: integer\n                          regex:\n                            description: Regular expression against which the extracted\n                              value is matched. Default is '(.*)'\n                            type: string\n                          replacement:\n                            description: Replacement value against which a regex replace\n                              is performed if the regular expression matches. Regex\n                              capture groups are available. Default is '$1'\n                            type: string\n                          separator:\n                            description: Separator placed between concatenated source\n                              label values. default is ';'.\n                            type: string\n                          sourceLabels:\n                            description: The source labels select values from existing\n                              labels. Their content is concatenated using the configured\n                              separator and matched against the configured regular\n                              expression for the replace, keep, and drop actions.\n                            items:\n                              type: string\n                            type: array\n                          targetLabel:\n                            description: Label to which the resulting value is written\n                              in a replace action. It is mandatory for replace actions.\n                              Regex capture groups are available.\n                            type: string\n                        type: object\n                      type: array\n                  required:\n                  - url\n                  type: object\n                type: array\n              replicaExternalLabelName:\n                description: Name of Prometheus external label used to denote replica\n                  name. Defaults to the value of `prometheus_replica`. External label\n                  will _not_ be added when value is set to empty string (`\"\"`).\n                type: string\n              replicas:\n                description: Number of replicas of each shard to deploy for a Prometheus\n                  deployment. Number of replicas multiplied by shards is the total\n                  number of Pods created.\n                format: int32\n                type: integer\n              resources:\n                description: Define resources requests and limits for single Pods.\n                properties:\n                  limits:\n                    additionalProperties:\n                      anyOf:\n                      - type: integer\n                      - type: string\n                      pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                      x-kubernetes-int-or-string: true\n                    description: 'Limits describes the maximum amount of compute resources\n                      allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                    type: object\n                  requests:\n                    additionalProperties:\n                      anyOf:\n                      - type: integer\n                      - type: string\n                      pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                      x-kubernetes-int-or-string: true\n                    description: 'Requests describes the minimum amount of compute\n                      resources required. If Requests is omitted for a container,\n                      it defaults to Limits if that is explicitly specified, otherwise\n                      to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                    type: object\n                type: object\n              retention:\n                description: Time duration Prometheus shall retain data for. Default\n                  is '24h', and must match the regular expression `[0-9]+(ms|s|m|h|d|w|y)`\n                  (milliseconds seconds minutes hours days weeks years).\n                type: string\n              retentionSize:\n                description: 'Maximum amount of disk space used by blocks. Supported\n                  units: B, KB, MB, GB, TB, PB, EB. Ex: `512MB`.'\n                type: string\n              routePrefix:\n                description: The route prefix Prometheus registers HTTP handlers for.\n                  This is useful, if using ExternalURL and a proxy is rewriting HTTP\n                  routes of a request, and the actual ExternalURL is still true, but\n                  the server serves requests under a different route prefix. For example\n                  for use with `kubectl proxy`.\n                type: string\n              ruleNamespaceSelector:\n                description: Namespaces to be selected for PrometheusRules discovery.\n                  If unspecified, only the same namespace as the Prometheus object\n                  is in is used.\n                properties:\n                  matchExpressions:\n                    description: matchExpressions is a list of label selector requirements.\n                      The requirements are ANDed.\n                    items:\n                      description: A label selector requirement is a selector that\n                        contains values, a key, and an operator that relates the key\n                        and values.\n                      properties:\n                        key:\n                          description: key is the label key that the selector applies\n                            to.\n                          type: string\n                        operator:\n                          description: operator represents a key's relationship to\n                            a set of values. Valid operators are In, NotIn, Exists\n                            and DoesNotExist.\n                          type: string\n                        values:\n                          description: values is an array of string values. If the\n                            operator is In or NotIn, the values array must be non-empty.\n                            If the operator is Exists or DoesNotExist, the values\n                            array must be empty. This array is replaced during a strategic\n                            merge patch.\n                          items:\n                            type: string\n                          type: array\n                      required:\n                      - key\n                      - operator\n                      type: object\n                    type: array\n                  matchLabels:\n                    additionalProperties:\n                      type: string\n                    description: matchLabels is a map of {key,value} pairs. A single\n                      {key,value} in the matchLabels map is equivalent to an element\n                      of matchExpressions, whose key field is \"key\", the operator\n                      is \"In\", and the values array contains only \"value\". The requirements\n                      are ANDed.\n                    type: object\n                type: object\n              ruleSelector:\n                description: A selector to select which PrometheusRules to mount for\n                  loading alerting/recording rules from. Until (excluding) Prometheus\n                  Operator v0.24.0 Prometheus Operator will migrate any legacy rule\n                  ConfigMaps to PrometheusRule custom resources selected by RuleSelector.\n                  Make sure it does not match any config maps that you do not want\n                  to be migrated.\n                properties:\n                  matchExpressions:\n                    description: matchExpressions is a list of label selector requirements.\n                      The requirements are ANDed.\n                    items:\n                      description: A label selector requirement is a selector that\n                        contains values, a key, and an operator that relates the key\n                        and values.\n                      properties:\n                        key:\n                          description: key is the label key that the selector applies\n                            to.\n                          type: string\n                        operator:\n                          description: operator represents a key's relationship to\n                            a set of values. Valid operators are In, NotIn, Exists\n                            and DoesNotExist.\n                          type: string\n                        values:\n                          description: values is an array of string values. If the\n                            operator is In or NotIn, the values array must be non-empty.\n                            If the operator is Exists or DoesNotExist, the values\n                            array must be empty. This array is replaced during a strategic\n                            merge patch.\n                          items:\n                            type: string\n                          type: array\n                      required:\n                      - key\n                      - operator\n                      type: object\n                    type: array\n                  matchLabels:\n                    additionalProperties:\n                      type: string\n                    description: matchLabels is a map of {key,value} pairs. A single\n                      {key,value} in the matchLabels map is equivalent to an element\n                      of matchExpressions, whose key field is \"key\", the operator\n                      is \"In\", and the values array contains only \"value\". The requirements\n                      are ANDed.\n                    type: object\n                type: object\n              rules:\n                description: /--rules.*/ command-line arguments.\n                properties:\n                  alert:\n                    description: /--rules.alert.*/ command-line arguments\n                    properties:\n                      forGracePeriod:\n                        description: Minimum duration between alert and restored 'for'\n                          state. This is maintained only for alerts with configured\n                          'for' time greater than grace period.\n                        type: string\n                      forOutageTolerance:\n                        description: Max time to tolerate prometheus outage for restoring\n                          'for' state of alert.\n                        type: string\n                      resendDelay:\n                        description: Minimum amount of time to wait before resending\n                          an alert to Alertmanager.\n                        type: string\n                    type: object\n                type: object\n              scrapeInterval:\n                description: 'Interval between consecutive scrapes. Default: `1m`'\n                type: string\n              scrapeTimeout:\n                description: Number of seconds to wait for target to respond before\n                  erroring.\n                type: string\n              secrets:\n                description: Secrets is a list of Secrets in the same namespace as\n                  the Prometheus object, which shall be mounted into the Prometheus\n                  Pods. The Secrets are mounted into /etc/prometheus/secrets/<secret-name>.\n                items:\n                  type: string\n                type: array\n              securityContext:\n                description: SecurityContext holds pod-level security attributes and\n                  common container settings. This defaults to the default PodSecurityContext.\n                properties:\n                  fsGroup:\n                    description: \"A special supplemental group that applies to all\n                      containers in a pod. Some volume types allow the Kubelet to\n                      change the ownership of that volume to be owned by the pod:\n                      \\n 1. The owning GID will be the FSGroup 2. The setgid bit is\n                      set (new files created in the volume will be owned by FSGroup)\n                      3. The permission bits are OR'd with rw-rw---- \\n If unset,\n                      the Kubelet will not modify the ownership and permissions of\n                      any volume.\"\n                    format: int64\n                    type: integer\n                  fsGroupChangePolicy:\n                    description: 'fsGroupChangePolicy defines behavior of changing\n                      ownership and permission of the volume before being exposed\n                      inside Pod. This field will only apply to volume types which\n                      support fsGroup based ownership(and permissions). It will have\n                      no effect on ephemeral volume types such as: secret, configmaps\n                      and emptydir. Valid values are \"OnRootMismatch\" and \"Always\".\n                      If not specified defaults to \"Always\".'\n                    type: string\n                  runAsGroup:\n                    description: The GID to run the entrypoint of the container process.\n                      Uses runtime default if unset. May also be set in SecurityContext.  If\n                      set in both SecurityContext and PodSecurityContext, the value\n                      specified in SecurityContext takes precedence for that container.\n                    format: int64\n                    type: integer\n                  runAsNonRoot:\n                    description: Indicates that the container must run as a non-root\n                      user. If true, the Kubelet will validate the image at runtime\n                      to ensure that it does not run as UID 0 (root) and fail to start\n                      the container if it does. If unset or false, no such validation\n                      will be performed. May also be set in SecurityContext.  If set\n                      in both SecurityContext and PodSecurityContext, the value specified\n                      in SecurityContext takes precedence.\n                    type: boolean\n                  runAsUser:\n                    description: The UID to run the entrypoint of the container process.\n                      Defaults to user specified in image metadata if unspecified.\n                      May also be set in SecurityContext.  If set in both SecurityContext\n                      and PodSecurityContext, the value specified in SecurityContext\n                      takes precedence for that container.\n                    format: int64\n                    type: integer\n                  seLinuxOptions:\n                    description: The SELinux context to be applied to all containers.\n                      If unspecified, the container runtime will allocate a random\n                      SELinux context for each container.  May also be set in SecurityContext.  If\n                      set in both SecurityContext and PodSecurityContext, the value\n                      specified in SecurityContext takes precedence for that container.\n                    properties:\n                      level:\n                        description: Level is SELinux level label that applies to\n                          the container.\n                        type: string\n                      role:\n                        description: Role is a SELinux role label that applies to\n                          the container.\n                        type: string\n                      type:\n                        description: Type is a SELinux type label that applies to\n                          the container.\n                        type: string\n                      user:\n                        description: User is a SELinux user label that applies to\n                          the container.\n                        type: string\n                    type: object\n                  supplementalGroups:\n                    description: A list of groups applied to the first process run\n                      in each container, in addition to the container's primary GID.  If\n                      unspecified, no groups will be added to any container.\n                    items:\n                      format: int64\n                      type: integer\n                    type: array\n                  sysctls:\n                    description: Sysctls hold a list of namespaced sysctls used for\n                      the pod. Pods with unsupported sysctls (by the container runtime)\n                      might fail to launch.\n                    items:\n                      description: Sysctl defines a kernel parameter to be set\n                      properties:\n                        name:\n                          description: Name of a property to set\n                          type: string\n                        value:\n                          description: Value of a property to set\n                          type: string\n                      required:\n                      - name\n                      - value\n                      type: object\n                    type: array\n                  windowsOptions:\n                    description: The Windows specific settings applied to all containers.\n                      If unspecified, the options within a container's SecurityContext\n                      will be used. If set in both SecurityContext and PodSecurityContext,\n                      the value specified in SecurityContext takes precedence.\n                    properties:\n                      gmsaCredentialSpec:\n                        description: GMSACredentialSpec is where the GMSA admission\n                          webhook (https://github.com/kubernetes-sigs/windows-gmsa)\n                          inlines the contents of the GMSA credential spec named by\n                          the GMSACredentialSpecName field.\n                        type: string\n                      gmsaCredentialSpecName:\n                        description: GMSACredentialSpecName is the name of the GMSA\n                          credential spec to use.\n                        type: string\n                      runAsUserName:\n                        description: The UserName in Windows to run the entrypoint\n                          of the container process. Defaults to the user specified\n                          in image metadata if unspecified. May also be set in PodSecurityContext.\n                          If set in both SecurityContext and PodSecurityContext, the\n                          value specified in SecurityContext takes precedence.\n                        type: string\n                    type: object\n                type: object\n              serviceAccountName:\n                description: ServiceAccountName is the name of the ServiceAccount\n                  to use to run the Prometheus Pods.\n                type: string\n              serviceMonitorNamespaceSelector:\n                description: Namespace's labels to match for ServiceMonitor discovery.\n                  If nil, only check own namespace.\n                properties:\n                  matchExpressions:\n                    description: matchExpressions is a list of label selector requirements.\n                      The requirements are ANDed.\n                    items:\n                      description: A label selector requirement is a selector that\n                        contains values, a key, and an operator that relates the key\n                        and values.\n                      properties:\n                        key:\n                          description: key is the label key that the selector applies\n                            to.\n                          type: string\n                        operator:\n                          description: operator represents a key's relationship to\n                            a set of values. Valid operators are In, NotIn, Exists\n                            and DoesNotExist.\n                          type: string\n                        values:\n                          description: values is an array of string values. If the\n                            operator is In or NotIn, the values array must be non-empty.\n                            If the operator is Exists or DoesNotExist, the values\n                            array must be empty. This array is replaced during a strategic\n                            merge patch.\n                          items:\n                            type: string\n                          type: array\n                      required:\n                      - key\n                      - operator\n                      type: object\n                    type: array\n                  matchLabels:\n                    additionalProperties:\n                      type: string\n                    description: matchLabels is a map of {key,value} pairs. A single\n                      {key,value} in the matchLabels map is equivalent to an element\n                      of matchExpressions, whose key field is \"key\", the operator\n                      is \"In\", and the values array contains only \"value\". The requirements\n                      are ANDed.\n                    type: object\n                type: object\n              serviceMonitorSelector:\n                description: ServiceMonitors to be selected for target discovery.\n                  *Deprecated:* if neither this nor podMonitorSelector are specified,\n                  configuration is unmanaged.\n                properties:\n                  matchExpressions:\n                    description: matchExpressions is a list of label selector requirements.\n                      The requirements are ANDed.\n                    items:\n                      description: A label selector requirement is a selector that\n                        contains values, a key, and an operator that relates the key\n                        and values.\n                      properties:\n                        key:\n                          description: key is the label key that the selector applies\n                            to.\n                          type: string\n                        operator:\n                          description: operator represents a key's relationship to\n                            a set of values. Valid operators are In, NotIn, Exists\n                            and DoesNotExist.\n                          type: string\n                        values:\n                          description: values is an array of string values. If the\n                            operator is In or NotIn, the values array must be non-empty.\n                            If the operator is Exists or DoesNotExist, the values\n                            array must be empty. This array is replaced during a strategic\n                            merge patch.\n                          items:\n                            type: string\n                          type: array\n                      required:\n                      - key\n                      - operator\n                      type: object\n                    type: array\n                  matchLabels:\n                    additionalProperties:\n                      type: string\n                    description: matchLabels is a map of {key,value} pairs. A single\n                      {key,value} in the matchLabels map is equivalent to an element\n                      of matchExpressions, whose key field is \"key\", the operator\n                      is \"In\", and the values array contains only \"value\". The requirements\n                      are ANDed.\n                    type: object\n                type: object\n              sha:\n                description: 'SHA of Prometheus container image to be deployed. Defaults\n                  to the value of `version`. Similar to a tag, but the SHA explicitly\n                  deploys an immutable container image. Version and Tag are ignored\n                  if SHA is set. Deprecated: use ''image'' instead.  The image digest\n                  can be specified as part of the image URL.'\n                type: string\n              shards:\n                description: 'EXPERIMENTAL: Number of shards to distribute targets\n                  onto. Number of replicas multiplied by shards is the total number\n                  of Pods created. Note that scaling down shards will not reshard\n                  data onto remaining instances, it must be manually moved. Increasing\n                  shards will not reshard data either but it will continue to be available\n                  from the same instances. To query globally use Thanos sidecar and\n                  Thanos querier or remote write data to a central location. Sharding\n                  is done on the content of the `__address__` target meta-label.'\n                format: int32\n                type: integer\n              storage:\n                description: Storage spec to specify how storage shall be used.\n                properties:\n                  disableMountSubPath:\n                    description: 'Deprecated: subPath usage will be disabled by default\n                      in a future release, this option will become unnecessary. DisableMountSubPath\n                      allows to remove any subPath usage in volume mounts.'\n                    type: boolean\n                  emptyDir:\n                    description: 'EmptyDirVolumeSource to be used by the Prometheus\n                      StatefulSets. If specified, used in place of any volumeClaimTemplate.\n                      More info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir'\n                    properties:\n                      medium:\n                        description: 'What type of storage medium should back this\n                          directory. The default is \"\" which means to use the node''s\n                          default medium. Must be an empty string (default) or Memory.\n                          More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir'\n                        type: string\n                      sizeLimit:\n                        anyOf:\n                        - type: integer\n                        - type: string\n                        description: 'Total amount of local storage required for this\n                          EmptyDir volume. The size limit is also applicable for memory\n                          medium. The maximum usage on memory medium EmptyDir would\n                          be the minimum value between the SizeLimit specified here\n                          and the sum of memory limits of all containers in a pod.\n                          The default is nil which means that the limit is undefined.\n                          More info: http://kubernetes.io/docs/user-guide/volumes#emptydir'\n                        pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                        x-kubernetes-int-or-string: true\n                    type: object\n                  volumeClaimTemplate:\n                    description: A PVC spec to be used by the Prometheus StatefulSets.\n                    properties:\n                      apiVersion:\n                        description: 'APIVersion defines the versioned schema of this\n                          representation of an object. Servers should convert recognized\n                          schemas to the latest internal value, and may reject unrecognized\n                          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\n                          resource this object represents. Servers may infer this\n                          from the endpoint the client submits requests to. Cannot\n                          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                        description: EmbeddedMetadata contains metadata relevant to\n                          an EmbeddedResource.\n                        properties:\n                          annotations:\n                            additionalProperties:\n                              type: string\n                            description: 'Annotations is an unstructured key value\n                              map stored with a resource that may be set by external\n                              tools to store and retrieve arbitrary metadata. They\n                              are not queryable and should be preserved when modifying\n                              objects. More info: http://kubernetes.io/docs/user-guide/annotations'\n                            type: object\n                          labels:\n                            additionalProperties:\n                              type: string\n                            description: 'Map of string keys and values that can be\n                              used to organize and categorize (scope and select) objects.\n                              May match selectors of replication controllers and services.\n                              More info: http://kubernetes.io/docs/user-guide/labels'\n                            type: object\n                          name:\n                            description: 'Name must be unique within a namespace.\n                              Is required when creating resources, although some resources\n                              may allow a client to request the generation of an appropriate\n                              name automatically. Name is primarily intended for creation\n                              idempotence and configuration definition. Cannot be\n                              updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names'\n                            type: string\n                        type: object\n                      spec:\n                        description: 'Spec defines the desired characteristics of\n                          a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'\n                        properties:\n                          accessModes:\n                            description: 'AccessModes contains the desired access\n                              modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'\n                            items:\n                              type: string\n                            type: array\n                          dataSource:\n                            description: 'This field can be used to specify either:\n                              * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot\n                              - Beta) * An existing PVC (PersistentVolumeClaim) *\n                              An existing custom resource/object that implements data\n                              population (Alpha) In order to use VolumeSnapshot object\n                              types, the appropriate feature gate must be enabled\n                              (VolumeSnapshotDataSource or AnyVolumeDataSource) If\n                              the provisioner or an external controller can support\n                              the specified data source, it will create a new volume\n                              based on the contents of the specified data source.\n                              If the specified data source is not supported, the volume\n                              will not be created and the failure will be reported\n                              as an event. In the future, we plan to support more\n                              data source types and the behavior of the provisioner\n                              may change.'\n                            properties:\n                              apiGroup:\n                                description: APIGroup is the group for the resource\n                                  being referenced. If APIGroup is not specified,\n                                  the specified Kind must be in the core API group.\n                                  For any other third-party types, APIGroup is required.\n                                type: string\n                              kind:\n                                description: Kind is the type of resource being referenced\n                                type: string\n                              name:\n                                description: Name is the name of resource being referenced\n                                type: string\n                            required:\n                            - kind\n                            - name\n                            type: object\n                          resources:\n                            description: 'Resources represents the minimum resources\n                              the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources'\n                            properties:\n                              limits:\n                                additionalProperties:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                  x-kubernetes-int-or-string: true\n                                description: 'Limits describes the maximum amount\n                                  of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                                type: object\n                              requests:\n                                additionalProperties:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                  x-kubernetes-int-or-string: true\n                                description: 'Requests describes the minimum amount\n                                  of compute resources required. If Requests is omitted\n                                  for a container, it defaults to Limits if that is\n                                  explicitly specified, otherwise to an implementation-defined\n                                  value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                                type: object\n                            type: object\n                          selector:\n                            description: A label query over volumes to consider for\n                              binding.\n                            properties:\n                              matchExpressions:\n                                description: matchExpressions is a list of label selector\n                                  requirements. The requirements are ANDed.\n                                items:\n                                  description: A label selector requirement is a selector\n                                    that contains values, a key, and an operator that\n                                    relates the key and values.\n                                  properties:\n                                    key:\n                                      description: key is the label key that the selector\n                                        applies to.\n                                      type: string\n                                    operator:\n                                      description: operator represents a key's relationship\n                                        to a set of values. Valid operators are In,\n                                        NotIn, Exists and DoesNotExist.\n                                      type: string\n                                    values:\n                                      description: values is an array of string values.\n                                        If the operator is In or NotIn, the values\n                                        array must be non-empty. If the operator is\n                                        Exists or DoesNotExist, the values array must\n                                        be empty. This array is replaced during a\n                                        strategic merge patch.\n                                      items:\n                                        type: string\n                                      type: array\n                                  required:\n                                  - key\n                                  - operator\n                                  type: object\n                                type: array\n                              matchLabels:\n                                additionalProperties:\n                                  type: string\n                                description: matchLabels is a map of {key,value} pairs.\n                                  A single {key,value} in the matchLabels map is equivalent\n                                  to an element of matchExpressions, whose key field\n                                  is \"key\", the operator is \"In\", and the values array\n                                  contains only \"value\". The requirements are ANDed.\n                                type: object\n                            type: object\n                          storageClassName:\n                            description: 'Name of the StorageClass required by the\n                              claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1'\n                            type: string\n                          volumeMode:\n                            description: volumeMode defines what type of volume is\n                              required by the claim. Value of Filesystem is implied\n                              when not included in claim spec.\n                            type: string\n                          volumeName:\n                            description: VolumeName is the binding reference to the\n                              PersistentVolume backing this claim.\n                            type: string\n                        type: object\n                      status:\n                        description: 'Status represents the current information/status\n                          of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'\n                        properties:\n                          accessModes:\n                            description: 'AccessModes contains the actual access modes\n                              the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'\n                            items:\n                              type: string\n                            type: array\n                          capacity:\n                            additionalProperties:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                              x-kubernetes-int-or-string: true\n                            description: Represents the actual resources of the underlying\n                              volume.\n                            type: object\n                          conditions:\n                            description: Current Condition of persistent volume claim.\n                              If underlying persistent volume is being resized then\n                              the Condition will be set to 'ResizeStarted'.\n                            items:\n                              description: PersistentVolumeClaimCondition contails\n                                details about state of pvc\n                              properties:\n                                lastProbeTime:\n                                  description: Last time we probed the condition.\n                                  format: date-time\n                                  type: string\n                                lastTransitionTime:\n                                  description: Last time the condition transitioned\n                                    from one status to another.\n                                  format: date-time\n                                  type: string\n                                message:\n                                  description: Human-readable message indicating details\n                                    about last transition.\n                                  type: string\n                                reason:\n                                  description: Unique, this should be a short, machine\n                                    understandable string that gives the reason for\n                                    condition's last transition. If it reports \"ResizeStarted\"\n                                    that means the underlying persistent volume is\n                                    being resized.\n                                  type: string\n                                status:\n                                  type: string\n                                type:\n                                  description: PersistentVolumeClaimConditionType\n                                    is a valid value of PersistentVolumeClaimCondition.Type\n                                  type: string\n                              required:\n                              - status\n                              - type\n                              type: object\n                            type: array\n                          phase:\n                            description: Phase represents the current phase of PersistentVolumeClaim.\n                            type: string\n                        type: object\n                    type: object\n                type: object\n              tag:\n                description: 'Tag of Prometheus container image to be deployed. Defaults\n                  to the value of `version`. Version is ignored if Tag is set. Deprecated:\n                  use ''image'' instead.  The image tag can be specified as part of\n                  the image URL.'\n                type: string\n              thanos:\n                description: \"Thanos configuration allows configuring various aspects\n                  of a Prometheus server in a Thanos environment. \\n This section\n                  is experimental, it may change significantly without deprecation\n                  notice in any release. \\n This is experimental and may change significantly\n                  without backward compatibility in any release.\"\n                properties:\n                  baseImage:\n                    description: 'Thanos base image if other than default. Deprecated:\n                      use ''image'' instead'\n                    type: string\n                  grpcServerTlsConfig:\n                    description: 'GRPCServerTLSConfig configures the gRPC server from\n                      which Thanos Querier reads recorded rule data. Note: Currently\n                      only the CAFile, CertFile, and KeyFile fields are supported.\n                      Maps to the ''--grpc-server-tls-*'' CLI args.'\n                    properties:\n                      ca:\n                        description: Struct containing the CA cert to use for the\n                          targets.\n                        properties:\n                          configMap:\n                            description: ConfigMap containing data to use for the\n                              targets.\n                            properties:\n                              key:\n                                description: The key to select.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the ConfigMap or its\n                                  key must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                          secret:\n                            description: Secret containing data to use for the targets.\n                            properties:\n                              key:\n                                description: The key of the secret to select from.  Must\n                                  be a valid secret key.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret or its key\n                                  must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                        type: object\n                      caFile:\n                        description: Path to the CA cert in the Prometheus container\n                          to use for the targets.\n                        type: string\n                      cert:\n                        description: Struct containing the client cert file for the\n                          targets.\n                        properties:\n                          configMap:\n                            description: ConfigMap containing data to use for the\n                              targets.\n                            properties:\n                              key:\n                                description: The key to select.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the ConfigMap or its\n                                  key must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                          secret:\n                            description: Secret containing data to use for the targets.\n                            properties:\n                              key:\n                                description: The key of the secret to select from.  Must\n                                  be a valid secret key.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret or its key\n                                  must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                        type: object\n                      certFile:\n                        description: Path to the client cert file in the Prometheus\n                          container for the targets.\n                        type: string\n                      insecureSkipVerify:\n                        description: Disable target certificate validation.\n                        type: boolean\n                      keyFile:\n                        description: Path to the client key file in the Prometheus\n                          container for the targets.\n                        type: string\n                      keySecret:\n                        description: Secret containing the client key file for the\n                          targets.\n                        properties:\n                          key:\n                            description: The key of the secret to select from.  Must\n                              be a valid secret key.\n                            type: string\n                          name:\n                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                              TODO: Add other useful fields. apiVersion, kind, uid?'\n                            type: string\n                          optional:\n                            description: Specify whether the Secret or its key must\n                              be defined\n                            type: boolean\n                        required:\n                        - key\n                        type: object\n                      serverName:\n                        description: Used to verify the hostname for the targets.\n                        type: string\n                    type: object\n                  image:\n                    description: Image if specified has precedence over baseImage,\n                      tag and sha combinations. Specifying the version is still necessary\n                      to ensure the Prometheus Operator knows what version of Thanos\n                      is being configured.\n                    type: string\n                  listenLocal:\n                    description: ListenLocal makes the Thanos sidecar listen on loopback,\n                      so that it does not bind against the Pod IP.\n                    type: boolean\n                  logFormat:\n                    description: LogFormat for Thanos sidecar to be configured with.\n                    type: string\n                  logLevel:\n                    description: LogLevel for Thanos sidecar to be configured with.\n                    type: string\n                  minTime:\n                    description: MinTime for Thanos sidecar to be configured with.\n                      Option can be a constant time in RFC3339 format or time duration\n                      relative to current time, such as -1d or 2h45m. Valid duration\n                      units are ms, s, m, h, d, w, y.\n                    type: string\n                  objectStorageConfig:\n                    description: ObjectStorageConfig configures object storage in\n                      Thanos. Alternative to ObjectStorageConfigFile, and lower order\n                      priority.\n                    properties:\n                      key:\n                        description: The key of the secret to select from.  Must be\n                          a valid secret key.\n                        type: string\n                      name:\n                        description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                          TODO: Add other useful fields. apiVersion, kind, uid?'\n                        type: string\n                      optional:\n                        description: Specify whether the Secret or its key must be\n                          defined\n                        type: boolean\n                    required:\n                    - key\n                    type: object\n                  objectStorageConfigFile:\n                    description: ObjectStorageConfigFile specifies the path of the\n                      object storage configuration file. When used alongside with\n                      ObjectStorageConfig, ObjectStorageConfigFile takes precedence.\n                    type: string\n                  readyTimeout:\n                    description: ReadyTimeout is the maximum time Thanos sidecar will\n                      wait for Prometheus to start. Eg 10m\n                    type: string\n                  resources:\n                    description: Resources defines the resource requirements for the\n                      Thanos sidecar. If not provided, no requests/limits will be\n                      set\n                    properties:\n                      limits:\n                        additionalProperties:\n                          anyOf:\n                          - type: integer\n                          - type: string\n                          pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                          x-kubernetes-int-or-string: true\n                        description: 'Limits describes the maximum amount of compute\n                          resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                        type: object\n                      requests:\n                        additionalProperties:\n                          anyOf:\n                          - type: integer\n                          - type: string\n                          pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                          x-kubernetes-int-or-string: true\n                        description: 'Requests describes the minimum amount of compute\n                          resources required. If Requests is omitted for a container,\n                          it defaults to Limits if that is explicitly specified, otherwise\n                          to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                        type: object\n                    type: object\n                  sha:\n                    description: 'SHA of Thanos container image to be deployed. Defaults\n                      to the value of `version`. Similar to a tag, but the SHA explicitly\n                      deploys an immutable container image. Version and Tag are ignored\n                      if SHA is set. Deprecated: use ''image'' instead.  The image\n                      digest can be specified as part of the image URL.'\n                    type: string\n                  tag:\n                    description: 'Tag of Thanos sidecar container image to be deployed.\n                      Defaults to the value of `version`. Version is ignored if Tag\n                      is set. Deprecated: use ''image'' instead.  The image tag can\n                      be specified as part of the image URL.'\n                    type: string\n                  tracingConfig:\n                    description: TracingConfig configures tracing in Thanos. This\n                      is an experimental feature, it may change in any upcoming release\n                      in a breaking way.\n                    properties:\n                      key:\n                        description: The key of the secret to select from.  Must be\n                          a valid secret key.\n                        type: string\n                      name:\n                        description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                          TODO: Add other useful fields. apiVersion, kind, uid?'\n                        type: string\n                      optional:\n                        description: Specify whether the Secret or its key must be\n                          defined\n                        type: boolean\n                    required:\n                    - key\n                    type: object\n                  tracingConfigFile:\n                    description: TracingConfig specifies the path of the tracing configuration\n                      file. When used alongside with TracingConfig, TracingConfigFile\n                      takes precedence.\n                    type: string\n                  version:\n                    description: Version describes the version of Thanos to use.\n                    type: string\n                type: object\n              tolerations:\n                description: If specified, the pod's tolerations.\n                items:\n                  description: The pod this Toleration is attached to tolerates any\n                    taint that matches the triple <key,value,effect> using the matching\n                    operator <operator>.\n                  properties:\n                    effect:\n                      description: Effect indicates the taint effect to match. Empty\n                        means match all taint effects. When specified, allowed values\n                        are NoSchedule, PreferNoSchedule and NoExecute.\n                      type: string\n                    key:\n                      description: Key is the taint key that the toleration applies\n                        to. Empty means match all taint keys. If the key is empty,\n                        operator must be Exists; this combination means to match all\n                        values and all keys.\n                      type: string\n                    operator:\n                      description: Operator represents a key's relationship to the\n                        value. Valid operators are Exists and Equal. Defaults to Equal.\n                        Exists is equivalent to wildcard for value, so that a pod\n                        can tolerate all taints of a particular category.\n                      type: string\n                    tolerationSeconds:\n                      description: TolerationSeconds represents the period of time\n                        the toleration (which must be of effect NoExecute, otherwise\n                        this field is ignored) tolerates the taint. By default, it\n                        is not set, which means tolerate the taint forever (do not\n                        evict). Zero and negative values will be treated as 0 (evict\n                        immediately) by the system.\n                      format: int64\n                      type: integer\n                    value:\n                      description: Value is the taint value the toleration matches\n                        to. If the operator is Exists, the value should be empty,\n                        otherwise just a regular string.\n                      type: string\n                  type: object\n                type: array\n              topologySpreadConstraints:\n                description: If specified, the pod's topology spread constraints.\n                items:\n                  description: TopologySpreadConstraint specifies how to spread matching\n                    pods among the given topology.\n                  properties:\n                    labelSelector:\n                      description: LabelSelector is used to find matching pods. Pods\n                        that match this label selector are counted to determine the\n                        number of pods in their corresponding topology domain.\n                      properties:\n                        matchExpressions:\n                          description: matchExpressions is a list of label selector\n                            requirements. The requirements are ANDed.\n                          items:\n                            description: A label selector requirement is a selector\n                              that contains values, a key, and an operator that relates\n                              the key and values.\n                            properties:\n                              key:\n                                description: key is the label key that the selector\n                                  applies to.\n                                type: string\n                              operator:\n                                description: operator represents a key's relationship\n                                  to a set of values. Valid operators are In, NotIn,\n                                  Exists and DoesNotExist.\n                                type: string\n                              values:\n                                description: values is an array of string values.\n                                  If the operator is In or NotIn, the values array\n                                  must be non-empty. If the operator is Exists or\n                                  DoesNotExist, the values array must be empty. This\n                                  array is replaced during a strategic merge patch.\n                                items:\n                                  type: string\n                                type: array\n                            required:\n                            - key\n                            - operator\n                            type: object\n                          type: array\n                        matchLabels:\n                          additionalProperties:\n                            type: string\n                          description: matchLabels is a map of {key,value} pairs.\n                            A single {key,value} in the matchLabels map is equivalent\n                            to an element of matchExpressions, whose key field is\n                            \"key\", the operator is \"In\", and the values array contains\n                            only \"value\". The requirements are ANDed.\n                          type: object\n                      type: object\n                    maxSkew:\n                      description: 'MaxSkew describes the degree to which pods may\n                        be unevenly distributed. It''s the maximum permitted difference\n                        between the number of matching pods in any two topology domains\n                        of a given topology type. For example, in a 3-zone cluster,\n                        MaxSkew is set to 1, and pods with the same labelSelector\n                        spread as 1/1/0: | zone1 | zone2 | zone3 | |   P   |   P   |       |\n                        - if MaxSkew is 1, incoming pod can only be scheduled to zone3\n                        to become 1/1/1; scheduling it onto zone1(zone2) would make\n                        the ActualSkew(2-0) on zone1(zone2) violate MaxSkew(1). -\n                        if MaxSkew is 2, incoming pod can be scheduled onto any zone.\n                        It''s a required field. Default value is 1 and 0 is not allowed.'\n                      format: int32\n                      type: integer\n                    topologyKey:\n                      description: TopologyKey is the key of node labels. Nodes that\n                        have a label with this key and identical values are considered\n                        to be in the same topology. We consider each <key, value>\n                        as a \"bucket\", and try to put balanced number of pods into\n                        each bucket. It's a required field.\n                      type: string\n                    whenUnsatisfiable:\n                      description: 'WhenUnsatisfiable indicates how to deal with a\n                        pod if it doesn''t satisfy the spread constraint. - DoNotSchedule\n                        (default) tells the scheduler not to schedule it - ScheduleAnyway\n                        tells the scheduler to still schedule it It''s considered\n                        as \"Unsatisfiable\" if and only if placing incoming pod on\n                        any topology violates \"MaxSkew\". For example, in a 3-zone\n                        cluster, MaxSkew is set to 1, and pods with the same labelSelector\n                        spread as 3/1/1: | zone1 | zone2 | zone3 | | P P P |   P   |   P   |\n                        If WhenUnsatisfiable is set to DoNotSchedule, incoming pod\n                        can only be scheduled to zone2(zone3) to become 3/2/1(3/1/2)\n                        as ActualSkew(2-1) on zone2(zone3) satisfies MaxSkew(1). In\n                        other words, the cluster can still be imbalanced, but scheduler\n                        won''t make it *more* imbalanced. It''s a required field.'\n                      type: string\n                  required:\n                  - maxSkew\n                  - topologyKey\n                  - whenUnsatisfiable\n                  type: object\n                type: array\n              version:\n                description: Version of Prometheus to be deployed.\n                type: string\n              volumeMounts:\n                description: VolumeMounts allows configuration of additional VolumeMounts\n                  on the output StatefulSet definition. VolumeMounts specified will\n                  be appended to other VolumeMounts in the prometheus container, that\n                  are generated as a result of StorageSpec objects.\n                items:\n                  description: VolumeMount describes a mounting of a Volume within\n                    a container.\n                  properties:\n                    mountPath:\n                      description: Path within the container at which the volume should\n                        be mounted.  Must not contain ':'.\n                      type: string\n                    mountPropagation:\n                      description: mountPropagation determines how mounts are propagated\n                        from the host to container and the other way around. When\n                        not set, MountPropagationNone is used. This field is beta\n                        in 1.10.\n                      type: string\n                    name:\n                      description: This must match the Name of a Volume.\n                      type: string\n                    readOnly:\n                      description: Mounted read-only if true, read-write otherwise\n                        (false or unspecified). Defaults to false.\n                      type: boolean\n                    subPath:\n                      description: Path within the volume from which the container's\n                        volume should be mounted. Defaults to \"\" (volume's root).\n                      type: string\n                    subPathExpr:\n                      description: Expanded path within the volume from which the\n                        container's volume should be mounted. Behaves similarly to\n                        SubPath but environment variable references $(VAR_NAME) are\n                        expanded using the container's environment. Defaults to \"\"\n                        (volume's root). SubPathExpr and SubPath are mutually exclusive.\n                      type: string\n                  required:\n                  - mountPath\n                  - name\n                  type: object\n                type: array\n              volumes:\n                description: Volumes allows configuration of additional volumes on\n                  the output StatefulSet definition. Volumes specified will be appended\n                  to other volumes that are generated as a result of StorageSpec objects.\n                items:\n                  description: Volume represents a named volume in a pod that may\n                    be accessed by any container in the pod.\n                  properties:\n                    awsElasticBlockStore:\n                      description: 'AWSElasticBlockStore represents an AWS Disk resource\n                        that is attached to a kubelet''s host machine and then exposed\n                        to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore'\n                      properties:\n                        fsType:\n                          description: 'Filesystem type of the volume that you want\n                            to mount. Tip: Ensure that the filesystem type is supported\n                            by the host operating system. Examples: \"ext4\", \"xfs\",\n                            \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore\n                            TODO: how do we prevent errors in the filesystem from\n                            compromising the machine'\n                          type: string\n                        partition:\n                          description: 'The partition in the volume that you want\n                            to mount. If omitted, the default is to mount by volume\n                            name. Examples: For volume /dev/sda1, you specify the\n                            partition as \"1\". Similarly, the volume partition for\n                            /dev/sda is \"0\" (or you can leave the property empty).'\n                          format: int32\n                          type: integer\n                        readOnly:\n                          description: 'Specify \"true\" to force and set the ReadOnly\n                            property in VolumeMounts to \"true\". If omitted, the default\n                            is \"false\". More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore'\n                          type: boolean\n                        volumeID:\n                          description: 'Unique ID of the persistent disk resource\n                            in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore'\n                          type: string\n                      required:\n                      - volumeID\n                      type: object\n                    azureDisk:\n                      description: AzureDisk represents an Azure Data Disk mount on\n                        the host and bind mount to the pod.\n                      properties:\n                        cachingMode:\n                          description: 'Host Caching mode: None, Read Only, Read Write.'\n                          type: string\n                        diskName:\n                          description: The Name of the data disk in the blob storage\n                          type: string\n                        diskURI:\n                          description: The URI the data disk in the blob storage\n                          type: string\n                        fsType:\n                          description: Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                          type: string\n                        kind:\n                          description: 'Expected values Shared: multiple blob disks\n                            per storage account  Dedicated: single blob disk per storage\n                            account  Managed: azure managed data disk (only in managed\n                            availability set). defaults to shared'\n                          type: string\n                        readOnly:\n                          description: Defaults to false (read/write). ReadOnly here\n                            will force the ReadOnly setting in VolumeMounts.\n                          type: boolean\n                      required:\n                      - diskName\n                      - diskURI\n                      type: object\n                    azureFile:\n                      description: AzureFile represents an Azure File Service mount\n                        on the host and bind mount to the pod.\n                      properties:\n                        readOnly:\n                          description: Defaults to false (read/write). ReadOnly here\n                            will force the ReadOnly setting in VolumeMounts.\n                          type: boolean\n                        secretName:\n                          description: the name of secret that contains Azure Storage\n                            Account Name and Key\n                          type: string\n                        shareName:\n                          description: Share Name\n                          type: string\n                      required:\n                      - secretName\n                      - shareName\n                      type: object\n                    cephfs:\n                      description: CephFS represents a Ceph FS mount on the host that\n                        shares a pod's lifetime\n                      properties:\n                        monitors:\n                          description: 'Required: Monitors is a collection of Ceph\n                            monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it'\n                          items:\n                            type: string\n                          type: array\n                        path:\n                          description: 'Optional: Used as the mounted root, rather\n                            than the full Ceph tree, default is /'\n                          type: string\n                        readOnly:\n                          description: 'Optional: Defaults to false (read/write).\n                            ReadOnly here will force the ReadOnly setting in VolumeMounts.\n                            More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it'\n                          type: boolean\n                        secretFile:\n                          description: 'Optional: SecretFile is the path to key ring\n                            for User, default is /etc/ceph/user.secret More info:\n                            https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it'\n                          type: string\n                        secretRef:\n                          description: 'Optional: SecretRef is reference to the authentication\n                            secret for User, default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it'\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        user:\n                          description: 'Optional: User is the rados user name, default\n                            is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it'\n                          type: string\n                      required:\n                      - monitors\n                      type: object\n                    cinder:\n                      description: 'Cinder represents a cinder volume attached and\n                        mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md'\n                      properties:\n                        fsType:\n                          description: 'Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Examples:\n                            \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\"\n                            if unspecified. More info: https://examples.k8s.io/mysql-cinder-pd/README.md'\n                          type: string\n                        readOnly:\n                          description: 'Optional: Defaults to false (read/write).\n                            ReadOnly here will force the ReadOnly setting in VolumeMounts.\n                            More info: https://examples.k8s.io/mysql-cinder-pd/README.md'\n                          type: boolean\n                        secretRef:\n                          description: 'Optional: points to a secret object containing\n                            parameters used to connect to OpenStack.'\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        volumeID:\n                          description: 'volume id used to identify the volume in cinder.\n                            More info: https://examples.k8s.io/mysql-cinder-pd/README.md'\n                          type: string\n                      required:\n                      - volumeID\n                      type: object\n                    configMap:\n                      description: ConfigMap represents a configMap that should populate\n                        this volume\n                      properties:\n                        defaultMode:\n                          description: 'Optional: mode bits to use on created files\n                            by default. Must be a value between 0 and 0777. Defaults\n                            to 0644. Directories within the path are not affected\n                            by this setting. This might be in conflict with other\n                            options that affect the file mode, like fsGroup, and the\n                            result can be other mode bits set.'\n                          format: int32\n                          type: integer\n                        items:\n                          description: If unspecified, each key-value pair in the\n                            Data field of the referenced ConfigMap will be projected\n                            into the volume as a file whose name is the key and content\n                            is the value. If specified, the listed keys will be projected\n                            into the specified paths, and unlisted keys will not be\n                            present. If a key is specified which is not present in\n                            the ConfigMap, the volume setup will error unless it is\n                            marked optional. Paths must be relative and may not contain\n                            the '..' path or start with '..'.\n                          items:\n                            description: Maps a string key to a path within a volume.\n                            properties:\n                              key:\n                                description: The key to project.\n                                type: string\n                              mode:\n                                description: 'Optional: mode bits to use on this file,\n                                  must be a value between 0 and 0777. If not specified,\n                                  the volume defaultMode will be used. This might\n                                  be in conflict with other options that affect the\n                                  file mode, like fsGroup, and the result can be other\n                                  mode bits set.'\n                                format: int32\n                                type: integer\n                              path:\n                                description: The relative path of the file to map\n                                  the key to. May not be an absolute path. May not\n                                  contain the path element '..'. May not start with\n                                  the string '..'.\n                                type: string\n                            required:\n                            - key\n                            - path\n                            type: object\n                          type: array\n                        name:\n                          description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                            TODO: Add other useful fields. apiVersion, kind, uid?'\n                          type: string\n                        optional:\n                          description: Specify whether the ConfigMap or its keys must\n                            be defined\n                          type: boolean\n                      type: object\n                    csi:\n                      description: CSI (Container Storage Interface) represents storage\n                        that is handled by an external CSI driver (Alpha feature).\n                      properties:\n                        driver:\n                          description: Driver is the name of the CSI driver that handles\n                            this volume. Consult with your admin for the correct name\n                            as registered in the cluster.\n                          type: string\n                        fsType:\n                          description: Filesystem type to mount. Ex. \"ext4\", \"xfs\",\n                            \"ntfs\". If not provided, the empty value is passed to\n                            the associated CSI driver which will determine the default\n                            filesystem to apply.\n                          type: string\n                        nodePublishSecretRef:\n                          description: NodePublishSecretRef is a reference to the\n                            secret object containing sensitive information to pass\n                            to the CSI driver to complete the CSI NodePublishVolume\n                            and NodeUnpublishVolume calls. This field is optional,\n                            and  may be empty if no secret is required. If the secret\n                            object contains more than one secret, all secret references\n                            are passed.\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        readOnly:\n                          description: Specifies a read-only configuration for the\n                            volume. Defaults to false (read/write).\n                          type: boolean\n                        volumeAttributes:\n                          additionalProperties:\n                            type: string\n                          description: VolumeAttributes stores driver-specific properties\n                            that are passed to the CSI driver. Consult your driver's\n                            documentation for supported values.\n                          type: object\n                      required:\n                      - driver\n                      type: object\n                    downwardAPI:\n                      description: DownwardAPI represents downward API about the pod\n                        that should populate this volume\n                      properties:\n                        defaultMode:\n                          description: 'Optional: mode bits to use on created files\n                            by default. Must be a value between 0 and 0777. Defaults\n                            to 0644. Directories within the path are not affected\n                            by this setting. This might be in conflict with other\n                            options that affect the file mode, like fsGroup, and the\n                            result can be other mode bits set.'\n                          format: int32\n                          type: integer\n                        items:\n                          description: Items is a list of downward API volume file\n                          items:\n                            description: DownwardAPIVolumeFile represents information\n                              to create the file containing the pod field\n                            properties:\n                              fieldRef:\n                                description: 'Required: Selects a field of the pod:\n                                  only annotations, labels, name and namespace are\n                                  supported.'\n                                properties:\n                                  apiVersion:\n                                    description: Version of the schema the FieldPath\n                                      is written in terms of, defaults to \"v1\".\n                                    type: string\n                                  fieldPath:\n                                    description: Path of the field to select in the\n                                      specified API version.\n                                    type: string\n                                required:\n                                - fieldPath\n                                type: object\n                              mode:\n                                description: 'Optional: mode bits to use on this file,\n                                  must be a value between 0 and 0777. If not specified,\n                                  the volume defaultMode will be used. This might\n                                  be in conflict with other options that affect the\n                                  file mode, like fsGroup, and the result can be other\n                                  mode bits set.'\n                                format: int32\n                                type: integer\n                              path:\n                                description: 'Required: Path is  the relative path\n                                  name of the file to be created. Must not be absolute\n                                  or contain the ''..'' path. Must be utf-8 encoded.\n                                  The first item of the relative path must not start\n                                  with ''..'''\n                                type: string\n                              resourceFieldRef:\n                                description: 'Selects a resource of the container:\n                                  only resources limits and requests (limits.cpu,\n                                  limits.memory, requests.cpu and requests.memory)\n                                  are currently supported.'\n                                properties:\n                                  containerName:\n                                    description: 'Container name: required for volumes,\n                                      optional for env vars'\n                                    type: string\n                                  divisor:\n                                    anyOf:\n                                    - type: integer\n                                    - type: string\n                                    description: Specifies the output format of the\n                                      exposed resources, defaults to \"1\"\n                                    pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                    x-kubernetes-int-or-string: true\n                                  resource:\n                                    description: 'Required: resource to select'\n                                    type: string\n                                required:\n                                - resource\n                                type: object\n                            required:\n                            - path\n                            type: object\n                          type: array\n                      type: object\n                    emptyDir:\n                      description: 'EmptyDir represents a temporary directory that\n                        shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir'\n                      properties:\n                        medium:\n                          description: 'What type of storage medium should back this\n                            directory. The default is \"\" which means to use the node''s\n                            default medium. Must be an empty string (default) or Memory.\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir'\n                          type: string\n                        sizeLimit:\n                          anyOf:\n                          - type: integer\n                          - type: string\n                          description: 'Total amount of local storage required for\n                            this EmptyDir volume. The size limit is also applicable\n                            for memory medium. The maximum usage on memory medium\n                            EmptyDir would be the minimum value between the SizeLimit\n                            specified here and the sum of memory limits of all containers\n                            in a pod. The default is nil which means that the limit\n                            is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir'\n                          pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                          x-kubernetes-int-or-string: true\n                      type: object\n                    fc:\n                      description: FC represents a Fibre Channel resource that is\n                        attached to a kubelet's host machine and then exposed to the\n                        pod.\n                      properties:\n                        fsType:\n                          description: 'Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                            TODO: how do we prevent errors in the filesystem from\n                            compromising the machine'\n                          type: string\n                        lun:\n                          description: 'Optional: FC target lun number'\n                          format: int32\n                          type: integer\n                        readOnly:\n                          description: 'Optional: Defaults to false (read/write).\n                            ReadOnly here will force the ReadOnly setting in VolumeMounts.'\n                          type: boolean\n                        targetWWNs:\n                          description: 'Optional: FC target worldwide names (WWNs)'\n                          items:\n                            type: string\n                          type: array\n                        wwids:\n                          description: 'Optional: FC volume world wide identifiers\n                            (wwids) Either wwids or combination of targetWWNs and\n                            lun must be set, but not both simultaneously.'\n                          items:\n                            type: string\n                          type: array\n                      type: object\n                    flexVolume:\n                      description: FlexVolume represents a generic volume resource\n                        that is provisioned/attached using an exec based plugin.\n                      properties:\n                        driver:\n                          description: Driver is the name of the driver to use for\n                            this volume.\n                          type: string\n                        fsType:\n                          description: Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". The default filesystem depends on FlexVolume\n                            script.\n                          type: string\n                        options:\n                          additionalProperties:\n                            type: string\n                          description: 'Optional: Extra command options if any.'\n                          type: object\n                        readOnly:\n                          description: 'Optional: Defaults to false (read/write).\n                            ReadOnly here will force the ReadOnly setting in VolumeMounts.'\n                          type: boolean\n                        secretRef:\n                          description: 'Optional: SecretRef is reference to the secret\n                            object containing sensitive information to pass to the\n                            plugin scripts. This may be empty if no secret object\n                            is specified. If the secret object contains more than\n                            one secret, all secrets are passed to the plugin scripts.'\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                      required:\n                      - driver\n                      type: object\n                    flocker:\n                      description: Flocker represents a Flocker volume attached to\n                        a kubelet's host machine. This depends on the Flocker control\n                        service being running\n                      properties:\n                        datasetName:\n                          description: Name of the dataset stored as metadata -> name\n                            on the dataset for Flocker should be considered as deprecated\n                          type: string\n                        datasetUUID:\n                          description: UUID of the dataset. This is unique identifier\n                            of a Flocker dataset\n                          type: string\n                      type: object\n                    gcePersistentDisk:\n                      description: 'GCEPersistentDisk represents a GCE Disk resource\n                        that is attached to a kubelet''s host machine and then exposed\n                        to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk'\n                      properties:\n                        fsType:\n                          description: 'Filesystem type of the volume that you want\n                            to mount. Tip: Ensure that the filesystem type is supported\n                            by the host operating system. Examples: \"ext4\", \"xfs\",\n                            \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk\n                            TODO: how do we prevent errors in the filesystem from\n                            compromising the machine'\n                          type: string\n                        partition:\n                          description: 'The partition in the volume that you want\n                            to mount. If omitted, the default is to mount by volume\n                            name. Examples: For volume /dev/sda1, you specify the\n                            partition as \"1\". Similarly, the volume partition for\n                            /dev/sda is \"0\" (or you can leave the property empty).\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk'\n                          format: int32\n                          type: integer\n                        pdName:\n                          description: 'Unique name of the PD resource in GCE. Used\n                            to identify the disk in GCE. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk'\n                          type: string\n                        readOnly:\n                          description: 'ReadOnly here will force the ReadOnly setting\n                            in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk'\n                          type: boolean\n                      required:\n                      - pdName\n                      type: object\n                    gitRepo:\n                      description: 'GitRepo represents a git repository at a particular\n                        revision. DEPRECATED: GitRepo is deprecated. To provision\n                        a container with a git repo, mount an EmptyDir into an InitContainer\n                        that clones the repo using git, then mount the EmptyDir into\n                        the Pod''s container.'\n                      properties:\n                        directory:\n                          description: Target directory name. Must not contain or\n                            start with '..'.  If '.' is supplied, the volume directory\n                            will be the git repository.  Otherwise, if specified,\n                            the volume will contain the git repository in the subdirectory\n                            with the given name.\n                          type: string\n                        repository:\n                          description: Repository URL\n                          type: string\n                        revision:\n                          description: Commit hash for the specified revision.\n                          type: string\n                      required:\n                      - repository\n                      type: object\n                    glusterfs:\n                      description: 'Glusterfs represents a Glusterfs mount on the\n                        host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md'\n                      properties:\n                        endpoints:\n                          description: 'EndpointsName is the endpoint name that details\n                            Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod'\n                          type: string\n                        path:\n                          description: 'Path is the Glusterfs volume path. More info:\n                            https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod'\n                          type: string\n                        readOnly:\n                          description: 'ReadOnly here will force the Glusterfs volume\n                            to be mounted with read-only permissions. Defaults to\n                            false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod'\n                          type: boolean\n                      required:\n                      - endpoints\n                      - path\n                      type: object\n                    hostPath:\n                      description: 'HostPath represents a pre-existing file or directory\n                        on the host machine that is directly exposed to the container.\n                        This is generally used for system agents or other privileged\n                        things that are allowed to see the host machine. Most containers\n                        will NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath\n                        --- TODO(jonesdl) We need to restrict who can use host directory\n                        mounts and who can/can not mount host directories as read/write.'\n                      properties:\n                        path:\n                          description: 'Path of the directory on the host. If the\n                            path is a symlink, it will follow the link to the real\n                            path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath'\n                          type: string\n                        type:\n                          description: 'Type for HostPath Volume Defaults to \"\" More\n                            info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath'\n                          type: string\n                      required:\n                      - path\n                      type: object\n                    iscsi:\n                      description: 'ISCSI represents an ISCSI Disk resource that is\n                        attached to a kubelet''s host machine and then exposed to\n                        the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md'\n                      properties:\n                        chapAuthDiscovery:\n                          description: whether support iSCSI Discovery CHAP authentication\n                          type: boolean\n                        chapAuthSession:\n                          description: whether support iSCSI Session CHAP authentication\n                          type: boolean\n                        fsType:\n                          description: 'Filesystem type of the volume that you want\n                            to mount. Tip: Ensure that the filesystem type is supported\n                            by the host operating system. Examples: \"ext4\", \"xfs\",\n                            \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi\n                            TODO: how do we prevent errors in the filesystem from\n                            compromising the machine'\n                          type: string\n                        initiatorName:\n                          description: Custom iSCSI Initiator Name. If initiatorName\n                            is specified with iscsiInterface simultaneously, new iSCSI\n                            interface <target portal>:<volume name> will be created\n                            for the connection.\n                          type: string\n                        iqn:\n                          description: Target iSCSI Qualified Name.\n                          type: string\n                        iscsiInterface:\n                          description: iSCSI Interface Name that uses an iSCSI transport.\n                            Defaults to 'default' (tcp).\n                          type: string\n                        lun:\n                          description: iSCSI Target Lun number.\n                          format: int32\n                          type: integer\n                        portals:\n                          description: iSCSI Target Portal List. The portal is either\n                            an IP or ip_addr:port if the port is other than default\n                            (typically TCP ports 860 and 3260).\n                          items:\n                            type: string\n                          type: array\n                        readOnly:\n                          description: ReadOnly here will force the ReadOnly setting\n                            in VolumeMounts. Defaults to false.\n                          type: boolean\n                        secretRef:\n                          description: CHAP Secret for iSCSI target and initiator\n                            authentication\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        targetPortal:\n                          description: iSCSI Target Portal. The Portal is either an\n                            IP or ip_addr:port if the port is other than default (typically\n                            TCP ports 860 and 3260).\n                          type: string\n                      required:\n                      - iqn\n                      - lun\n                      - targetPortal\n                      type: object\n                    name:\n                      description: 'Volume''s name. Must be a DNS_LABEL and unique\n                        within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'\n                      type: string\n                    nfs:\n                      description: 'NFS represents an NFS mount on the host that shares\n                        a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs'\n                      properties:\n                        path:\n                          description: 'Path that is exported by the NFS server. More\n                            info: https://kubernetes.io/docs/concepts/storage/volumes#nfs'\n                          type: string\n                        readOnly:\n                          description: 'ReadOnly here will force the NFS export to\n                            be mounted with read-only permissions. Defaults to false.\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs'\n                          type: boolean\n                        server:\n                          description: 'Server is the hostname or IP address of the\n                            NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs'\n                          type: string\n                      required:\n                      - path\n                      - server\n                      type: object\n                    persistentVolumeClaim:\n                      description: 'PersistentVolumeClaimVolumeSource represents a\n                        reference to a PersistentVolumeClaim in the same namespace.\n                        More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'\n                      properties:\n                        claimName:\n                          description: 'ClaimName is the name of a PersistentVolumeClaim\n                            in the same namespace as the pod using this volume. More\n                            info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'\n                          type: string\n                        readOnly:\n                          description: Will force the ReadOnly setting in VolumeMounts.\n                            Default false.\n                          type: boolean\n                      required:\n                      - claimName\n                      type: object\n                    photonPersistentDisk:\n                      description: PhotonPersistentDisk represents a PhotonController\n                        persistent disk attached and mounted on kubelets host machine\n                      properties:\n                        fsType:\n                          description: Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                          type: string\n                        pdID:\n                          description: ID that identifies Photon Controller persistent\n                            disk\n                          type: string\n                      required:\n                      - pdID\n                      type: object\n                    portworxVolume:\n                      description: PortworxVolume represents a portworx volume attached\n                        and mounted on kubelets host machine\n                      properties:\n                        fsType:\n                          description: FSType represents the filesystem type to mount\n                            Must be a filesystem type supported by the host operating\n                            system. Ex. \"ext4\", \"xfs\". Implicitly inferred to be \"ext4\"\n                            if unspecified.\n                          type: string\n                        readOnly:\n                          description: Defaults to false (read/write). ReadOnly here\n                            will force the ReadOnly setting in VolumeMounts.\n                          type: boolean\n                        volumeID:\n                          description: VolumeID uniquely identifies a Portworx volume\n                          type: string\n                      required:\n                      - volumeID\n                      type: object\n                    projected:\n                      description: Items for all in one resources secrets, configmaps,\n                        and downward API\n                      properties:\n                        defaultMode:\n                          description: Mode bits to use on created files by default.\n                            Must be a value between 0 and 0777. Directories within\n                            the path are not affected by this setting. This might\n                            be in conflict with other options that affect the file\n                            mode, like fsGroup, and the result can be other mode bits\n                            set.\n                          format: int32\n                          type: integer\n                        sources:\n                          description: list of volume projections\n                          items:\n                            description: Projection that may be projected along with\n                              other supported volume types\n                            properties:\n                              configMap:\n                                description: information about the configMap data\n                                  to project\n                                properties:\n                                  items:\n                                    description: If unspecified, each key-value pair\n                                      in the Data field of the referenced ConfigMap\n                                      will be projected into the volume as a file\n                                      whose name is the key and content is the value.\n                                      If specified, the listed keys will be projected\n                                      into the specified paths, and unlisted keys\n                                      will not be present. If a key is specified which\n                                      is not present in the ConfigMap, the volume\n                                      setup will error unless it is marked optional.\n                                      Paths must be relative and may not contain the\n                                      '..' path or start with '..'.\n                                    items:\n                                      description: Maps a string key to a path within\n                                        a volume.\n                                      properties:\n                                        key:\n                                          description: The key to project.\n                                          type: string\n                                        mode:\n                                          description: 'Optional: mode bits to use\n                                            on this file, must be a value between\n                                            0 and 0777. If not specified, the volume\n                                            defaultMode will be used. This might be\n                                            in conflict with other options that affect\n                                            the file mode, like fsGroup, and the result\n                                            can be other mode bits set.'\n                                          format: int32\n                                          type: integer\n                                        path:\n                                          description: The relative path of the file\n                                            to map the key to. May not be an absolute\n                                            path. May not contain the path element\n                                            '..'. May not start with the string '..'.\n                                          type: string\n                                      required:\n                                      - key\n                                      - path\n                                      type: object\n                                    type: array\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the ConfigMap or\n                                      its keys must be defined\n                                    type: boolean\n                                type: object\n                              downwardAPI:\n                                description: information about the downwardAPI data\n                                  to project\n                                properties:\n                                  items:\n                                    description: Items is a list of DownwardAPIVolume\n                                      file\n                                    items:\n                                      description: DownwardAPIVolumeFile represents\n                                        information to create the file containing\n                                        the pod field\n                                      properties:\n                                        fieldRef:\n                                          description: 'Required: Selects a field\n                                            of the pod: only annotations, labels,\n                                            name and namespace are supported.'\n                                          properties:\n                                            apiVersion:\n                                              description: Version of the schema the\n                                                FieldPath is written in terms of,\n                                                defaults to \"v1\".\n                                              type: string\n                                            fieldPath:\n                                              description: Path of the field to select\n                                                in the specified API version.\n                                              type: string\n                                          required:\n                                          - fieldPath\n                                          type: object\n                                        mode:\n                                          description: 'Optional: mode bits to use\n                                            on this file, must be a value between\n                                            0 and 0777. If not specified, the volume\n                                            defaultMode will be used. This might be\n                                            in conflict with other options that affect\n                                            the file mode, like fsGroup, and the result\n                                            can be other mode bits set.'\n                                          format: int32\n                                          type: integer\n                                        path:\n                                          description: 'Required: Path is  the relative\n                                            path name of the file to be created. Must\n                                            not be absolute or contain the ''..''\n                                            path. Must be utf-8 encoded. The first\n                                            item of the relative path must not start\n                                            with ''..'''\n                                          type: string\n                                        resourceFieldRef:\n                                          description: 'Selects a resource of the\n                                            container: only resources limits and requests\n                                            (limits.cpu, limits.memory, requests.cpu\n                                            and requests.memory) are currently supported.'\n                                          properties:\n                                            containerName:\n                                              description: 'Container name: required\n                                                for volumes, optional for env vars'\n                                              type: string\n                                            divisor:\n                                              anyOf:\n                                              - type: integer\n                                              - type: string\n                                              description: Specifies the output format\n                                                of the exposed resources, defaults\n                                                to \"1\"\n                                              pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                              x-kubernetes-int-or-string: true\n                                            resource:\n                                              description: 'Required: resource to\n                                                select'\n                                              type: string\n                                          required:\n                                          - resource\n                                          type: object\n                                      required:\n                                      - path\n                                      type: object\n                                    type: array\n                                type: object\n                              secret:\n                                description: information about the secret data to\n                                  project\n                                properties:\n                                  items:\n                                    description: If unspecified, each key-value pair\n                                      in the Data field of the referenced Secret will\n                                      be projected into the volume as a file whose\n                                      name is the key and content is the value. If\n                                      specified, the listed keys will be projected\n                                      into the specified paths, and unlisted keys\n                                      will not be present. If a key is specified which\n                                      is not present in the Secret, the volume setup\n                                      will error unless it is marked optional. Paths\n                                      must be relative and may not contain the '..'\n                                      path or start with '..'.\n                                    items:\n                                      description: Maps a string key to a path within\n                                        a volume.\n                                      properties:\n                                        key:\n                                          description: The key to project.\n                                          type: string\n                                        mode:\n                                          description: 'Optional: mode bits to use\n                                            on this file, must be a value between\n                                            0 and 0777. If not specified, the volume\n                                            defaultMode will be used. This might be\n                                            in conflict with other options that affect\n                                            the file mode, like fsGroup, and the result\n                                            can be other mode bits set.'\n                                          format: int32\n                                          type: integer\n                                        path:\n                                          description: The relative path of the file\n                                            to map the key to. May not be an absolute\n                                            path. May not contain the path element\n                                            '..'. May not start with the string '..'.\n                                          type: string\n                                      required:\n                                      - key\n                                      - path\n                                      type: object\n                                    type: array\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the Secret or its\n                                      key must be defined\n                                    type: boolean\n                                type: object\n                              serviceAccountToken:\n                                description: information about the serviceAccountToken\n                                  data to project\n                                properties:\n                                  audience:\n                                    description: Audience is the intended audience\n                                      of the token. A recipient of a token must identify\n                                      itself with an identifier specified in the audience\n                                      of the token, and otherwise should reject the\n                                      token. The audience defaults to the identifier\n                                      of the apiserver.\n                                    type: string\n                                  expirationSeconds:\n                                    description: ExpirationSeconds is the requested\n                                      duration of validity of the service account\n                                      token. As the token approaches expiration, the\n                                      kubelet volume plugin will proactively rotate\n                                      the service account token. The kubelet will\n                                      start trying to rotate the token if the token\n                                      is older than 80 percent of its time to live\n                                      or if the token is older than 24 hours.Defaults\n                                      to 1 hour and must be at least 10 minutes.\n                                    format: int64\n                                    type: integer\n                                  path:\n                                    description: Path is the path relative to the\n                                      mount point of the file to project the token\n                                      into.\n                                    type: string\n                                required:\n                                - path\n                                type: object\n                            type: object\n                          type: array\n                      required:\n                      - sources\n                      type: object\n                    quobyte:\n                      description: Quobyte represents a Quobyte mount on the host\n                        that shares a pod's lifetime\n                      properties:\n                        group:\n                          description: Group to map volume access to Default is no\n                            group\n                          type: string\n                        readOnly:\n                          description: ReadOnly here will force the Quobyte volume\n                            to be mounted with read-only permissions. Defaults to\n                            false.\n                          type: boolean\n                        registry:\n                          description: Registry represents a single or multiple Quobyte\n                            Registry services specified as a string as host:port pair\n                            (multiple entries are separated with commas) which acts\n                            as the central registry for volumes\n                          type: string\n                        tenant:\n                          description: Tenant owning the given Quobyte volume in the\n                            Backend Used with dynamically provisioned Quobyte volumes,\n                            value is set by the plugin\n                          type: string\n                        user:\n                          description: User to map volume access to Defaults to serivceaccount\n                            user\n                          type: string\n                        volume:\n                          description: Volume is a string that references an already\n                            created Quobyte volume by name.\n                          type: string\n                      required:\n                      - registry\n                      - volume\n                      type: object\n                    rbd:\n                      description: 'RBD represents a Rados Block Device mount on the\n                        host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md'\n                      properties:\n                        fsType:\n                          description: 'Filesystem type of the volume that you want\n                            to mount. Tip: Ensure that the filesystem type is supported\n                            by the host operating system. Examples: \"ext4\", \"xfs\",\n                            \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd\n                            TODO: how do we prevent errors in the filesystem from\n                            compromising the machine'\n                          type: string\n                        image:\n                          description: 'The rados image name. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          type: string\n                        keyring:\n                          description: 'Keyring is the path to key ring for RBDUser.\n                            Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          type: string\n                        monitors:\n                          description: 'A collection of Ceph monitors. More info:\n                            https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          items:\n                            type: string\n                          type: array\n                        pool:\n                          description: 'The rados pool name. Default is rbd. More\n                            info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          type: string\n                        readOnly:\n                          description: 'ReadOnly here will force the ReadOnly setting\n                            in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          type: boolean\n                        secretRef:\n                          description: 'SecretRef is name of the authentication secret\n                            for RBDUser. If provided overrides keyring. Default is\n                            nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        user:\n                          description: 'The rados user name. Default is admin. More\n                            info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          type: string\n                      required:\n                      - image\n                      - monitors\n                      type: object\n                    scaleIO:\n                      description: ScaleIO represents a ScaleIO persistent volume\n                        attached and mounted on Kubernetes nodes.\n                      properties:\n                        fsType:\n                          description: Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". Default is \"xfs\".\n                          type: string\n                        gateway:\n                          description: The host address of the ScaleIO API Gateway.\n                          type: string\n                        protectionDomain:\n                          description: The name of the ScaleIO Protection Domain for\n                            the configured storage.\n                          type: string\n                        readOnly:\n                          description: Defaults to false (read/write). ReadOnly here\n                            will force the ReadOnly setting in VolumeMounts.\n                          type: boolean\n                        secretRef:\n                          description: SecretRef references to the secret for ScaleIO\n                            user and other sensitive information. If this is not provided,\n                            Login operation will fail.\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        sslEnabled:\n                          description: Flag to enable/disable SSL communication with\n                            Gateway, default false\n                          type: boolean\n                        storageMode:\n                          description: Indicates whether the storage for a volume\n                            should be ThickProvisioned or ThinProvisioned. Default\n                            is ThinProvisioned.\n                          type: string\n                        storagePool:\n                          description: The ScaleIO Storage Pool associated with the\n                            protection domain.\n                          type: string\n                        system:\n                          description: The name of the storage system as configured\n                            in ScaleIO.\n                          type: string\n                        volumeName:\n                          description: The name of a volume already created in the\n                            ScaleIO system that is associated with this volume source.\n                          type: string\n                      required:\n                      - gateway\n                      - secretRef\n                      - system\n                      type: object\n                    secret:\n                      description: 'Secret represents a secret that should populate\n                        this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret'\n                      properties:\n                        defaultMode:\n                          description: 'Optional: mode bits to use on created files\n                            by default. Must be a value between 0 and 0777. Defaults\n                            to 0644. Directories within the path are not affected\n                            by this setting. This might be in conflict with other\n                            options that affect the file mode, like fsGroup, and the\n                            result can be other mode bits set.'\n                          format: int32\n                          type: integer\n                        items:\n                          description: If unspecified, each key-value pair in the\n                            Data field of the referenced Secret will be projected\n                            into the volume as a file whose name is the key and content\n                            is the value. If specified, the listed keys will be projected\n                            into the specified paths, and unlisted keys will not be\n                            present. If a key is specified which is not present in\n                            the Secret, the volume setup will error unless it is marked\n                            optional. Paths must be relative and may not contain the\n                            '..' path or start with '..'.\n                          items:\n                            description: Maps a string key to a path within a volume.\n                            properties:\n                              key:\n                                description: The key to project.\n                                type: string\n                              mode:\n                                description: 'Optional: mode bits to use on this file,\n                                  must be a value between 0 and 0777. If not specified,\n                                  the volume defaultMode will be used. This might\n                                  be in conflict with other options that affect the\n                                  file mode, like fsGroup, and the result can be other\n                                  mode bits set.'\n                                format: int32\n                                type: integer\n                              path:\n                                description: The relative path of the file to map\n                                  the key to. May not be an absolute path. May not\n                                  contain the path element '..'. May not start with\n                                  the string '..'.\n                                type: string\n                            required:\n                            - key\n                            - path\n                            type: object\n                          type: array\n                        optional:\n                          description: Specify whether the Secret or its keys must\n                            be defined\n                          type: boolean\n                        secretName:\n                          description: 'Name of the secret in the pod''s namespace\n                            to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret'\n                          type: string\n                      type: object\n                    storageos:\n                      description: StorageOS represents a StorageOS volume attached\n                        and mounted on Kubernetes nodes.\n                      properties:\n                        fsType:\n                          description: Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                          type: string\n                        readOnly:\n                          description: Defaults to false (read/write). ReadOnly here\n                            will force the ReadOnly setting in VolumeMounts.\n                          type: boolean\n                        secretRef:\n                          description: SecretRef specifies the secret to use for obtaining\n                            the StorageOS API credentials.  If not specified, default\n                            values will be attempted.\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        volumeName:\n                          description: VolumeName is the human-readable name of the\n                            StorageOS volume.  Volume names are only unique within\n                            a namespace.\n                          type: string\n                        volumeNamespace:\n                          description: VolumeNamespace specifies the scope of the\n                            volume within StorageOS.  If no namespace is specified\n                            then the Pod's namespace will be used.  This allows the\n                            Kubernetes name scoping to be mirrored within StorageOS\n                            for tighter integration. Set VolumeName to any name to\n                            override the default behaviour. Set to \"default\" if you\n                            are not using namespaces within StorageOS. Namespaces\n                            that do not pre-exist within StorageOS will be created.\n                          type: string\n                      type: object\n                    vsphereVolume:\n                      description: VsphereVolume represents a vSphere volume attached\n                        and mounted on kubelets host machine\n                      properties:\n                        fsType:\n                          description: Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                          type: string\n                        storagePolicyID:\n                          description: Storage Policy Based Management (SPBM) profile\n                            ID associated with the StoragePolicyName.\n                          type: string\n                        storagePolicyName:\n                          description: Storage Policy Based Management (SPBM) profile\n                            name.\n                          type: string\n                        volumePath:\n                          description: Path that identifies vSphere volume vmdk\n                          type: string\n                      required:\n                      - volumePath\n                      type: object\n                  required:\n                  - name\n                  type: object\n                type: array\n              walCompression:\n                description: Enable compression of the write-ahead log using Snappy.\n                  This flag is only available in versions of Prometheus >= 2.11.0.\n                type: boolean\n              web:\n                description: WebSpec defines the web command line flags when starting\n                  Prometheus.\n                properties:\n                  pageTitle:\n                    description: The prometheus web page title\n                    type: string\n                  tlsConfig:\n                    description: WebTLSConfig defines the TLS parameters for HTTPS.\n                    properties:\n                      cert:\n                        description: Contains the TLS certificate for the server.\n                        properties:\n                          configMap:\n                            description: ConfigMap containing data to use for the\n                              targets.\n                            properties:\n                              key:\n                                description: The key to select.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the ConfigMap or its\n                                  key must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                          secret:\n                            description: Secret containing data to use for the targets.\n                            properties:\n                              key:\n                                description: The key of the secret to select from.  Must\n                                  be a valid secret key.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret or its key\n                                  must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                        type: object\n                      cipherSuites:\n                        description: 'List of supported cipher suites for TLS versions\n                          up to TLS 1.2. If empty, Go default cipher suites are used.\n                          Available cipher suites are documented in the go documentation:\n                          https://golang.org/pkg/crypto/tls/#pkg-constants'\n                        items:\n                          type: string\n                        type: array\n                      client_ca:\n                        description: Contains the CA certificate for client certificate\n                          authentication to the server.\n                        properties:\n                          configMap:\n                            description: ConfigMap containing data to use for the\n                              targets.\n                            properties:\n                              key:\n                                description: The key to select.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the ConfigMap or its\n                                  key must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                          secret:\n                            description: Secret containing data to use for the targets.\n                            properties:\n                              key:\n                                description: The key of the secret to select from.  Must\n                                  be a valid secret key.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret or its key\n                                  must be defined\n                                type: boolean\n                            required:\n                            - key\n                            type: object\n                        type: object\n                      clientAuthType:\n                        description: 'Server policy for client authentication. Maps\n                          to ClientAuth Policies. For more detail on clientAuth options:\n                          https://golang.org/pkg/crypto/tls/#ClientAuthType'\n                        type: string\n                      curvePreferences:\n                        description: 'Elliptic curves that will be used in an ECDHE\n                          handshake, in preference order. Available curves are documented\n                          in the go documentation: https://golang.org/pkg/crypto/tls/#CurveID'\n                        items:\n                          type: string\n                        type: array\n                      keySecret:\n                        description: Secret containing the TLS key for the server.\n                        properties:\n                          key:\n                            description: The key of the secret to select from.  Must\n                              be a valid secret key.\n                            type: string\n                          name:\n                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                              TODO: Add other useful fields. apiVersion, kind, uid?'\n                            type: string\n                          optional:\n                            description: Specify whether the Secret or its key must\n                              be defined\n                            type: boolean\n                        required:\n                        - key\n                        type: object\n                      maxVersion:\n                        description: Maximum TLS version that is acceptable. Defaults\n                          to TLS13.\n                        type: string\n                      minVersion:\n                        description: Minimum TLS version that is acceptable. Defaults\n                          to TLS12.\n                        type: string\n                      preferServerCipherSuites:\n                        description: Controls whether the server selects the client's\n                          most preferred cipher suite, or the server's most preferred\n                          cipher suite. If true then the server's preference, as expressed\n                          in the order of elements in cipherSuites, is used.\n                        type: boolean\n                    required:\n                    - cert\n                    - keySecret\n                    type: object\n                type: object\n            type: object\n          status:\n            description: 'Most recent observed status of the Prometheus cluster. Read-only.\n              Not included when requesting from the apiserver, only from the Prometheus\n              Operator API itself. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status'\n            properties:\n              availableReplicas:\n                description: Total number of available pods (ready for at least minReadySeconds)\n                  targeted by this Prometheus deployment.\n                format: int32\n                type: integer\n              paused:\n                description: Represents whether any actions on the underlying managed\n                  objects are being performed. Only delete actions will be performed.\n                type: boolean\n              replicas:\n                description: Total number of non-terminated pods targeted by this\n                  Prometheus deployment (their labels match the selector).\n                format: int32\n                type: integer\n              unavailableReplicas:\n                description: Total number of unavailable pods targeted by this Prometheus\n                  deployment.\n                format: int32\n                type: integer\n              updatedReplicas:\n                description: Total number of non-terminated pods targeted by this\n                  Prometheus deployment that have the desired version spec.\n                format: int32\n                type: integer\n            required:\n            - availableReplicas\n            - paused\n            - replicas\n            - unavailableReplicas\n            - updatedReplicas\n            type: object\n        required:\n        - spec\n        type: object\n    served: true\n    storage: true\n    subresources: {}\nstatus:\n  acceptedNames:\n    kind: \"\"\n    plural: \"\"\n  conditions: []\n  storedVersions: []\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/crds/crd-prometheusrules.yaml",
    "content": "# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml\n\n---\napiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.4.1\n  creationTimestamp: null\n  name: prometheusrules.monitoring.coreos.com\nspec:\n  group: monitoring.coreos.com\n  names:\n    kind: PrometheusRule\n    listKind: PrometheusRuleList\n    plural: prometheusrules\n    singular: prometheusrule\n  scope: Namespaced\n  versions:\n  - name: v1\n    schema:\n      openAPIV3Schema:\n        description: PrometheusRule defines recording and alerting rules for a Prometheus\n          instance\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: Specification of desired alerting rule definitions for Prometheus.\n            properties:\n              groups:\n                description: Content of Prometheus rule file\n                items:\n                  description: 'RuleGroup is a list of sequentially evaluated recording\n                    and alerting rules. Note: PartialResponseStrategy is only used\n                    by ThanosRuler and will be ignored by Prometheus instances.  Valid\n                    values for this field are ''warn'' or ''abort''.  More info: https://github.com/thanos-io/thanos/blob/master/docs/components/rule.md#partial-response'\n                  properties:\n                    interval:\n                      type: string\n                    name:\n                      type: string\n                    partial_response_strategy:\n                      type: string\n                    rules:\n                      items:\n                        description: 'Rule describes an alerting or recording rule\n                          See Prometheus documentation: [alerting](https://www.prometheus.io/docs/prometheus/latest/configuration/alerting_rules/)\n                          or [recording](https://www.prometheus.io/docs/prometheus/latest/configuration/recording_rules/#recording-rules)\n                          rule'\n                        properties:\n                          alert:\n                            type: string\n                          annotations:\n                            additionalProperties:\n                              type: string\n                            type: object\n                          expr:\n                            anyOf:\n                            - type: integer\n                            - type: string\n                            x-kubernetes-int-or-string: true\n                          for:\n                            type: string\n                          labels:\n                            additionalProperties:\n                              type: string\n                            type: object\n                          record:\n                            type: string\n                        required:\n                        - expr\n                        type: object\n                      type: array\n                  required:\n                  - name\n                  - rules\n                  type: object\n                type: array\n            type: object\n        required:\n        - spec\n        type: object\n    served: true\n    storage: true\nstatus:\n  acceptedNames:\n    kind: \"\"\n    plural: \"\"\n  conditions: []\n  storedVersions: []\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/crds/crd-servicemonitors.yaml",
    "content": "# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml\n\n---\napiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.4.1\n  creationTimestamp: null\n  name: servicemonitors.monitoring.coreos.com\nspec:\n  group: monitoring.coreos.com\n  names:\n    categories:\n    - prometheus-operator\n    kind: ServiceMonitor\n    listKind: ServiceMonitorList\n    plural: servicemonitors\n    singular: servicemonitor\n  scope: Namespaced\n  versions:\n  - name: v1\n    schema:\n      openAPIV3Schema:\n        description: ServiceMonitor defines monitoring for a set of services.\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: Specification of desired Service selection for target discovery\n              by Prometheus.\n            properties:\n              endpoints:\n                description: A list of endpoints allowed as part of this ServiceMonitor.\n                items:\n                  description: Endpoint defines a scrapeable endpoint serving Prometheus\n                    metrics.\n                  properties:\n                    basicAuth:\n                      description: 'BasicAuth allow an endpoint to authenticate over\n                        basic authentication More info: https://prometheus.io/docs/operating/configuration/#endpoints'\n                      properties:\n                        password:\n                          description: The secret in the service monitor namespace\n                            that contains the password for authentication.\n                          properties:\n                            key:\n                              description: The key of the secret to select from.  Must\n                                be a valid secret key.\n                              type: string\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                            optional:\n                              description: Specify whether the Secret or its key must\n                                be defined\n                              type: boolean\n                          required:\n                          - key\n                          type: object\n                        username:\n                          description: The secret in the service monitor namespace\n                            that contains the username for authentication.\n                          properties:\n                            key:\n                              description: The key of the secret to select from.  Must\n                                be a valid secret key.\n                              type: string\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                            optional:\n                              description: Specify whether the Secret or its key must\n                                be defined\n                              type: boolean\n                          required:\n                          - key\n                          type: object\n                      type: object\n                    bearerTokenFile:\n                      description: File to read bearer token for scraping targets.\n                      type: string\n                    bearerTokenSecret:\n                      description: Secret to mount to read bearer token for scraping\n                        targets. The secret needs to be in the same namespace as the\n                        service monitor and accessible by the Prometheus Operator.\n                      properties:\n                        key:\n                          description: The key of the secret to select from.  Must\n                            be a valid secret key.\n                          type: string\n                        name:\n                          description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                            TODO: Add other useful fields. apiVersion, kind, uid?'\n                          type: string\n                        optional:\n                          description: Specify whether the Secret or its key must\n                            be defined\n                          type: boolean\n                      required:\n                      - key\n                      type: object\n                    honorLabels:\n                      description: HonorLabels chooses the metric's labels on collisions\n                        with target labels.\n                      type: boolean\n                    honorTimestamps:\n                      description: HonorTimestamps controls whether Prometheus respects\n                        the timestamps present in scraped data.\n                      type: boolean\n                    interval:\n                      description: Interval at which metrics should be scraped\n                      type: string\n                    metricRelabelings:\n                      description: MetricRelabelConfigs to apply to samples before\n                        ingestion.\n                      items:\n                        description: 'RelabelConfig allows dynamic rewriting of the\n                          label set, being applied to samples before ingestion. It\n                          defines `<metric_relabel_configs>`-section of Prometheus\n                          configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs'\n                        properties:\n                          action:\n                            description: Action to perform based on regex matching.\n                              Default is 'replace'\n                            type: string\n                          modulus:\n                            description: Modulus to take of the hash of the source\n                              label values.\n                            format: int64\n                            type: integer\n                          regex:\n                            description: Regular expression against which the extracted\n                              value is matched. Default is '(.*)'\n                            type: string\n                          replacement:\n                            description: Replacement value against which a regex replace\n                              is performed if the regular expression matches. Regex\n                              capture groups are available. Default is '$1'\n                            type: string\n                          separator:\n                            description: Separator placed between concatenated source\n                              label values. default is ';'.\n                            type: string\n                          sourceLabels:\n                            description: The source labels select values from existing\n                              labels. Their content is concatenated using the configured\n                              separator and matched against the configured regular\n                              expression for the replace, keep, and drop actions.\n                            items:\n                              type: string\n                            type: array\n                          targetLabel:\n                            description: Label to which the resulting value is written\n                              in a replace action. It is mandatory for replace actions.\n                              Regex capture groups are available.\n                            type: string\n                        type: object\n                      type: array\n                    params:\n                      additionalProperties:\n                        items:\n                          type: string\n                        type: array\n                      description: Optional HTTP URL parameters\n                      type: object\n                    path:\n                      description: HTTP path to scrape for metrics.\n                      type: string\n                    port:\n                      description: Name of the service port this endpoint refers to.\n                        Mutually exclusive with targetPort.\n                      type: string\n                    proxyUrl:\n                      description: ProxyURL eg http://proxyserver:2195 Directs scrapes\n                        to proxy through this endpoint.\n                      type: string\n                    relabelings:\n                      description: 'RelabelConfigs to apply to samples before scraping.\n                        Prometheus Operator automatically adds relabelings for a few\n                        standard Kubernetes fields and replaces original scrape job\n                        name with __tmp_prometheus_job_name. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config'\n                      items:\n                        description: 'RelabelConfig allows dynamic rewriting of the\n                          label set, being applied to samples before ingestion. It\n                          defines `<metric_relabel_configs>`-section of Prometheus\n                          configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs'\n                        properties:\n                          action:\n                            description: Action to perform based on regex matching.\n                              Default is 'replace'\n                            type: string\n                          modulus:\n                            description: Modulus to take of the hash of the source\n                              label values.\n                            format: int64\n                            type: integer\n                          regex:\n                            description: Regular expression against which the extracted\n                              value is matched. Default is '(.*)'\n                            type: string\n                          replacement:\n                            description: Replacement value against which a regex replace\n                              is performed if the regular expression matches. Regex\n                              capture groups are available. Default is '$1'\n                            type: string\n                          separator:\n                            description: Separator placed between concatenated source\n                              label values. default is ';'.\n                            type: string\n                          sourceLabels:\n                            description: The source labels select values from existing\n                              labels. Their content is concatenated using the configured\n                              separator and matched against the configured regular\n                              expression for the replace, keep, and drop actions.\n                            items:\n                              type: string\n                            type: array\n                          targetLabel:\n                            description: Label to which the resulting value is written\n                              in a replace action. It is mandatory for replace actions.\n                              Regex capture groups are available.\n                            type: string\n                        type: object\n                      type: array\n                    scheme:\n                      description: HTTP scheme to use for scraping.\n                      type: string\n                    scrapeTimeout:\n                      description: Timeout after which the scrape is ended\n                      type: string\n                    targetPort:\n                      anyOf:\n                      - type: integer\n                      - type: string\n                      description: Name or number of the target port of the Pod behind\n                        the Service, the port must be specified with container port\n                        property. Mutually exclusive with port.\n                      x-kubernetes-int-or-string: true\n                    tlsConfig:\n                      description: TLS configuration to use when scraping the endpoint\n                      properties:\n                        ca:\n                          description: Struct containing the CA cert to use for the\n                            targets.\n                          properties:\n                            configMap:\n                              description: ConfigMap containing data to use for the\n                                targets.\n                              properties:\n                                key:\n                                  description: The key to select.\n                                  type: string\n                                name:\n                                  description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                    TODO: Add other useful fields. apiVersion, kind,\n                                    uid?'\n                                  type: string\n                                optional:\n                                  description: Specify whether the ConfigMap or its\n                                    key must be defined\n                                  type: boolean\n                              required:\n                              - key\n                              type: object\n                            secret:\n                              description: Secret containing data to use for the targets.\n                              properties:\n                                key:\n                                  description: The key of the secret to select from.  Must\n                                    be a valid secret key.\n                                  type: string\n                                name:\n                                  description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                    TODO: Add other useful fields. apiVersion, kind,\n                                    uid?'\n                                  type: string\n                                optional:\n                                  description: Specify whether the Secret or its key\n                                    must be defined\n                                  type: boolean\n                              required:\n                              - key\n                              type: object\n                          type: object\n                        caFile:\n                          description: Path to the CA cert in the Prometheus container\n                            to use for the targets.\n                          type: string\n                        cert:\n                          description: Struct containing the client cert file for\n                            the targets.\n                          properties:\n                            configMap:\n                              description: ConfigMap containing data to use for the\n                                targets.\n                              properties:\n                                key:\n                                  description: The key to select.\n                                  type: string\n                                name:\n                                  description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                    TODO: Add other useful fields. apiVersion, kind,\n                                    uid?'\n                                  type: string\n                                optional:\n                                  description: Specify whether the ConfigMap or its\n                                    key must be defined\n                                  type: boolean\n                              required:\n                              - key\n                              type: object\n                            secret:\n                              description: Secret containing data to use for the targets.\n                              properties:\n                                key:\n                                  description: The key of the secret to select from.  Must\n                                    be a valid secret key.\n                                  type: string\n                                name:\n                                  description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                    TODO: Add other useful fields. apiVersion, kind,\n                                    uid?'\n                                  type: string\n                                optional:\n                                  description: Specify whether the Secret or its key\n                                    must be defined\n                                  type: boolean\n                              required:\n                              - key\n                              type: object\n                          type: object\n                        certFile:\n                          description: Path to the client cert file in the Prometheus\n                            container for the targets.\n                          type: string\n                        insecureSkipVerify:\n                          description: Disable target certificate validation.\n                          type: boolean\n                        keyFile:\n                          description: Path to the client key file in the Prometheus\n                            container for the targets.\n                          type: string\n                        keySecret:\n                          description: Secret containing the client key file for the\n                            targets.\n                          properties:\n                            key:\n                              description: The key of the secret to select from.  Must\n                                be a valid secret key.\n                              type: string\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                            optional:\n                              description: Specify whether the Secret or its key must\n                                be defined\n                              type: boolean\n                          required:\n                          - key\n                          type: object\n                        serverName:\n                          description: Used to verify the hostname for the targets.\n                          type: string\n                      type: object\n                  type: object\n                type: array\n              jobLabel:\n                description: \"Chooses the label of the Kubernetes `Endpoints`. Its\n                  value will be used for the `job`-label's value of the created metrics.\n                  \\n Default & fallback value: the name of the respective Kubernetes\n                  `Endpoint`.\"\n                type: string\n              namespaceSelector:\n                description: Selector to select which namespaces the Kubernetes Endpoints\n                  objects are discovered from.\n                properties:\n                  any:\n                    description: Boolean describing whether all namespaces are selected\n                      in contrast to a list restricting them.\n                    type: boolean\n                  matchNames:\n                    description: List of namespace names.\n                    items:\n                      type: string\n                    type: array\n                type: object\n              podTargetLabels:\n                description: PodTargetLabels transfers labels on the Kubernetes `Pod`\n                  onto the created metrics.\n                items:\n                  type: string\n                type: array\n              sampleLimit:\n                description: SampleLimit defines per-scrape limit on number of scraped\n                  samples that will be accepted.\n                format: int64\n                type: integer\n              selector:\n                description: Selector to select Endpoints objects.\n                properties:\n                  matchExpressions:\n                    description: matchExpressions is a list of label selector requirements.\n                      The requirements are ANDed.\n                    items:\n                      description: A label selector requirement is a selector that\n                        contains values, a key, and an operator that relates the key\n                        and values.\n                      properties:\n                        key:\n                          description: key is the label key that the selector applies\n                            to.\n                          type: string\n                        operator:\n                          description: operator represents a key's relationship to\n                            a set of values. Valid operators are In, NotIn, Exists\n                            and DoesNotExist.\n                          type: string\n                        values:\n                          description: values is an array of string values. If the\n                            operator is In or NotIn, the values array must be non-empty.\n                            If the operator is Exists or DoesNotExist, the values\n                            array must be empty. This array is replaced during a strategic\n                            merge patch.\n                          items:\n                            type: string\n                          type: array\n                      required:\n                      - key\n                      - operator\n                      type: object\n                    type: array\n                  matchLabels:\n                    additionalProperties:\n                      type: string\n                    description: matchLabels is a map of {key,value} pairs. A single\n                      {key,value} in the matchLabels map is equivalent to an element\n                      of matchExpressions, whose key field is \"key\", the operator\n                      is \"In\", and the values array contains only \"value\". The requirements\n                      are ANDed.\n                    type: object\n                type: object\n              targetLabels:\n                description: TargetLabels transfers labels from the Kubernetes `Service`\n                  onto the created metrics. All labels set in `selector.matchLabels`\n                  are automatically transferred.\n                items:\n                  type: string\n                type: array\n              targetLimit:\n                description: TargetLimit defines a limit on the number of scraped\n                  targets that will be accepted.\n                format: int64\n                type: integer\n            required:\n            - endpoints\n            - selector\n            type: object\n        required:\n        - spec\n        type: object\n    served: true\n    storage: true\nstatus:\n  acceptedNames:\n    kind: \"\"\n    plural: \"\"\n  conditions: []\n  storedVersions: []\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/crds/crd-thanosrulers.yaml",
    "content": "# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml\n\n---\napiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.4.1\n  creationTimestamp: null\n  name: thanosrulers.monitoring.coreos.com\nspec:\n  group: monitoring.coreos.com\n  names:\n    categories:\n    - prometheus-operator\n    kind: ThanosRuler\n    listKind: ThanosRulerList\n    plural: thanosrulers\n    singular: thanosruler\n  scope: Namespaced\n  versions:\n  - name: v1\n    schema:\n      openAPIV3Schema:\n        description: ThanosRuler defines a ThanosRuler deployment.\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: 'Specification of the desired behavior of the ThanosRuler\n              cluster. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status'\n            properties:\n              affinity:\n                description: If specified, the pod's scheduling constraints.\n                properties:\n                  nodeAffinity:\n                    description: Describes node affinity scheduling rules for the\n                      pod.\n                    properties:\n                      preferredDuringSchedulingIgnoredDuringExecution:\n                        description: The scheduler will prefer to schedule pods to\n                          nodes that satisfy the affinity expressions specified by\n                          this field, but it may choose a node that violates one or\n                          more of the expressions. The node that is most preferred\n                          is the one with the greatest sum of weights, i.e. for each\n                          node that meets all of the scheduling requirements (resource\n                          request, requiredDuringScheduling affinity expressions,\n                          etc.), compute a sum by iterating through the elements of\n                          this field and adding \"weight\" to the sum if the node matches\n                          the corresponding matchExpressions; the node(s) with the\n                          highest sum are the most preferred.\n                        items:\n                          description: An empty preferred scheduling term matches\n                            all objects with implicit weight 0 (i.e. it's a no-op).\n                            A null preferred scheduling term matches no objects (i.e.\n                            is also a no-op).\n                          properties:\n                            preference:\n                              description: A node selector term, associated with the\n                                corresponding weight.\n                              properties:\n                                matchExpressions:\n                                  description: A list of node selector requirements\n                                    by node's labels.\n                                  items:\n                                    description: A node selector requirement is a\n                                      selector that contains values, a key, and an\n                                      operator that relates the key and values.\n                                    properties:\n                                      key:\n                                        description: The label key that the selector\n                                          applies to.\n                                        type: string\n                                      operator:\n                                        description: Represents a key's relationship\n                                          to a set of values. Valid operators are\n                                          In, NotIn, Exists, DoesNotExist. Gt, and\n                                          Lt.\n                                        type: string\n                                      values:\n                                        description: An array of string values. If\n                                          the operator is In or NotIn, the values\n                                          array must be non-empty. If the operator\n                                          is Exists or DoesNotExist, the values array\n                                          must be empty. If the operator is Gt or\n                                          Lt, the values array must have a single\n                                          element, which will be interpreted as an\n                                          integer. This array is replaced during a\n                                          strategic merge patch.\n                                        items:\n                                          type: string\n                                        type: array\n                                    required:\n                                    - key\n                                    - operator\n                                    type: object\n                                  type: array\n                                matchFields:\n                                  description: A list of node selector requirements\n                                    by node's fields.\n                                  items:\n                                    description: A node selector requirement is a\n                                      selector that contains values, a key, and an\n                                      operator that relates the key and values.\n                                    properties:\n                                      key:\n                                        description: The label key that the selector\n                                          applies to.\n                                        type: string\n                                      operator:\n                                        description: Represents a key's relationship\n                                          to a set of values. Valid operators are\n                                          In, NotIn, Exists, DoesNotExist. Gt, and\n                                          Lt.\n                                        type: string\n                                      values:\n                                        description: An array of string values. If\n                                          the operator is In or NotIn, the values\n                                          array must be non-empty. If the operator\n                                          is Exists or DoesNotExist, the values array\n                                          must be empty. If the operator is Gt or\n                                          Lt, the values array must have a single\n                                          element, which will be interpreted as an\n                                          integer. This array is replaced during a\n                                          strategic merge patch.\n                                        items:\n                                          type: string\n                                        type: array\n                                    required:\n                                    - key\n                                    - operator\n                                    type: object\n                                  type: array\n                              type: object\n                            weight:\n                              description: Weight associated with matching the corresponding\n                                nodeSelectorTerm, in the range 1-100.\n                              format: int32\n                              type: integer\n                          required:\n                          - preference\n                          - weight\n                          type: object\n                        type: array\n                      requiredDuringSchedulingIgnoredDuringExecution:\n                        description: If the affinity requirements specified by this\n                          field are not met at scheduling time, the pod will not be\n                          scheduled onto the node. If the affinity requirements specified\n                          by this field cease to be met at some point during pod execution\n                          (e.g. due to an update), the system may or may not try to\n                          eventually evict the pod from its node.\n                        properties:\n                          nodeSelectorTerms:\n                            description: Required. A list of node selector terms.\n                              The terms are ORed.\n                            items:\n                              description: A null or empty node selector term matches\n                                no objects. The requirements of them are ANDed. The\n                                TopologySelectorTerm type implements a subset of the\n                                NodeSelectorTerm.\n                              properties:\n                                matchExpressions:\n                                  description: A list of node selector requirements\n                                    by node's labels.\n                                  items:\n                                    description: A node selector requirement is a\n                                      selector that contains values, a key, and an\n                                      operator that relates the key and values.\n                                    properties:\n                                      key:\n                                        description: The label key that the selector\n                                          applies to.\n                                        type: string\n                                      operator:\n                                        description: Represents a key's relationship\n                                          to a set of values. Valid operators are\n                                          In, NotIn, Exists, DoesNotExist. Gt, and\n                                          Lt.\n                                        type: string\n                                      values:\n                                        description: An array of string values. If\n                                          the operator is In or NotIn, the values\n                                          array must be non-empty. If the operator\n                                          is Exists or DoesNotExist, the values array\n                                          must be empty. If the operator is Gt or\n                                          Lt, the values array must have a single\n                                          element, which will be interpreted as an\n                                          integer. This array is replaced during a\n                                          strategic merge patch.\n                                        items:\n                                          type: string\n                                        type: array\n                                    required:\n                                    - key\n                                    - operator\n                                    type: object\n                                  type: array\n                                matchFields:\n                                  description: A list of node selector requirements\n                                    by node's fields.\n                                  items:\n                                    description: A node selector requirement is a\n                                      selector that contains values, a key, and an\n                                      operator that relates the key and values.\n                                    properties:\n                                      key:\n                                        description: The label key that the selector\n                                          applies to.\n                                        type: string\n                                      operator:\n                                        description: Represents a key's relationship\n                                          to a set of values. Valid operators are\n                                          In, NotIn, Exists, DoesNotExist. Gt, and\n                                          Lt.\n                                        type: string\n                                      values:\n                                        description: An array of string values. If\n                                          the operator is In or NotIn, the values\n                                          array must be non-empty. If the operator\n                                          is Exists or DoesNotExist, the values array\n                                          must be empty. If the operator is Gt or\n                                          Lt, the values array must have a single\n                                          element, which will be interpreted as an\n                                          integer. This array is replaced during a\n                                          strategic merge patch.\n                                        items:\n                                          type: string\n                                        type: array\n                                    required:\n                                    - key\n                                    - operator\n                                    type: object\n                                  type: array\n                              type: object\n                            type: array\n                        required:\n                        - nodeSelectorTerms\n                        type: object\n                    type: object\n                  podAffinity:\n                    description: Describes pod affinity scheduling rules (e.g. co-locate\n                      this pod in the same node, zone, etc. as some other pod(s)).\n                    properties:\n                      preferredDuringSchedulingIgnoredDuringExecution:\n                        description: The scheduler will prefer to schedule pods to\n                          nodes that satisfy the affinity expressions specified by\n                          this field, but it may choose a node that violates one or\n                          more of the expressions. The node that is most preferred\n                          is the one with the greatest sum of weights, i.e. for each\n                          node that meets all of the scheduling requirements (resource\n                          request, requiredDuringScheduling affinity expressions,\n                          etc.), compute a sum by iterating through the elements of\n                          this field and adding \"weight\" to the sum if the node has\n                          pods which matches the corresponding podAffinityTerm; the\n                          node(s) with the highest sum are the most preferred.\n                        items:\n                          description: The weights of all of the matched WeightedPodAffinityTerm\n                            fields are added per-node to find the most preferred node(s)\n                          properties:\n                            podAffinityTerm:\n                              description: Required. A pod affinity term, associated\n                                with the corresponding weight.\n                              properties:\n                                labelSelector:\n                                  description: A label query over a set of resources,\n                                    in this case pods.\n                                  properties:\n                                    matchExpressions:\n                                      description: matchExpressions is a list of label\n                                        selector requirements. The requirements are\n                                        ANDed.\n                                      items:\n                                        description: A label selector requirement\n                                          is a selector that contains values, a key,\n                                          and an operator that relates the key and\n                                          values.\n                                        properties:\n                                          key:\n                                            description: key is the label key that\n                                              the selector applies to.\n                                            type: string\n                                          operator:\n                                            description: operator represents a key's\n                                              relationship to a set of values. Valid\n                                              operators are In, NotIn, Exists and\n                                              DoesNotExist.\n                                            type: string\n                                          values:\n                                            description: values is an array of string\n                                              values. If the operator is In or NotIn,\n                                              the values array must be non-empty.\n                                              If the operator is Exists or DoesNotExist,\n                                              the values array must be empty. This\n                                              array is replaced during a strategic\n                                              merge patch.\n                                            items:\n                                              type: string\n                                            type: array\n                                        required:\n                                        - key\n                                        - operator\n                                        type: object\n                                      type: array\n                                    matchLabels:\n                                      additionalProperties:\n                                        type: string\n                                      description: matchLabels is a map of {key,value}\n                                        pairs. A single {key,value} in the matchLabels\n                                        map is equivalent to an element of matchExpressions,\n                                        whose key field is \"key\", the operator is\n                                        \"In\", and the values array contains only \"value\".\n                                        The requirements are ANDed.\n                                      type: object\n                                  type: object\n                                namespaces:\n                                  description: namespaces specifies which namespaces\n                                    the labelSelector applies to (matches against);\n                                    null or empty list means \"this pod's namespace\"\n                                  items:\n                                    type: string\n                                  type: array\n                                topologyKey:\n                                  description: This pod should be co-located (affinity)\n                                    or not co-located (anti-affinity) with the pods\n                                    matching the labelSelector in the specified namespaces,\n                                    where co-located is defined as running on a node\n                                    whose value of the label with key topologyKey\n                                    matches that of any node on which any of the selected\n                                    pods is running. Empty topologyKey is not allowed.\n                                  type: string\n                              required:\n                              - topologyKey\n                              type: object\n                            weight:\n                              description: weight associated with matching the corresponding\n                                podAffinityTerm, in the range 1-100.\n                              format: int32\n                              type: integer\n                          required:\n                          - podAffinityTerm\n                          - weight\n                          type: object\n                        type: array\n                      requiredDuringSchedulingIgnoredDuringExecution:\n                        description: If the affinity requirements specified by this\n                          field are not met at scheduling time, the pod will not be\n                          scheduled onto the node. If the affinity requirements specified\n                          by this field cease to be met at some point during pod execution\n                          (e.g. due to a pod label update), the system may or may\n                          not try to eventually evict the pod from its node. When\n                          there are multiple elements, the lists of nodes corresponding\n                          to each podAffinityTerm are intersected, i.e. all terms\n                          must be satisfied.\n                        items:\n                          description: Defines a set of pods (namely those matching\n                            the labelSelector relative to the given namespace(s))\n                            that this pod should be co-located (affinity) or not co-located\n                            (anti-affinity) with, where co-located is defined as running\n                            on a node whose value of the label with key <topologyKey>\n                            matches that of any node on which a pod of the set of\n                            pods is running\n                          properties:\n                            labelSelector:\n                              description: A label query over a set of resources,\n                                in this case pods.\n                              properties:\n                                matchExpressions:\n                                  description: matchExpressions is a list of label\n                                    selector requirements. The requirements are ANDed.\n                                  items:\n                                    description: A label selector requirement is a\n                                      selector that contains values, a key, and an\n                                      operator that relates the key and values.\n                                    properties:\n                                      key:\n                                        description: key is the label key that the\n                                          selector applies to.\n                                        type: string\n                                      operator:\n                                        description: operator represents a key's relationship\n                                          to a set of values. Valid operators are\n                                          In, NotIn, Exists and DoesNotExist.\n                                        type: string\n                                      values:\n                                        description: values is an array of string\n                                          values. If the operator is In or NotIn,\n                                          the values array must be non-empty. If the\n                                          operator is Exists or DoesNotExist, the\n                                          values array must be empty. This array is\n                                          replaced during a strategic merge patch.\n                                        items:\n                                          type: string\n                                        type: array\n                                    required:\n                                    - key\n                                    - operator\n                                    type: object\n                                  type: array\n                                matchLabels:\n                                  additionalProperties:\n                                    type: string\n                                  description: matchLabels is a map of {key,value}\n                                    pairs. A single {key,value} in the matchLabels\n                                    map is equivalent to an element of matchExpressions,\n                                    whose key field is \"key\", the operator is \"In\",\n                                    and the values array contains only \"value\". The\n                                    requirements are ANDed.\n                                  type: object\n                              type: object\n                            namespaces:\n                              description: namespaces specifies which namespaces the\n                                labelSelector applies to (matches against); null or\n                                empty list means \"this pod's namespace\"\n                              items:\n                                type: string\n                              type: array\n                            topologyKey:\n                              description: This pod should be co-located (affinity)\n                                or not co-located (anti-affinity) with the pods matching\n                                the labelSelector in the specified namespaces, where\n                                co-located is defined as running on a node whose value\n                                of the label with key topologyKey matches that of\n                                any node on which any of the selected pods is running.\n                                Empty topologyKey is not allowed.\n                              type: string\n                          required:\n                          - topologyKey\n                          type: object\n                        type: array\n                    type: object\n                  podAntiAffinity:\n                    description: Describes pod anti-affinity scheduling rules (e.g.\n                      avoid putting this pod in the same node, zone, etc. as some\n                      other pod(s)).\n                    properties:\n                      preferredDuringSchedulingIgnoredDuringExecution:\n                        description: The scheduler will prefer to schedule pods to\n                          nodes that satisfy the anti-affinity expressions specified\n                          by this field, but it may choose a node that violates one\n                          or more of the expressions. The node that is most preferred\n                          is the one with the greatest sum of weights, i.e. for each\n                          node that meets all of the scheduling requirements (resource\n                          request, requiredDuringScheduling anti-affinity expressions,\n                          etc.), compute a sum by iterating through the elements of\n                          this field and adding \"weight\" to the sum if the node has\n                          pods which matches the corresponding podAffinityTerm; the\n                          node(s) with the highest sum are the most preferred.\n                        items:\n                          description: The weights of all of the matched WeightedPodAffinityTerm\n                            fields are added per-node to find the most preferred node(s)\n                          properties:\n                            podAffinityTerm:\n                              description: Required. A pod affinity term, associated\n                                with the corresponding weight.\n                              properties:\n                                labelSelector:\n                                  description: A label query over a set of resources,\n                                    in this case pods.\n                                  properties:\n                                    matchExpressions:\n                                      description: matchExpressions is a list of label\n                                        selector requirements. The requirements are\n                                        ANDed.\n                                      items:\n                                        description: A label selector requirement\n                                          is a selector that contains values, a key,\n                                          and an operator that relates the key and\n                                          values.\n                                        properties:\n                                          key:\n                                            description: key is the label key that\n                                              the selector applies to.\n                                            type: string\n                                          operator:\n                                            description: operator represents a key's\n                                              relationship to a set of values. Valid\n                                              operators are In, NotIn, Exists and\n                                              DoesNotExist.\n                                            type: string\n                                          values:\n                                            description: values is an array of string\n                                              values. If the operator is In or NotIn,\n                                              the values array must be non-empty.\n                                              If the operator is Exists or DoesNotExist,\n                                              the values array must be empty. This\n                                              array is replaced during a strategic\n                                              merge patch.\n                                            items:\n                                              type: string\n                                            type: array\n                                        required:\n                                        - key\n                                        - operator\n                                        type: object\n                                      type: array\n                                    matchLabels:\n                                      additionalProperties:\n                                        type: string\n                                      description: matchLabels is a map of {key,value}\n                                        pairs. A single {key,value} in the matchLabels\n                                        map is equivalent to an element of matchExpressions,\n                                        whose key field is \"key\", the operator is\n                                        \"In\", and the values array contains only \"value\".\n                                        The requirements are ANDed.\n                                      type: object\n                                  type: object\n                                namespaces:\n                                  description: namespaces specifies which namespaces\n                                    the labelSelector applies to (matches against);\n                                    null or empty list means \"this pod's namespace\"\n                                  items:\n                                    type: string\n                                  type: array\n                                topologyKey:\n                                  description: This pod should be co-located (affinity)\n                                    or not co-located (anti-affinity) with the pods\n                                    matching the labelSelector in the specified namespaces,\n                                    where co-located is defined as running on a node\n                                    whose value of the label with key topologyKey\n                                    matches that of any node on which any of the selected\n                                    pods is running. Empty topologyKey is not allowed.\n                                  type: string\n                              required:\n                              - topologyKey\n                              type: object\n                            weight:\n                              description: weight associated with matching the corresponding\n                                podAffinityTerm, in the range 1-100.\n                              format: int32\n                              type: integer\n                          required:\n                          - podAffinityTerm\n                          - weight\n                          type: object\n                        type: array\n                      requiredDuringSchedulingIgnoredDuringExecution:\n                        description: If the anti-affinity requirements specified by\n                          this field are not met at scheduling time, the pod will\n                          not be scheduled onto the node. If the anti-affinity requirements\n                          specified by this field cease to be met at some point during\n                          pod execution (e.g. due to a pod label update), the system\n                          may or may not try to eventually evict the pod from its\n                          node. When there are multiple elements, the lists of nodes\n                          corresponding to each podAffinityTerm are intersected, i.e.\n                          all terms must be satisfied.\n                        items:\n                          description: Defines a set of pods (namely those matching\n                            the labelSelector relative to the given namespace(s))\n                            that this pod should be co-located (affinity) or not co-located\n                            (anti-affinity) with, where co-located is defined as running\n                            on a node whose value of the label with key <topologyKey>\n                            matches that of any node on which a pod of the set of\n                            pods is running\n                          properties:\n                            labelSelector:\n                              description: A label query over a set of resources,\n                                in this case pods.\n                              properties:\n                                matchExpressions:\n                                  description: matchExpressions is a list of label\n                                    selector requirements. The requirements are ANDed.\n                                  items:\n                                    description: A label selector requirement is a\n                                      selector that contains values, a key, and an\n                                      operator that relates the key and values.\n                                    properties:\n                                      key:\n                                        description: key is the label key that the\n                                          selector applies to.\n                                        type: string\n                                      operator:\n                                        description: operator represents a key's relationship\n                                          to a set of values. Valid operators are\n                                          In, NotIn, Exists and DoesNotExist.\n                                        type: string\n                                      values:\n                                        description: values is an array of string\n                                          values. If the operator is In or NotIn,\n                                          the values array must be non-empty. If the\n                                          operator is Exists or DoesNotExist, the\n                                          values array must be empty. This array is\n                                          replaced during a strategic merge patch.\n                                        items:\n                                          type: string\n                                        type: array\n                                    required:\n                                    - key\n                                    - operator\n                                    type: object\n                                  type: array\n                                matchLabels:\n                                  additionalProperties:\n                                    type: string\n                                  description: matchLabels is a map of {key,value}\n                                    pairs. A single {key,value} in the matchLabels\n                                    map is equivalent to an element of matchExpressions,\n                                    whose key field is \"key\", the operator is \"In\",\n                                    and the values array contains only \"value\". The\n                                    requirements are ANDed.\n                                  type: object\n                              type: object\n                            namespaces:\n                              description: namespaces specifies which namespaces the\n                                labelSelector applies to (matches against); null or\n                                empty list means \"this pod's namespace\"\n                              items:\n                                type: string\n                              type: array\n                            topologyKey:\n                              description: This pod should be co-located (affinity)\n                                or not co-located (anti-affinity) with the pods matching\n                                the labelSelector in the specified namespaces, where\n                                co-located is defined as running on a node whose value\n                                of the label with key topologyKey matches that of\n                                any node on which any of the selected pods is running.\n                                Empty topologyKey is not allowed.\n                              type: string\n                          required:\n                          - topologyKey\n                          type: object\n                        type: array\n                    type: object\n                type: object\n              alertDropLabels:\n                description: AlertDropLabels configure the label names which should\n                  be dropped in ThanosRuler alerts. If `labels` field is not provided,\n                  `thanos_ruler_replica` will be dropped in alerts by default.\n                items:\n                  type: string\n                type: array\n              alertQueryUrl:\n                description: The external Query URL the Thanos Ruler will set in the\n                  'Source' field of all alerts. Maps to the '--alert.query-url' CLI\n                  arg.\n                type: string\n              alertmanagersConfig:\n                description: Define configuration for connecting to alertmanager.  Only\n                  available with thanos v0.10.0 and higher.  Maps to the `alertmanagers.config`\n                  arg.\n                properties:\n                  key:\n                    description: The key of the secret to select from.  Must be a\n                      valid secret key.\n                    type: string\n                  name:\n                    description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                      TODO: Add other useful fields. apiVersion, kind, uid?'\n                    type: string\n                  optional:\n                    description: Specify whether the Secret or its key must be defined\n                    type: boolean\n                required:\n                - key\n                type: object\n              alertmanagersUrl:\n                description: 'Define URLs to send alerts to Alertmanager.  For Thanos\n                  v0.10.0 and higher, AlertManagersConfig should be used instead.  Note:\n                  this field will be ignored if AlertManagersConfig is specified.\n                  Maps to the `alertmanagers.url` arg.'\n                items:\n                  type: string\n                type: array\n              containers:\n                description: 'Containers allows injecting additional containers or\n                  modifying operator generated containers. This can be used to allow\n                  adding an authentication proxy to a ThanosRuler pod or to change\n                  the behavior of an operator generated container. Containers described\n                  here modify an operator generated container if they share the same\n                  name and modifications are done via a strategic merge patch. The\n                  current container names are: `thanos-ruler` and `config-reloader`.\n                  Overriding containers is entirely outside the scope of what the\n                  maintainers will support and by doing so, you accept that this behaviour\n                  may break at any time without notice.'\n                items:\n                  description: A single application container that you want to run\n                    within a pod.\n                  properties:\n                    args:\n                      description: 'Arguments to the entrypoint. The docker image''s\n                        CMD is used if this is not provided. Variable references $(VAR_NAME)\n                        are expanded using the container''s environment. If a variable\n                        cannot be resolved, the reference in the input string will\n                        be unchanged. The $(VAR_NAME) syntax can be escaped with a\n                        double $$, ie: $$(VAR_NAME). Escaped references will never\n                        be expanded, regardless of whether the variable exists or\n                        not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell'\n                      items:\n                        type: string\n                      type: array\n                    command:\n                      description: 'Entrypoint array. Not executed within a shell.\n                        The docker image''s ENTRYPOINT is used if this is not provided.\n                        Variable references $(VAR_NAME) are expanded using the container''s\n                        environment. If a variable cannot be resolved, the reference\n                        in the input string will be unchanged. The $(VAR_NAME) syntax\n                        can be escaped with a double $$, ie: $$(VAR_NAME). Escaped\n                        references will never be expanded, regardless of whether the\n                        variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell'\n                      items:\n                        type: string\n                      type: array\n                    env:\n                      description: List of environment variables to set in the container.\n                        Cannot be updated.\n                      items:\n                        description: EnvVar represents an environment variable present\n                          in a Container.\n                        properties:\n                          name:\n                            description: Name of the environment variable. Must be\n                              a C_IDENTIFIER.\n                            type: string\n                          value:\n                            description: 'Variable references $(VAR_NAME) are expanded\n                              using the previous defined environment variables in\n                              the container and any service environment variables.\n                              If a variable cannot be resolved, the reference in the\n                              input string will be unchanged. The $(VAR_NAME) syntax\n                              can be escaped with a double $$, ie: $$(VAR_NAME). Escaped\n                              references will never be expanded, regardless of whether\n                              the variable exists or not. Defaults to \"\".'\n                            type: string\n                          valueFrom:\n                            description: Source for the environment variable's value.\n                              Cannot be used if value is not empty.\n                            properties:\n                              configMapKeyRef:\n                                description: Selects a key of a ConfigMap.\n                                properties:\n                                  key:\n                                    description: The key to select.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the ConfigMap or\n                                      its key must be defined\n                                    type: boolean\n                                required:\n                                - key\n                                type: object\n                              fieldRef:\n                                description: 'Selects a field of the pod: supports\n                                  metadata.name, metadata.namespace, metadata.labels,\n                                  metadata.annotations, spec.nodeName, spec.serviceAccountName,\n                                  status.hostIP, status.podIP, status.podIPs.'\n                                properties:\n                                  apiVersion:\n                                    description: Version of the schema the FieldPath\n                                      is written in terms of, defaults to \"v1\".\n                                    type: string\n                                  fieldPath:\n                                    description: Path of the field to select in the\n                                      specified API version.\n                                    type: string\n                                required:\n                                - fieldPath\n                                type: object\n                              resourceFieldRef:\n                                description: 'Selects a resource of the container:\n                                  only resources limits and requests (limits.cpu,\n                                  limits.memory, limits.ephemeral-storage, requests.cpu,\n                                  requests.memory and requests.ephemeral-storage)\n                                  are currently supported.'\n                                properties:\n                                  containerName:\n                                    description: 'Container name: required for volumes,\n                                      optional for env vars'\n                                    type: string\n                                  divisor:\n                                    anyOf:\n                                    - type: integer\n                                    - type: string\n                                    description: Specifies the output format of the\n                                      exposed resources, defaults to \"1\"\n                                    pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                    x-kubernetes-int-or-string: true\n                                  resource:\n                                    description: 'Required: resource to select'\n                                    type: string\n                                required:\n                                - resource\n                                type: object\n                              secretKeyRef:\n                                description: Selects a key of a secret in the pod's\n                                  namespace\n                                properties:\n                                  key:\n                                    description: The key of the secret to select from.  Must\n                                      be a valid secret key.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the Secret or its\n                                      key must be defined\n                                    type: boolean\n                                required:\n                                - key\n                                type: object\n                            type: object\n                        required:\n                        - name\n                        type: object\n                      type: array\n                    envFrom:\n                      description: List of sources to populate environment variables\n                        in the container. The keys defined within a source must be\n                        a C_IDENTIFIER. All invalid keys will be reported as an event\n                        when the container is starting. When a key exists in multiple\n                        sources, the value associated with the last source will take\n                        precedence. Values defined by an Env with a duplicate key\n                        will take precedence. Cannot be updated.\n                      items:\n                        description: EnvFromSource represents the source of a set\n                          of ConfigMaps\n                        properties:\n                          configMapRef:\n                            description: The ConfigMap to select from\n                            properties:\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the ConfigMap must be\n                                  defined\n                                type: boolean\n                            type: object\n                          prefix:\n                            description: An optional identifier to prepend to each\n                              key in the ConfigMap. Must be a C_IDENTIFIER.\n                            type: string\n                          secretRef:\n                            description: The Secret to select from\n                            properties:\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret must be defined\n                                type: boolean\n                            type: object\n                        type: object\n                      type: array\n                    image:\n                      description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images\n                        This field is optional to allow higher level config management\n                        to default or override container images in workload controllers\n                        like Deployments and StatefulSets.'\n                      type: string\n                    imagePullPolicy:\n                      description: 'Image pull policy. One of Always, Never, IfNotPresent.\n                        Defaults to Always if :latest tag is specified, or IfNotPresent\n                        otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images'\n                      type: string\n                    lifecycle:\n                      description: Actions that the management system should take\n                        in response to container lifecycle events. Cannot be updated.\n                      properties:\n                        postStart:\n                          description: 'PostStart is called immediately after a container\n                            is created. If the handler fails, the container is terminated\n                            and restarted according to its restart policy. Other management\n                            of the container blocks until the hook completes. More\n                            info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks'\n                          properties:\n                            exec:\n                              description: One and only one of the following should\n                                be specified. Exec specifies the action to take.\n                              properties:\n                                command:\n                                  description: Command is the command line to execute\n                                    inside the container, the working directory for\n                                    the command  is root ('/') in the container's\n                                    filesystem. The command is simply exec'd, it is\n                                    not run inside a shell, so traditional shell instructions\n                                    ('|', etc) won't work. To use a shell, you need\n                                    to explicitly call out to that shell. Exit status\n                                    of 0 is treated as live/healthy and non-zero is\n                                    unhealthy.\n                                  items:\n                                    type: string\n                                  type: array\n                              type: object\n                            httpGet:\n                              description: HTTPGet specifies the http request to perform.\n                              properties:\n                                host:\n                                  description: Host name to connect to, defaults to\n                                    the pod IP. You probably want to set \"Host\" in\n                                    httpHeaders instead.\n                                  type: string\n                                httpHeaders:\n                                  description: Custom headers to set in the request.\n                                    HTTP allows repeated headers.\n                                  items:\n                                    description: HTTPHeader describes a custom header\n                                      to be used in HTTP probes\n                                    properties:\n                                      name:\n                                        description: The header field name\n                                        type: string\n                                      value:\n                                        description: The header field value\n                                        type: string\n                                    required:\n                                    - name\n                                    - value\n                                    type: object\n                                  type: array\n                                path:\n                                  description: Path to access on the HTTP server.\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Name or number of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                                scheme:\n                                  description: Scheme to use for connecting to the\n                                    host. Defaults to HTTP.\n                                  type: string\n                              required:\n                              - port\n                              type: object\n                            tcpSocket:\n                              description: 'TCPSocket specifies an action involving\n                                a TCP port. TCP hooks not yet supported TODO: implement\n                                a realistic TCP lifecycle hook'\n                              properties:\n                                host:\n                                  description: 'Optional: Host name to connect to,\n                                    defaults to the pod IP.'\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Number or name of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                              required:\n                              - port\n                              type: object\n                          type: object\n                        preStop:\n                          description: 'PreStop is called immediately before a container\n                            is terminated due to an API request or management event\n                            such as liveness/startup probe failure, preemption, resource\n                            contention, etc. The handler is not called if the container\n                            crashes or exits. The reason for termination is passed\n                            to the handler. The Pod''s termination grace period countdown\n                            begins before the PreStop hooked is executed. Regardless\n                            of the outcome of the handler, the container will eventually\n                            terminate within the Pod''s termination grace period.\n                            Other management of the container blocks until the hook\n                            completes or until the termination grace period is reached.\n                            More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks'\n                          properties:\n                            exec:\n                              description: One and only one of the following should\n                                be specified. Exec specifies the action to take.\n                              properties:\n                                command:\n                                  description: Command is the command line to execute\n                                    inside the container, the working directory for\n                                    the command  is root ('/') in the container's\n                                    filesystem. The command is simply exec'd, it is\n                                    not run inside a shell, so traditional shell instructions\n                                    ('|', etc) won't work. To use a shell, you need\n                                    to explicitly call out to that shell. Exit status\n                                    of 0 is treated as live/healthy and non-zero is\n                                    unhealthy.\n                                  items:\n                                    type: string\n                                  type: array\n                              type: object\n                            httpGet:\n                              description: HTTPGet specifies the http request to perform.\n                              properties:\n                                host:\n                                  description: Host name to connect to, defaults to\n                                    the pod IP. You probably want to set \"Host\" in\n                                    httpHeaders instead.\n                                  type: string\n                                httpHeaders:\n                                  description: Custom headers to set in the request.\n                                    HTTP allows repeated headers.\n                                  items:\n                                    description: HTTPHeader describes a custom header\n                                      to be used in HTTP probes\n                                    properties:\n                                      name:\n                                        description: The header field name\n                                        type: string\n                                      value:\n                                        description: The header field value\n                                        type: string\n                                    required:\n                                    - name\n                                    - value\n                                    type: object\n                                  type: array\n                                path:\n                                  description: Path to access on the HTTP server.\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Name or number of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                                scheme:\n                                  description: Scheme to use for connecting to the\n                                    host. Defaults to HTTP.\n                                  type: string\n                              required:\n                              - port\n                              type: object\n                            tcpSocket:\n                              description: 'TCPSocket specifies an action involving\n                                a TCP port. TCP hooks not yet supported TODO: implement\n                                a realistic TCP lifecycle hook'\n                              properties:\n                                host:\n                                  description: 'Optional: Host name to connect to,\n                                    defaults to the pod IP.'\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Number or name of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                              required:\n                              - port\n                              type: object\n                          type: object\n                      type: object\n                    livenessProbe:\n                      description: 'Periodic probe of container liveness. Container\n                        will be restarted if the probe fails. Cannot be updated. More\n                        info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                      properties:\n                        exec:\n                          description: One and only one of the following should be\n                            specified. Exec specifies the action to take.\n                          properties:\n                            command:\n                              description: Command is the command line to execute\n                                inside the container, the working directory for the\n                                command  is root ('/') in the container's filesystem.\n                                The command is simply exec'd, it is not run inside\n                                a shell, so traditional shell instructions ('|', etc)\n                                won't work. To use a shell, you need to explicitly\n                                call out to that shell. Exit status of 0 is treated\n                                as live/healthy and non-zero is unhealthy.\n                              items:\n                                type: string\n                              type: array\n                          type: object\n                        failureThreshold:\n                          description: Minimum consecutive failures for the probe\n                            to be considered failed after having succeeded. Defaults\n                            to 3. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        httpGet:\n                          description: HTTPGet specifies the http request to perform.\n                          properties:\n                            host:\n                              description: Host name to connect to, defaults to the\n                                pod IP. You probably want to set \"Host\" in httpHeaders\n                                instead.\n                              type: string\n                            httpHeaders:\n                              description: Custom headers to set in the request. HTTP\n                                allows repeated headers.\n                              items:\n                                description: HTTPHeader describes a custom header\n                                  to be used in HTTP probes\n                                properties:\n                                  name:\n                                    description: The header field name\n                                    type: string\n                                  value:\n                                    description: The header field value\n                                    type: string\n                                required:\n                                - name\n                                - value\n                                type: object\n                              type: array\n                            path:\n                              description: Path to access on the HTTP server.\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Name or number of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                            scheme:\n                              description: Scheme to use for connecting to the host.\n                                Defaults to HTTP.\n                              type: string\n                          required:\n                          - port\n                          type: object\n                        initialDelaySeconds:\n                          description: 'Number of seconds after the container has\n                            started before liveness probes are initiated. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                        periodSeconds:\n                          description: How often (in seconds) to perform the probe.\n                            Default to 10 seconds. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        successThreshold:\n                          description: Minimum consecutive successes for the probe\n                            to be considered successful after having failed. Defaults\n                            to 1. Must be 1 for liveness and startup. Minimum value\n                            is 1.\n                          format: int32\n                          type: integer\n                        tcpSocket:\n                          description: 'TCPSocket specifies an action involving a\n                            TCP port. TCP hooks not yet supported TODO: implement\n                            a realistic TCP lifecycle hook'\n                          properties:\n                            host:\n                              description: 'Optional: Host name to connect to, defaults\n                                to the pod IP.'\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Number or name of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                          required:\n                          - port\n                          type: object\n                        timeoutSeconds:\n                          description: 'Number of seconds after which the probe times\n                            out. Defaults to 1 second. Minimum value is 1. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                      type: object\n                    name:\n                      description: Name of the container specified as a DNS_LABEL.\n                        Each container in a pod must have a unique name (DNS_LABEL).\n                        Cannot be updated.\n                      type: string\n                    ports:\n                      description: List of ports to expose from the container. Exposing\n                        a port here gives the system additional information about\n                        the network connections a container uses, but is primarily\n                        informational. Not specifying a port here DOES NOT prevent\n                        that port from being exposed. Any port which is listening\n                        on the default \"0.0.0.0\" address inside a container will be\n                        accessible from the network. Cannot be updated.\n                      items:\n                        description: ContainerPort represents a network port in a\n                          single container.\n                        properties:\n                          containerPort:\n                            description: Number of port to expose on the pod's IP\n                              address. This must be a valid port number, 0 < x < 65536.\n                            format: int32\n                            type: integer\n                          hostIP:\n                            description: What host IP to bind the external port to.\n                            type: string\n                          hostPort:\n                            description: Number of port to expose on the host. If\n                              specified, this must be a valid port number, 0 < x <\n                              65536. If HostNetwork is specified, this must match\n                              ContainerPort. Most containers do not need this.\n                            format: int32\n                            type: integer\n                          name:\n                            description: If specified, this must be an IANA_SVC_NAME\n                              and unique within the pod. Each named port in a pod\n                              must have a unique name. Name for the port that can\n                              be referred to by services.\n                            type: string\n                          protocol:\n                            default: TCP\n                            description: Protocol for port. Must be UDP, TCP, or SCTP.\n                              Defaults to \"TCP\".\n                            type: string\n                        required:\n                        - containerPort\n                        type: object\n                      type: array\n                      x-kubernetes-list-map-keys:\n                      - containerPort\n                      - protocol\n                      x-kubernetes-list-type: map\n                    readinessProbe:\n                      description: 'Periodic probe of container service readiness.\n                        Container will be removed from service endpoints if the probe\n                        fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                      properties:\n                        exec:\n                          description: One and only one of the following should be\n                            specified. Exec specifies the action to take.\n                          properties:\n                            command:\n                              description: Command is the command line to execute\n                                inside the container, the working directory for the\n                                command  is root ('/') in the container's filesystem.\n                                The command is simply exec'd, it is not run inside\n                                a shell, so traditional shell instructions ('|', etc)\n                                won't work. To use a shell, you need to explicitly\n                                call out to that shell. Exit status of 0 is treated\n                                as live/healthy and non-zero is unhealthy.\n                              items:\n                                type: string\n                              type: array\n                          type: object\n                        failureThreshold:\n                          description: Minimum consecutive failures for the probe\n                            to be considered failed after having succeeded. Defaults\n                            to 3. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        httpGet:\n                          description: HTTPGet specifies the http request to perform.\n                          properties:\n                            host:\n                              description: Host name to connect to, defaults to the\n                                pod IP. You probably want to set \"Host\" in httpHeaders\n                                instead.\n                              type: string\n                            httpHeaders:\n                              description: Custom headers to set in the request. HTTP\n                                allows repeated headers.\n                              items:\n                                description: HTTPHeader describes a custom header\n                                  to be used in HTTP probes\n                                properties:\n                                  name:\n                                    description: The header field name\n                                    type: string\n                                  value:\n                                    description: The header field value\n                                    type: string\n                                required:\n                                - name\n                                - value\n                                type: object\n                              type: array\n                            path:\n                              description: Path to access on the HTTP server.\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Name or number of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                            scheme:\n                              description: Scheme to use for connecting to the host.\n                                Defaults to HTTP.\n                              type: string\n                          required:\n                          - port\n                          type: object\n                        initialDelaySeconds:\n                          description: 'Number of seconds after the container has\n                            started before liveness probes are initiated. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                        periodSeconds:\n                          description: How often (in seconds) to perform the probe.\n                            Default to 10 seconds. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        successThreshold:\n                          description: Minimum consecutive successes for the probe\n                            to be considered successful after having failed. Defaults\n                            to 1. Must be 1 for liveness and startup. Minimum value\n                            is 1.\n                          format: int32\n                          type: integer\n                        tcpSocket:\n                          description: 'TCPSocket specifies an action involving a\n                            TCP port. TCP hooks not yet supported TODO: implement\n                            a realistic TCP lifecycle hook'\n                          properties:\n                            host:\n                              description: 'Optional: Host name to connect to, defaults\n                                to the pod IP.'\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Number or name of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                          required:\n                          - port\n                          type: object\n                        timeoutSeconds:\n                          description: 'Number of seconds after which the probe times\n                            out. Defaults to 1 second. Minimum value is 1. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                      type: object\n                    resources:\n                      description: 'Compute Resources required by this container.\n                        Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                      properties:\n                        limits:\n                          additionalProperties:\n                            anyOf:\n                            - type: integer\n                            - type: string\n                            pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                            x-kubernetes-int-or-string: true\n                          description: 'Limits describes the maximum amount of compute\n                            resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                          type: object\n                        requests:\n                          additionalProperties:\n                            anyOf:\n                            - type: integer\n                            - type: string\n                            pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                            x-kubernetes-int-or-string: true\n                          description: 'Requests describes the minimum amount of compute\n                            resources required. If Requests is omitted for a container,\n                            it defaults to Limits if that is explicitly specified,\n                            otherwise to an implementation-defined value. More info:\n                            https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                          type: object\n                      type: object\n                    securityContext:\n                      description: 'Security options the pod should run with. More\n                        info: https://kubernetes.io/docs/concepts/policy/security-context/\n                        More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/'\n                      properties:\n                        allowPrivilegeEscalation:\n                          description: 'AllowPrivilegeEscalation controls whether\n                            a process can gain more privileges than its parent process.\n                            This bool directly controls if the no_new_privs flag will\n                            be set on the container process. AllowPrivilegeEscalation\n                            is true always when the container is: 1) run as Privileged\n                            2) has CAP_SYS_ADMIN'\n                          type: boolean\n                        capabilities:\n                          description: The capabilities to add/drop when running containers.\n                            Defaults to the default set of capabilities granted by\n                            the container runtime.\n                          properties:\n                            add:\n                              description: Added capabilities\n                              items:\n                                description: Capability represent POSIX capabilities\n                                  type\n                                type: string\n                              type: array\n                            drop:\n                              description: Removed capabilities\n                              items:\n                                description: Capability represent POSIX capabilities\n                                  type\n                                type: string\n                              type: array\n                          type: object\n                        privileged:\n                          description: Run container in privileged mode. Processes\n                            in privileged containers are essentially equivalent to\n                            root on the host. Defaults to false.\n                          type: boolean\n                        procMount:\n                          description: procMount denotes the type of proc mount to\n                            use for the containers. The default is DefaultProcMount\n                            which uses the container runtime defaults for readonly\n                            paths and masked paths. This requires the ProcMountType\n                            feature flag to be enabled.\n                          type: string\n                        readOnlyRootFilesystem:\n                          description: Whether this container has a read-only root\n                            filesystem. Default is false.\n                          type: boolean\n                        runAsGroup:\n                          description: The GID to run the entrypoint of the container\n                            process. Uses runtime default if unset. May also be set\n                            in PodSecurityContext.  If set in both SecurityContext\n                            and PodSecurityContext, the value specified in SecurityContext\n                            takes precedence.\n                          format: int64\n                          type: integer\n                        runAsNonRoot:\n                          description: Indicates that the container must run as a\n                            non-root user. If true, the Kubelet will validate the\n                            image at runtime to ensure that it does not run as UID\n                            0 (root) and fail to start the container if it does. If\n                            unset or false, no such validation will be performed.\n                            May also be set in PodSecurityContext.  If set in both\n                            SecurityContext and PodSecurityContext, the value specified\n                            in SecurityContext takes precedence.\n                          type: boolean\n                        runAsUser:\n                          description: The UID to run the entrypoint of the container\n                            process. Defaults to user specified in image metadata\n                            if unspecified. May also be set in PodSecurityContext.  If\n                            set in both SecurityContext and PodSecurityContext, the\n                            value specified in SecurityContext takes precedence.\n                          format: int64\n                          type: integer\n                        seLinuxOptions:\n                          description: The SELinux context to be applied to the container.\n                            If unspecified, the container runtime will allocate a\n                            random SELinux context for each container.  May also be\n                            set in PodSecurityContext.  If set in both SecurityContext\n                            and PodSecurityContext, the value specified in SecurityContext\n                            takes precedence.\n                          properties:\n                            level:\n                              description: Level is SELinux level label that applies\n                                to the container.\n                              type: string\n                            role:\n                              description: Role is a SELinux role label that applies\n                                to the container.\n                              type: string\n                            type:\n                              description: Type is a SELinux type label that applies\n                                to the container.\n                              type: string\n                            user:\n                              description: User is a SELinux user label that applies\n                                to the container.\n                              type: string\n                          type: object\n                        windowsOptions:\n                          description: The Windows specific settings applied to all\n                            containers. If unspecified, the options from the PodSecurityContext\n                            will be used. If set in both SecurityContext and PodSecurityContext,\n                            the value specified in SecurityContext takes precedence.\n                          properties:\n                            gmsaCredentialSpec:\n                              description: GMSACredentialSpec is where the GMSA admission\n                                webhook (https://github.com/kubernetes-sigs/windows-gmsa)\n                                inlines the contents of the GMSA credential spec named\n                                by the GMSACredentialSpecName field.\n                              type: string\n                            gmsaCredentialSpecName:\n                              description: GMSACredentialSpecName is the name of the\n                                GMSA credential spec to use.\n                              type: string\n                            runAsUserName:\n                              description: The UserName in Windows to run the entrypoint\n                                of the container process. Defaults to the user specified\n                                in image metadata if unspecified. May also be set\n                                in PodSecurityContext. If set in both SecurityContext\n                                and PodSecurityContext, the value specified in SecurityContext\n                                takes precedence.\n                              type: string\n                          type: object\n                      type: object\n                    startupProbe:\n                      description: 'StartupProbe indicates that the Pod has successfully\n                        initialized. If specified, no other probes are executed until\n                        this completes successfully. If this probe fails, the Pod\n                        will be restarted, just as if the livenessProbe failed. This\n                        can be used to provide different probe parameters at the beginning\n                        of a Pod''s lifecycle, when it might take a long time to load\n                        data or warm a cache, than during steady-state operation.\n                        This cannot be updated. This is a beta feature enabled by\n                        the StartupProbe feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                      properties:\n                        exec:\n                          description: One and only one of the following should be\n                            specified. Exec specifies the action to take.\n                          properties:\n                            command:\n                              description: Command is the command line to execute\n                                inside the container, the working directory for the\n                                command  is root ('/') in the container's filesystem.\n                                The command is simply exec'd, it is not run inside\n                                a shell, so traditional shell instructions ('|', etc)\n                                won't work. To use a shell, you need to explicitly\n                                call out to that shell. Exit status of 0 is treated\n                                as live/healthy and non-zero is unhealthy.\n                              items:\n                                type: string\n                              type: array\n                          type: object\n                        failureThreshold:\n                          description: Minimum consecutive failures for the probe\n                            to be considered failed after having succeeded. Defaults\n                            to 3. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        httpGet:\n                          description: HTTPGet specifies the http request to perform.\n                          properties:\n                            host:\n                              description: Host name to connect to, defaults to the\n                                pod IP. You probably want to set \"Host\" in httpHeaders\n                                instead.\n                              type: string\n                            httpHeaders:\n                              description: Custom headers to set in the request. HTTP\n                                allows repeated headers.\n                              items:\n                                description: HTTPHeader describes a custom header\n                                  to be used in HTTP probes\n                                properties:\n                                  name:\n                                    description: The header field name\n                                    type: string\n                                  value:\n                                    description: The header field value\n                                    type: string\n                                required:\n                                - name\n                                - value\n                                type: object\n                              type: array\n                            path:\n                              description: Path to access on the HTTP server.\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Name or number of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                            scheme:\n                              description: Scheme to use for connecting to the host.\n                                Defaults to HTTP.\n                              type: string\n                          required:\n                          - port\n                          type: object\n                        initialDelaySeconds:\n                          description: 'Number of seconds after the container has\n                            started before liveness probes are initiated. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                        periodSeconds:\n                          description: How often (in seconds) to perform the probe.\n                            Default to 10 seconds. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        successThreshold:\n                          description: Minimum consecutive successes for the probe\n                            to be considered successful after having failed. Defaults\n                            to 1. Must be 1 for liveness and startup. Minimum value\n                            is 1.\n                          format: int32\n                          type: integer\n                        tcpSocket:\n                          description: 'TCPSocket specifies an action involving a\n                            TCP port. TCP hooks not yet supported TODO: implement\n                            a realistic TCP lifecycle hook'\n                          properties:\n                            host:\n                              description: 'Optional: Host name to connect to, defaults\n                                to the pod IP.'\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Number or name of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                          required:\n                          - port\n                          type: object\n                        timeoutSeconds:\n                          description: 'Number of seconds after which the probe times\n                            out. Defaults to 1 second. Minimum value is 1. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                      type: object\n                    stdin:\n                      description: Whether this container should allocate a buffer\n                        for stdin in the container runtime. If this is not set, reads\n                        from stdin in the container will always result in EOF. Default\n                        is false.\n                      type: boolean\n                    stdinOnce:\n                      description: Whether the container runtime should close the\n                        stdin channel after it has been opened by a single attach.\n                        When stdin is true the stdin stream will remain open across\n                        multiple attach sessions. If stdinOnce is set to true, stdin\n                        is opened on container start, is empty until the first client\n                        attaches to stdin, and then remains open and accepts data\n                        until the client disconnects, at which time stdin is closed\n                        and remains closed until the container is restarted. If this\n                        flag is false, a container processes that reads from stdin\n                        will never receive an EOF. Default is false\n                      type: boolean\n                    terminationMessagePath:\n                      description: 'Optional: Path at which the file to which the\n                        container''s termination message will be written is mounted\n                        into the container''s filesystem. Message written is intended\n                        to be brief final status, such as an assertion failure message.\n                        Will be truncated by the node if greater than 4096 bytes.\n                        The total message length across all containers will be limited\n                        to 12kb. Defaults to /dev/termination-log. Cannot be updated.'\n                      type: string\n                    terminationMessagePolicy:\n                      description: Indicate how the termination message should be\n                        populated. File will use the contents of terminationMessagePath\n                        to populate the container status message on both success and\n                        failure. FallbackToLogsOnError will use the last chunk of\n                        container log output if the termination message file is empty\n                        and the container exited with an error. The log output is\n                        limited to 2048 bytes or 80 lines, whichever is smaller. Defaults\n                        to File. Cannot be updated.\n                      type: string\n                    tty:\n                      description: Whether this container should allocate a TTY for\n                        itself, also requires 'stdin' to be true. Default is false.\n                      type: boolean\n                    volumeDevices:\n                      description: volumeDevices is the list of block devices to be\n                        used by the container.\n                      items:\n                        description: volumeDevice describes a mapping of a raw block\n                          device within a container.\n                        properties:\n                          devicePath:\n                            description: devicePath is the path inside of the container\n                              that the device will be mapped to.\n                            type: string\n                          name:\n                            description: name must match the name of a persistentVolumeClaim\n                              in the pod\n                            type: string\n                        required:\n                        - devicePath\n                        - name\n                        type: object\n                      type: array\n                    volumeMounts:\n                      description: Pod volumes to mount into the container's filesystem.\n                        Cannot be updated.\n                      items:\n                        description: VolumeMount describes a mounting of a Volume\n                          within a container.\n                        properties:\n                          mountPath:\n                            description: Path within the container at which the volume\n                              should be mounted.  Must not contain ':'.\n                            type: string\n                          mountPropagation:\n                            description: mountPropagation determines how mounts are\n                              propagated from the host to container and the other\n                              way around. When not set, MountPropagationNone is used.\n                              This field is beta in 1.10.\n                            type: string\n                          name:\n                            description: This must match the Name of a Volume.\n                            type: string\n                          readOnly:\n                            description: Mounted read-only if true, read-write otherwise\n                              (false or unspecified). Defaults to false.\n                            type: boolean\n                          subPath:\n                            description: Path within the volume from which the container's\n                              volume should be mounted. Defaults to \"\" (volume's root).\n                            type: string\n                          subPathExpr:\n                            description: Expanded path within the volume from which\n                              the container's volume should be mounted. Behaves similarly\n                              to SubPath but environment variable references $(VAR_NAME)\n                              are expanded using the container's environment. Defaults\n                              to \"\" (volume's root). SubPathExpr and SubPath are mutually\n                              exclusive.\n                            type: string\n                        required:\n                        - mountPath\n                        - name\n                        type: object\n                      type: array\n                    workingDir:\n                      description: Container's working directory. If not specified,\n                        the container runtime's default will be used, which might\n                        be configured in the container image. Cannot be updated.\n                      type: string\n                  required:\n                  - name\n                  type: object\n                type: array\n              enforcedNamespaceLabel:\n                description: EnforcedNamespaceLabel enforces adding a namespace label\n                  of origin for each alert and metric that is user created. The label\n                  value will always be the namespace of the object that is being created.\n                type: string\n              evaluationInterval:\n                description: Interval between consecutive evaluations.\n                type: string\n              externalPrefix:\n                description: The external URL the Thanos Ruler instances will be available\n                  under. This is necessary to generate correct URLs. This is necessary\n                  if Thanos Ruler is not served from root of a DNS name.\n                type: string\n              grpcServerTlsConfig:\n                description: 'GRPCServerTLSConfig configures the gRPC server from\n                  which Thanos Querier reads recorded rule data. Note: Currently only\n                  the CAFile, CertFile, and KeyFile fields are supported. Maps to\n                  the ''--grpc-server-tls-*'' CLI args.'\n                properties:\n                  ca:\n                    description: Struct containing the CA cert to use for the targets.\n                    properties:\n                      configMap:\n                        description: ConfigMap containing data to use for the targets.\n                        properties:\n                          key:\n                            description: The key to select.\n                            type: string\n                          name:\n                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                              TODO: Add other useful fields. apiVersion, kind, uid?'\n                            type: string\n                          optional:\n                            description: Specify whether the ConfigMap or its key\n                              must be defined\n                            type: boolean\n                        required:\n                        - key\n                        type: object\n                      secret:\n                        description: Secret containing data to use for the targets.\n                        properties:\n                          key:\n                            description: The key of the secret to select from.  Must\n                              be a valid secret key.\n                            type: string\n                          name:\n                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                              TODO: Add other useful fields. apiVersion, kind, uid?'\n                            type: string\n                          optional:\n                            description: Specify whether the Secret or its key must\n                              be defined\n                            type: boolean\n                        required:\n                        - key\n                        type: object\n                    type: object\n                  caFile:\n                    description: Path to the CA cert in the Prometheus container to\n                      use for the targets.\n                    type: string\n                  cert:\n                    description: Struct containing the client cert file for the targets.\n                    properties:\n                      configMap:\n                        description: ConfigMap containing data to use for the targets.\n                        properties:\n                          key:\n                            description: The key to select.\n                            type: string\n                          name:\n                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                              TODO: Add other useful fields. apiVersion, kind, uid?'\n                            type: string\n                          optional:\n                            description: Specify whether the ConfigMap or its key\n                              must be defined\n                            type: boolean\n                        required:\n                        - key\n                        type: object\n                      secret:\n                        description: Secret containing data to use for the targets.\n                        properties:\n                          key:\n                            description: The key of the secret to select from.  Must\n                              be a valid secret key.\n                            type: string\n                          name:\n                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                              TODO: Add other useful fields. apiVersion, kind, uid?'\n                            type: string\n                          optional:\n                            description: Specify whether the Secret or its key must\n                              be defined\n                            type: boolean\n                        required:\n                        - key\n                        type: object\n                    type: object\n                  certFile:\n                    description: Path to the client cert file in the Prometheus container\n                      for the targets.\n                    type: string\n                  insecureSkipVerify:\n                    description: Disable target certificate validation.\n                    type: boolean\n                  keyFile:\n                    description: Path to the client key file in the Prometheus container\n                      for the targets.\n                    type: string\n                  keySecret:\n                    description: Secret containing the client key file for the targets.\n                    properties:\n                      key:\n                        description: The key of the secret to select from.  Must be\n                          a valid secret key.\n                        type: string\n                      name:\n                        description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                          TODO: Add other useful fields. apiVersion, kind, uid?'\n                        type: string\n                      optional:\n                        description: Specify whether the Secret or its key must be\n                          defined\n                        type: boolean\n                    required:\n                    - key\n                    type: object\n                  serverName:\n                    description: Used to verify the hostname for the targets.\n                    type: string\n                type: object\n              image:\n                description: Thanos container image URL.\n                type: string\n              imagePullSecrets:\n                description: An optional list of references to secrets in the same\n                  namespace to use for pulling thanos images from registries see http://kubernetes.io/docs/user-guide/images#specifying-imagepullsecrets-on-a-pod\n                items:\n                  description: LocalObjectReference contains enough information to\n                    let you locate the referenced object inside the same namespace.\n                  properties:\n                    name:\n                      description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                        TODO: Add other useful fields. apiVersion, kind, uid?'\n                      type: string\n                  type: object\n                type: array\n              initContainers:\n                description: 'InitContainers allows adding initContainers to the pod\n                  definition. Those can be used to e.g. fetch secrets for injection\n                  into the ThanosRuler configuration from external sources. Any errors\n                  during the execution of an initContainer will lead to a restart\n                  of the Pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/\n                  Using initContainers for any use case other then secret fetching\n                  is entirely outside the scope of what the maintainers will support\n                  and by doing so, you accept that this behaviour may break at any\n                  time without notice.'\n                items:\n                  description: A single application container that you want to run\n                    within a pod.\n                  properties:\n                    args:\n                      description: 'Arguments to the entrypoint. The docker image''s\n                        CMD is used if this is not provided. Variable references $(VAR_NAME)\n                        are expanded using the container''s environment. If a variable\n                        cannot be resolved, the reference in the input string will\n                        be unchanged. The $(VAR_NAME) syntax can be escaped with a\n                        double $$, ie: $$(VAR_NAME). Escaped references will never\n                        be expanded, regardless of whether the variable exists or\n                        not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell'\n                      items:\n                        type: string\n                      type: array\n                    command:\n                      description: 'Entrypoint array. Not executed within a shell.\n                        The docker image''s ENTRYPOINT is used if this is not provided.\n                        Variable references $(VAR_NAME) are expanded using the container''s\n                        environment. If a variable cannot be resolved, the reference\n                        in the input string will be unchanged. The $(VAR_NAME) syntax\n                        can be escaped with a double $$, ie: $$(VAR_NAME). Escaped\n                        references will never be expanded, regardless of whether the\n                        variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell'\n                      items:\n                        type: string\n                      type: array\n                    env:\n                      description: List of environment variables to set in the container.\n                        Cannot be updated.\n                      items:\n                        description: EnvVar represents an environment variable present\n                          in a Container.\n                        properties:\n                          name:\n                            description: Name of the environment variable. Must be\n                              a C_IDENTIFIER.\n                            type: string\n                          value:\n                            description: 'Variable references $(VAR_NAME) are expanded\n                              using the previous defined environment variables in\n                              the container and any service environment variables.\n                              If a variable cannot be resolved, the reference in the\n                              input string will be unchanged. The $(VAR_NAME) syntax\n                              can be escaped with a double $$, ie: $$(VAR_NAME). Escaped\n                              references will never be expanded, regardless of whether\n                              the variable exists or not. Defaults to \"\".'\n                            type: string\n                          valueFrom:\n                            description: Source for the environment variable's value.\n                              Cannot be used if value is not empty.\n                            properties:\n                              configMapKeyRef:\n                                description: Selects a key of a ConfigMap.\n                                properties:\n                                  key:\n                                    description: The key to select.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the ConfigMap or\n                                      its key must be defined\n                                    type: boolean\n                                required:\n                                - key\n                                type: object\n                              fieldRef:\n                                description: 'Selects a field of the pod: supports\n                                  metadata.name, metadata.namespace, metadata.labels,\n                                  metadata.annotations, spec.nodeName, spec.serviceAccountName,\n                                  status.hostIP, status.podIP, status.podIPs.'\n                                properties:\n                                  apiVersion:\n                                    description: Version of the schema the FieldPath\n                                      is written in terms of, defaults to \"v1\".\n                                    type: string\n                                  fieldPath:\n                                    description: Path of the field to select in the\n                                      specified API version.\n                                    type: string\n                                required:\n                                - fieldPath\n                                type: object\n                              resourceFieldRef:\n                                description: 'Selects a resource of the container:\n                                  only resources limits and requests (limits.cpu,\n                                  limits.memory, limits.ephemeral-storage, requests.cpu,\n                                  requests.memory and requests.ephemeral-storage)\n                                  are currently supported.'\n                                properties:\n                                  containerName:\n                                    description: 'Container name: required for volumes,\n                                      optional for env vars'\n                                    type: string\n                                  divisor:\n                                    anyOf:\n                                    - type: integer\n                                    - type: string\n                                    description: Specifies the output format of the\n                                      exposed resources, defaults to \"1\"\n                                    pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                    x-kubernetes-int-or-string: true\n                                  resource:\n                                    description: 'Required: resource to select'\n                                    type: string\n                                required:\n                                - resource\n                                type: object\n                              secretKeyRef:\n                                description: Selects a key of a secret in the pod's\n                                  namespace\n                                properties:\n                                  key:\n                                    description: The key of the secret to select from.  Must\n                                      be a valid secret key.\n                                    type: string\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the Secret or its\n                                      key must be defined\n                                    type: boolean\n                                required:\n                                - key\n                                type: object\n                            type: object\n                        required:\n                        - name\n                        type: object\n                      type: array\n                    envFrom:\n                      description: List of sources to populate environment variables\n                        in the container. The keys defined within a source must be\n                        a C_IDENTIFIER. All invalid keys will be reported as an event\n                        when the container is starting. When a key exists in multiple\n                        sources, the value associated with the last source will take\n                        precedence. Values defined by an Env with a duplicate key\n                        will take precedence. Cannot be updated.\n                      items:\n                        description: EnvFromSource represents the source of a set\n                          of ConfigMaps\n                        properties:\n                          configMapRef:\n                            description: The ConfigMap to select from\n                            properties:\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the ConfigMap must be\n                                  defined\n                                type: boolean\n                            type: object\n                          prefix:\n                            description: An optional identifier to prepend to each\n                              key in the ConfigMap. Must be a C_IDENTIFIER.\n                            type: string\n                          secretRef:\n                            description: The Secret to select from\n                            properties:\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                  TODO: Add other useful fields. apiVersion, kind,\n                                  uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret must be defined\n                                type: boolean\n                            type: object\n                        type: object\n                      type: array\n                    image:\n                      description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images\n                        This field is optional to allow higher level config management\n                        to default or override container images in workload controllers\n                        like Deployments and StatefulSets.'\n                      type: string\n                    imagePullPolicy:\n                      description: 'Image pull policy. One of Always, Never, IfNotPresent.\n                        Defaults to Always if :latest tag is specified, or IfNotPresent\n                        otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images'\n                      type: string\n                    lifecycle:\n                      description: Actions that the management system should take\n                        in response to container lifecycle events. Cannot be updated.\n                      properties:\n                        postStart:\n                          description: 'PostStart is called immediately after a container\n                            is created. If the handler fails, the container is terminated\n                            and restarted according to its restart policy. Other management\n                            of the container blocks until the hook completes. More\n                            info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks'\n                          properties:\n                            exec:\n                              description: One and only one of the following should\n                                be specified. Exec specifies the action to take.\n                              properties:\n                                command:\n                                  description: Command is the command line to execute\n                                    inside the container, the working directory for\n                                    the command  is root ('/') in the container's\n                                    filesystem. The command is simply exec'd, it is\n                                    not run inside a shell, so traditional shell instructions\n                                    ('|', etc) won't work. To use a shell, you need\n                                    to explicitly call out to that shell. Exit status\n                                    of 0 is treated as live/healthy and non-zero is\n                                    unhealthy.\n                                  items:\n                                    type: string\n                                  type: array\n                              type: object\n                            httpGet:\n                              description: HTTPGet specifies the http request to perform.\n                              properties:\n                                host:\n                                  description: Host name to connect to, defaults to\n                                    the pod IP. You probably want to set \"Host\" in\n                                    httpHeaders instead.\n                                  type: string\n                                httpHeaders:\n                                  description: Custom headers to set in the request.\n                                    HTTP allows repeated headers.\n                                  items:\n                                    description: HTTPHeader describes a custom header\n                                      to be used in HTTP probes\n                                    properties:\n                                      name:\n                                        description: The header field name\n                                        type: string\n                                      value:\n                                        description: The header field value\n                                        type: string\n                                    required:\n                                    - name\n                                    - value\n                                    type: object\n                                  type: array\n                                path:\n                                  description: Path to access on the HTTP server.\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Name or number of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                                scheme:\n                                  description: Scheme to use for connecting to the\n                                    host. Defaults to HTTP.\n                                  type: string\n                              required:\n                              - port\n                              type: object\n                            tcpSocket:\n                              description: 'TCPSocket specifies an action involving\n                                a TCP port. TCP hooks not yet supported TODO: implement\n                                a realistic TCP lifecycle hook'\n                              properties:\n                                host:\n                                  description: 'Optional: Host name to connect to,\n                                    defaults to the pod IP.'\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Number or name of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                              required:\n                              - port\n                              type: object\n                          type: object\n                        preStop:\n                          description: 'PreStop is called immediately before a container\n                            is terminated due to an API request or management event\n                            such as liveness/startup probe failure, preemption, resource\n                            contention, etc. The handler is not called if the container\n                            crashes or exits. The reason for termination is passed\n                            to the handler. The Pod''s termination grace period countdown\n                            begins before the PreStop hooked is executed. Regardless\n                            of the outcome of the handler, the container will eventually\n                            terminate within the Pod''s termination grace period.\n                            Other management of the container blocks until the hook\n                            completes or until the termination grace period is reached.\n                            More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks'\n                          properties:\n                            exec:\n                              description: One and only one of the following should\n                                be specified. Exec specifies the action to take.\n                              properties:\n                                command:\n                                  description: Command is the command line to execute\n                                    inside the container, the working directory for\n                                    the command  is root ('/') in the container's\n                                    filesystem. The command is simply exec'd, it is\n                                    not run inside a shell, so traditional shell instructions\n                                    ('|', etc) won't work. To use a shell, you need\n                                    to explicitly call out to that shell. Exit status\n                                    of 0 is treated as live/healthy and non-zero is\n                                    unhealthy.\n                                  items:\n                                    type: string\n                                  type: array\n                              type: object\n                            httpGet:\n                              description: HTTPGet specifies the http request to perform.\n                              properties:\n                                host:\n                                  description: Host name to connect to, defaults to\n                                    the pod IP. You probably want to set \"Host\" in\n                                    httpHeaders instead.\n                                  type: string\n                                httpHeaders:\n                                  description: Custom headers to set in the request.\n                                    HTTP allows repeated headers.\n                                  items:\n                                    description: HTTPHeader describes a custom header\n                                      to be used in HTTP probes\n                                    properties:\n                                      name:\n                                        description: The header field name\n                                        type: string\n                                      value:\n                                        description: The header field value\n                                        type: string\n                                    required:\n                                    - name\n                                    - value\n                                    type: object\n                                  type: array\n                                path:\n                                  description: Path to access on the HTTP server.\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Name or number of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                                scheme:\n                                  description: Scheme to use for connecting to the\n                                    host. Defaults to HTTP.\n                                  type: string\n                              required:\n                              - port\n                              type: object\n                            tcpSocket:\n                              description: 'TCPSocket specifies an action involving\n                                a TCP port. TCP hooks not yet supported TODO: implement\n                                a realistic TCP lifecycle hook'\n                              properties:\n                                host:\n                                  description: 'Optional: Host name to connect to,\n                                    defaults to the pod IP.'\n                                  type: string\n                                port:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  description: Number or name of the port to access\n                                    on the container. Number must be in the range\n                                    1 to 65535. Name must be an IANA_SVC_NAME.\n                                  x-kubernetes-int-or-string: true\n                              required:\n                              - port\n                              type: object\n                          type: object\n                      type: object\n                    livenessProbe:\n                      description: 'Periodic probe of container liveness. Container\n                        will be restarted if the probe fails. Cannot be updated. More\n                        info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                      properties:\n                        exec:\n                          description: One and only one of the following should be\n                            specified. Exec specifies the action to take.\n                          properties:\n                            command:\n                              description: Command is the command line to execute\n                                inside the container, the working directory for the\n                                command  is root ('/') in the container's filesystem.\n                                The command is simply exec'd, it is not run inside\n                                a shell, so traditional shell instructions ('|', etc)\n                                won't work. To use a shell, you need to explicitly\n                                call out to that shell. Exit status of 0 is treated\n                                as live/healthy and non-zero is unhealthy.\n                              items:\n                                type: string\n                              type: array\n                          type: object\n                        failureThreshold:\n                          description: Minimum consecutive failures for the probe\n                            to be considered failed after having succeeded. Defaults\n                            to 3. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        httpGet:\n                          description: HTTPGet specifies the http request to perform.\n                          properties:\n                            host:\n                              description: Host name to connect to, defaults to the\n                                pod IP. You probably want to set \"Host\" in httpHeaders\n                                instead.\n                              type: string\n                            httpHeaders:\n                              description: Custom headers to set in the request. HTTP\n                                allows repeated headers.\n                              items:\n                                description: HTTPHeader describes a custom header\n                                  to be used in HTTP probes\n                                properties:\n                                  name:\n                                    description: The header field name\n                                    type: string\n                                  value:\n                                    description: The header field value\n                                    type: string\n                                required:\n                                - name\n                                - value\n                                type: object\n                              type: array\n                            path:\n                              description: Path to access on the HTTP server.\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Name or number of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                            scheme:\n                              description: Scheme to use for connecting to the host.\n                                Defaults to HTTP.\n                              type: string\n                          required:\n                          - port\n                          type: object\n                        initialDelaySeconds:\n                          description: 'Number of seconds after the container has\n                            started before liveness probes are initiated. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                        periodSeconds:\n                          description: How often (in seconds) to perform the probe.\n                            Default to 10 seconds. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        successThreshold:\n                          description: Minimum consecutive successes for the probe\n                            to be considered successful after having failed. Defaults\n                            to 1. Must be 1 for liveness and startup. Minimum value\n                            is 1.\n                          format: int32\n                          type: integer\n                        tcpSocket:\n                          description: 'TCPSocket specifies an action involving a\n                            TCP port. TCP hooks not yet supported TODO: implement\n                            a realistic TCP lifecycle hook'\n                          properties:\n                            host:\n                              description: 'Optional: Host name to connect to, defaults\n                                to the pod IP.'\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Number or name of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                          required:\n                          - port\n                          type: object\n                        timeoutSeconds:\n                          description: 'Number of seconds after which the probe times\n                            out. Defaults to 1 second. Minimum value is 1. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                      type: object\n                    name:\n                      description: Name of the container specified as a DNS_LABEL.\n                        Each container in a pod must have a unique name (DNS_LABEL).\n                        Cannot be updated.\n                      type: string\n                    ports:\n                      description: List of ports to expose from the container. Exposing\n                        a port here gives the system additional information about\n                        the network connections a container uses, but is primarily\n                        informational. Not specifying a port here DOES NOT prevent\n                        that port from being exposed. Any port which is listening\n                        on the default \"0.0.0.0\" address inside a container will be\n                        accessible from the network. Cannot be updated.\n                      items:\n                        description: ContainerPort represents a network port in a\n                          single container.\n                        properties:\n                          containerPort:\n                            description: Number of port to expose on the pod's IP\n                              address. This must be a valid port number, 0 < x < 65536.\n                            format: int32\n                            type: integer\n                          hostIP:\n                            description: What host IP to bind the external port to.\n                            type: string\n                          hostPort:\n                            description: Number of port to expose on the host. If\n                              specified, this must be a valid port number, 0 < x <\n                              65536. If HostNetwork is specified, this must match\n                              ContainerPort. Most containers do not need this.\n                            format: int32\n                            type: integer\n                          name:\n                            description: If specified, this must be an IANA_SVC_NAME\n                              and unique within the pod. Each named port in a pod\n                              must have a unique name. Name for the port that can\n                              be referred to by services.\n                            type: string\n                          protocol:\n                            default: TCP\n                            description: Protocol for port. Must be UDP, TCP, or SCTP.\n                              Defaults to \"TCP\".\n                            type: string\n                        required:\n                        - containerPort\n                        type: object\n                      type: array\n                      x-kubernetes-list-map-keys:\n                      - containerPort\n                      - protocol\n                      x-kubernetes-list-type: map\n                    readinessProbe:\n                      description: 'Periodic probe of container service readiness.\n                        Container will be removed from service endpoints if the probe\n                        fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                      properties:\n                        exec:\n                          description: One and only one of the following should be\n                            specified. Exec specifies the action to take.\n                          properties:\n                            command:\n                              description: Command is the command line to execute\n                                inside the container, the working directory for the\n                                command  is root ('/') in the container's filesystem.\n                                The command is simply exec'd, it is not run inside\n                                a shell, so traditional shell instructions ('|', etc)\n                                won't work. To use a shell, you need to explicitly\n                                call out to that shell. Exit status of 0 is treated\n                                as live/healthy and non-zero is unhealthy.\n                              items:\n                                type: string\n                              type: array\n                          type: object\n                        failureThreshold:\n                          description: Minimum consecutive failures for the probe\n                            to be considered failed after having succeeded. Defaults\n                            to 3. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        httpGet:\n                          description: HTTPGet specifies the http request to perform.\n                          properties:\n                            host:\n                              description: Host name to connect to, defaults to the\n                                pod IP. You probably want to set \"Host\" in httpHeaders\n                                instead.\n                              type: string\n                            httpHeaders:\n                              description: Custom headers to set in the request. HTTP\n                                allows repeated headers.\n                              items:\n                                description: HTTPHeader describes a custom header\n                                  to be used in HTTP probes\n                                properties:\n                                  name:\n                                    description: The header field name\n                                    type: string\n                                  value:\n                                    description: The header field value\n                                    type: string\n                                required:\n                                - name\n                                - value\n                                type: object\n                              type: array\n                            path:\n                              description: Path to access on the HTTP server.\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Name or number of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                            scheme:\n                              description: Scheme to use for connecting to the host.\n                                Defaults to HTTP.\n                              type: string\n                          required:\n                          - port\n                          type: object\n                        initialDelaySeconds:\n                          description: 'Number of seconds after the container has\n                            started before liveness probes are initiated. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                        periodSeconds:\n                          description: How often (in seconds) to perform the probe.\n                            Default to 10 seconds. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        successThreshold:\n                          description: Minimum consecutive successes for the probe\n                            to be considered successful after having failed. Defaults\n                            to 1. Must be 1 for liveness and startup. Minimum value\n                            is 1.\n                          format: int32\n                          type: integer\n                        tcpSocket:\n                          description: 'TCPSocket specifies an action involving a\n                            TCP port. TCP hooks not yet supported TODO: implement\n                            a realistic TCP lifecycle hook'\n                          properties:\n                            host:\n                              description: 'Optional: Host name to connect to, defaults\n                                to the pod IP.'\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Number or name of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                          required:\n                          - port\n                          type: object\n                        timeoutSeconds:\n                          description: 'Number of seconds after which the probe times\n                            out. Defaults to 1 second. Minimum value is 1. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                      type: object\n                    resources:\n                      description: 'Compute Resources required by this container.\n                        Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                      properties:\n                        limits:\n                          additionalProperties:\n                            anyOf:\n                            - type: integer\n                            - type: string\n                            pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                            x-kubernetes-int-or-string: true\n                          description: 'Limits describes the maximum amount of compute\n                            resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                          type: object\n                        requests:\n                          additionalProperties:\n                            anyOf:\n                            - type: integer\n                            - type: string\n                            pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                            x-kubernetes-int-or-string: true\n                          description: 'Requests describes the minimum amount of compute\n                            resources required. If Requests is omitted for a container,\n                            it defaults to Limits if that is explicitly specified,\n                            otherwise to an implementation-defined value. More info:\n                            https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                          type: object\n                      type: object\n                    securityContext:\n                      description: 'Security options the pod should run with. More\n                        info: https://kubernetes.io/docs/concepts/policy/security-context/\n                        More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/'\n                      properties:\n                        allowPrivilegeEscalation:\n                          description: 'AllowPrivilegeEscalation controls whether\n                            a process can gain more privileges than its parent process.\n                            This bool directly controls if the no_new_privs flag will\n                            be set on the container process. AllowPrivilegeEscalation\n                            is true always when the container is: 1) run as Privileged\n                            2) has CAP_SYS_ADMIN'\n                          type: boolean\n                        capabilities:\n                          description: The capabilities to add/drop when running containers.\n                            Defaults to the default set of capabilities granted by\n                            the container runtime.\n                          properties:\n                            add:\n                              description: Added capabilities\n                              items:\n                                description: Capability represent POSIX capabilities\n                                  type\n                                type: string\n                              type: array\n                            drop:\n                              description: Removed capabilities\n                              items:\n                                description: Capability represent POSIX capabilities\n                                  type\n                                type: string\n                              type: array\n                          type: object\n                        privileged:\n                          description: Run container in privileged mode. Processes\n                            in privileged containers are essentially equivalent to\n                            root on the host. Defaults to false.\n                          type: boolean\n                        procMount:\n                          description: procMount denotes the type of proc mount to\n                            use for the containers. The default is DefaultProcMount\n                            which uses the container runtime defaults for readonly\n                            paths and masked paths. This requires the ProcMountType\n                            feature flag to be enabled.\n                          type: string\n                        readOnlyRootFilesystem:\n                          description: Whether this container has a read-only root\n                            filesystem. Default is false.\n                          type: boolean\n                        runAsGroup:\n                          description: The GID to run the entrypoint of the container\n                            process. Uses runtime default if unset. May also be set\n                            in PodSecurityContext.  If set in both SecurityContext\n                            and PodSecurityContext, the value specified in SecurityContext\n                            takes precedence.\n                          format: int64\n                          type: integer\n                        runAsNonRoot:\n                          description: Indicates that the container must run as a\n                            non-root user. If true, the Kubelet will validate the\n                            image at runtime to ensure that it does not run as UID\n                            0 (root) and fail to start the container if it does. If\n                            unset or false, no such validation will be performed.\n                            May also be set in PodSecurityContext.  If set in both\n                            SecurityContext and PodSecurityContext, the value specified\n                            in SecurityContext takes precedence.\n                          type: boolean\n                        runAsUser:\n                          description: The UID to run the entrypoint of the container\n                            process. Defaults to user specified in image metadata\n                            if unspecified. May also be set in PodSecurityContext.  If\n                            set in both SecurityContext and PodSecurityContext, the\n                            value specified in SecurityContext takes precedence.\n                          format: int64\n                          type: integer\n                        seLinuxOptions:\n                          description: The SELinux context to be applied to the container.\n                            If unspecified, the container runtime will allocate a\n                            random SELinux context for each container.  May also be\n                            set in PodSecurityContext.  If set in both SecurityContext\n                            and PodSecurityContext, the value specified in SecurityContext\n                            takes precedence.\n                          properties:\n                            level:\n                              description: Level is SELinux level label that applies\n                                to the container.\n                              type: string\n                            role:\n                              description: Role is a SELinux role label that applies\n                                to the container.\n                              type: string\n                            type:\n                              description: Type is a SELinux type label that applies\n                                to the container.\n                              type: string\n                            user:\n                              description: User is a SELinux user label that applies\n                                to the container.\n                              type: string\n                          type: object\n                        windowsOptions:\n                          description: The Windows specific settings applied to all\n                            containers. If unspecified, the options from the PodSecurityContext\n                            will be used. If set in both SecurityContext and PodSecurityContext,\n                            the value specified in SecurityContext takes precedence.\n                          properties:\n                            gmsaCredentialSpec:\n                              description: GMSACredentialSpec is where the GMSA admission\n                                webhook (https://github.com/kubernetes-sigs/windows-gmsa)\n                                inlines the contents of the GMSA credential spec named\n                                by the GMSACredentialSpecName field.\n                              type: string\n                            gmsaCredentialSpecName:\n                              description: GMSACredentialSpecName is the name of the\n                                GMSA credential spec to use.\n                              type: string\n                            runAsUserName:\n                              description: The UserName in Windows to run the entrypoint\n                                of the container process. Defaults to the user specified\n                                in image metadata if unspecified. May also be set\n                                in PodSecurityContext. If set in both SecurityContext\n                                and PodSecurityContext, the value specified in SecurityContext\n                                takes precedence.\n                              type: string\n                          type: object\n                      type: object\n                    startupProbe:\n                      description: 'StartupProbe indicates that the Pod has successfully\n                        initialized. If specified, no other probes are executed until\n                        this completes successfully. If this probe fails, the Pod\n                        will be restarted, just as if the livenessProbe failed. This\n                        can be used to provide different probe parameters at the beginning\n                        of a Pod''s lifecycle, when it might take a long time to load\n                        data or warm a cache, than during steady-state operation.\n                        This cannot be updated. This is a beta feature enabled by\n                        the StartupProbe feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                      properties:\n                        exec:\n                          description: One and only one of the following should be\n                            specified. Exec specifies the action to take.\n                          properties:\n                            command:\n                              description: Command is the command line to execute\n                                inside the container, the working directory for the\n                                command  is root ('/') in the container's filesystem.\n                                The command is simply exec'd, it is not run inside\n                                a shell, so traditional shell instructions ('|', etc)\n                                won't work. To use a shell, you need to explicitly\n                                call out to that shell. Exit status of 0 is treated\n                                as live/healthy and non-zero is unhealthy.\n                              items:\n                                type: string\n                              type: array\n                          type: object\n                        failureThreshold:\n                          description: Minimum consecutive failures for the probe\n                            to be considered failed after having succeeded. Defaults\n                            to 3. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        httpGet:\n                          description: HTTPGet specifies the http request to perform.\n                          properties:\n                            host:\n                              description: Host name to connect to, defaults to the\n                                pod IP. You probably want to set \"Host\" in httpHeaders\n                                instead.\n                              type: string\n                            httpHeaders:\n                              description: Custom headers to set in the request. HTTP\n                                allows repeated headers.\n                              items:\n                                description: HTTPHeader describes a custom header\n                                  to be used in HTTP probes\n                                properties:\n                                  name:\n                                    description: The header field name\n                                    type: string\n                                  value:\n                                    description: The header field value\n                                    type: string\n                                required:\n                                - name\n                                - value\n                                type: object\n                              type: array\n                            path:\n                              description: Path to access on the HTTP server.\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Name or number of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                            scheme:\n                              description: Scheme to use for connecting to the host.\n                                Defaults to HTTP.\n                              type: string\n                          required:\n                          - port\n                          type: object\n                        initialDelaySeconds:\n                          description: 'Number of seconds after the container has\n                            started before liveness probes are initiated. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                        periodSeconds:\n                          description: How often (in seconds) to perform the probe.\n                            Default to 10 seconds. Minimum value is 1.\n                          format: int32\n                          type: integer\n                        successThreshold:\n                          description: Minimum consecutive successes for the probe\n                            to be considered successful after having failed. Defaults\n                            to 1. Must be 1 for liveness and startup. Minimum value\n                            is 1.\n                          format: int32\n                          type: integer\n                        tcpSocket:\n                          description: 'TCPSocket specifies an action involving a\n                            TCP port. TCP hooks not yet supported TODO: implement\n                            a realistic TCP lifecycle hook'\n                          properties:\n                            host:\n                              description: 'Optional: Host name to connect to, defaults\n                                to the pod IP.'\n                              type: string\n                            port:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              description: Number or name of the port to access on\n                                the container. Number must be in the range 1 to 65535.\n                                Name must be an IANA_SVC_NAME.\n                              x-kubernetes-int-or-string: true\n                          required:\n                          - port\n                          type: object\n                        timeoutSeconds:\n                          description: 'Number of seconds after which the probe times\n                            out. Defaults to 1 second. Minimum value is 1. More info:\n                            https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'\n                          format: int32\n                          type: integer\n                      type: object\n                    stdin:\n                      description: Whether this container should allocate a buffer\n                        for stdin in the container runtime. If this is not set, reads\n                        from stdin in the container will always result in EOF. Default\n                        is false.\n                      type: boolean\n                    stdinOnce:\n                      description: Whether the container runtime should close the\n                        stdin channel after it has been opened by a single attach.\n                        When stdin is true the stdin stream will remain open across\n                        multiple attach sessions. If stdinOnce is set to true, stdin\n                        is opened on container start, is empty until the first client\n                        attaches to stdin, and then remains open and accepts data\n                        until the client disconnects, at which time stdin is closed\n                        and remains closed until the container is restarted. If this\n                        flag is false, a container processes that reads from stdin\n                        will never receive an EOF. Default is false\n                      type: boolean\n                    terminationMessagePath:\n                      description: 'Optional: Path at which the file to which the\n                        container''s termination message will be written is mounted\n                        into the container''s filesystem. Message written is intended\n                        to be brief final status, such as an assertion failure message.\n                        Will be truncated by the node if greater than 4096 bytes.\n                        The total message length across all containers will be limited\n                        to 12kb. Defaults to /dev/termination-log. Cannot be updated.'\n                      type: string\n                    terminationMessagePolicy:\n                      description: Indicate how the termination message should be\n                        populated. File will use the contents of terminationMessagePath\n                        to populate the container status message on both success and\n                        failure. FallbackToLogsOnError will use the last chunk of\n                        container log output if the termination message file is empty\n                        and the container exited with an error. The log output is\n                        limited to 2048 bytes or 80 lines, whichever is smaller. Defaults\n                        to File. Cannot be updated.\n                      type: string\n                    tty:\n                      description: Whether this container should allocate a TTY for\n                        itself, also requires 'stdin' to be true. Default is false.\n                      type: boolean\n                    volumeDevices:\n                      description: volumeDevices is the list of block devices to be\n                        used by the container.\n                      items:\n                        description: volumeDevice describes a mapping of a raw block\n                          device within a container.\n                        properties:\n                          devicePath:\n                            description: devicePath is the path inside of the container\n                              that the device will be mapped to.\n                            type: string\n                          name:\n                            description: name must match the name of a persistentVolumeClaim\n                              in the pod\n                            type: string\n                        required:\n                        - devicePath\n                        - name\n                        type: object\n                      type: array\n                    volumeMounts:\n                      description: Pod volumes to mount into the container's filesystem.\n                        Cannot be updated.\n                      items:\n                        description: VolumeMount describes a mounting of a Volume\n                          within a container.\n                        properties:\n                          mountPath:\n                            description: Path within the container at which the volume\n                              should be mounted.  Must not contain ':'.\n                            type: string\n                          mountPropagation:\n                            description: mountPropagation determines how mounts are\n                              propagated from the host to container and the other\n                              way around. When not set, MountPropagationNone is used.\n                              This field is beta in 1.10.\n                            type: string\n                          name:\n                            description: This must match the Name of a Volume.\n                            type: string\n                          readOnly:\n                            description: Mounted read-only if true, read-write otherwise\n                              (false or unspecified). Defaults to false.\n                            type: boolean\n                          subPath:\n                            description: Path within the volume from which the container's\n                              volume should be mounted. Defaults to \"\" (volume's root).\n                            type: string\n                          subPathExpr:\n                            description: Expanded path within the volume from which\n                              the container's volume should be mounted. Behaves similarly\n                              to SubPath but environment variable references $(VAR_NAME)\n                              are expanded using the container's environment. Defaults\n                              to \"\" (volume's root). SubPathExpr and SubPath are mutually\n                              exclusive.\n                            type: string\n                        required:\n                        - mountPath\n                        - name\n                        type: object\n                      type: array\n                    workingDir:\n                      description: Container's working directory. If not specified,\n                        the container runtime's default will be used, which might\n                        be configured in the container image. Cannot be updated.\n                      type: string\n                  required:\n                  - name\n                  type: object\n                type: array\n              labels:\n                additionalProperties:\n                  type: string\n                description: Labels configure the external label pairs to ThanosRuler.\n                  If not provided, default replica label `thanos_ruler_replica` will\n                  be added as a label and be dropped in alerts.\n                type: object\n              listenLocal:\n                description: ListenLocal makes the Thanos ruler listen on loopback,\n                  so that it does not bind against the Pod IP.\n                type: boolean\n              logFormat:\n                description: Log format for ThanosRuler to be configured with.\n                type: string\n              logLevel:\n                description: Log level for ThanosRuler to be configured with.\n                type: string\n              nodeSelector:\n                additionalProperties:\n                  type: string\n                description: Define which Nodes the Pods are scheduled on.\n                type: object\n              objectStorageConfig:\n                description: ObjectStorageConfig configures object storage in Thanos.\n                  Alternative to ObjectStorageConfigFile, and lower order priority.\n                properties:\n                  key:\n                    description: The key of the secret to select from.  Must be a\n                      valid secret key.\n                    type: string\n                  name:\n                    description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                      TODO: Add other useful fields. apiVersion, kind, uid?'\n                    type: string\n                  optional:\n                    description: Specify whether the Secret or its key must be defined\n                    type: boolean\n                required:\n                - key\n                type: object\n              objectStorageConfigFile:\n                description: ObjectStorageConfigFile specifies the path of the object\n                  storage configuration file. When used alongside with ObjectStorageConfig,\n                  ObjectStorageConfigFile takes precedence.\n                type: string\n              paused:\n                description: When a ThanosRuler deployment is paused, no actions except\n                  for deletion will be performed on the underlying objects.\n                type: boolean\n              podMetadata:\n                description: PodMetadata contains Labels and Annotations gets propagated\n                  to the thanos ruler pods.\n                properties:\n                  annotations:\n                    additionalProperties:\n                      type: string\n                    description: 'Annotations is an unstructured key value map stored\n                      with a resource that may be set by external tools to store and\n                      retrieve arbitrary metadata. They are not queryable and should\n                      be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations'\n                    type: object\n                  labels:\n                    additionalProperties:\n                      type: string\n                    description: 'Map of string keys and values that can be used to\n                      organize and categorize (scope and select) objects. May match\n                      selectors of replication controllers and services. More info:\n                      http://kubernetes.io/docs/user-guide/labels'\n                    type: object\n                  name:\n                    description: 'Name must be unique within a namespace. Is required\n                      when creating resources, although some resources may allow a\n                      client to request the generation of an appropriate name automatically.\n                      Name is primarily intended for creation idempotence and configuration\n                      definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names'\n                    type: string\n                type: object\n              portName:\n                description: Port name used for the pods and governing service. This\n                  defaults to web\n                type: string\n              priorityClassName:\n                description: Priority class assigned to the Pods\n                type: string\n              prometheusRulesExcludedFromEnforce:\n                description: PrometheusRulesExcludedFromEnforce - list of Prometheus\n                  rules to be excluded from enforcing of adding namespace labels.\n                  Works only if enforcedNamespaceLabel set to true. Make sure both\n                  ruleNamespace and ruleName are set for each pair\n                items:\n                  description: PrometheusRuleExcludeConfig enables users to configure\n                    excluded PrometheusRule names and their namespaces to be ignored\n                    while enforcing namespace label for alerts and metrics.\n                  properties:\n                    ruleName:\n                      description: RuleNamespace - name of excluded rule\n                      type: string\n                    ruleNamespace:\n                      description: RuleNamespace - namespace of excluded rule\n                      type: string\n                  required:\n                  - ruleName\n                  - ruleNamespace\n                  type: object\n                type: array\n              queryConfig:\n                description: Define configuration for connecting to thanos query instances.\n                  If this is defined, the QueryEndpoints field will be ignored. Maps\n                  to the `query.config` CLI argument. Only available with thanos v0.11.0\n                  and higher.\n                properties:\n                  key:\n                    description: The key of the secret to select from.  Must be a\n                      valid secret key.\n                    type: string\n                  name:\n                    description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                      TODO: Add other useful fields. apiVersion, kind, uid?'\n                    type: string\n                  optional:\n                    description: Specify whether the Secret or its key must be defined\n                    type: boolean\n                required:\n                - key\n                type: object\n              queryEndpoints:\n                description: QueryEndpoints defines Thanos querier endpoints from\n                  which to query metrics. Maps to the --query flag of thanos ruler.\n                items:\n                  type: string\n                type: array\n              replicas:\n                description: Number of thanos ruler instances to deploy.\n                format: int32\n                type: integer\n              resources:\n                description: Resources defines the resource requirements for single\n                  Pods. If not provided, no requests/limits will be set\n                properties:\n                  limits:\n                    additionalProperties:\n                      anyOf:\n                      - type: integer\n                      - type: string\n                      pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                      x-kubernetes-int-or-string: true\n                    description: 'Limits describes the maximum amount of compute resources\n                      allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                    type: object\n                  requests:\n                    additionalProperties:\n                      anyOf:\n                      - type: integer\n                      - type: string\n                      pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                      x-kubernetes-int-or-string: true\n                    description: 'Requests describes the minimum amount of compute\n                      resources required. If Requests is omitted for a container,\n                      it defaults to Limits if that is explicitly specified, otherwise\n                      to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                    type: object\n                type: object\n              retention:\n                description: Time duration ThanosRuler shall retain data for. Default\n                  is '24h', and must match the regular expression `[0-9]+(ms|s|m|h|d|w|y)`\n                  (milliseconds seconds minutes hours days weeks years).\n                type: string\n              routePrefix:\n                description: The route prefix ThanosRuler registers HTTP handlers\n                  for. This allows thanos UI to be served on a sub-path.\n                type: string\n              ruleNamespaceSelector:\n                description: Namespaces to be selected for Rules discovery. If unspecified,\n                  only the same namespace as the ThanosRuler object is in is used.\n                properties:\n                  matchExpressions:\n                    description: matchExpressions is a list of label selector requirements.\n                      The requirements are ANDed.\n                    items:\n                      description: A label selector requirement is a selector that\n                        contains values, a key, and an operator that relates the key\n                        and values.\n                      properties:\n                        key:\n                          description: key is the label key that the selector applies\n                            to.\n                          type: string\n                        operator:\n                          description: operator represents a key's relationship to\n                            a set of values. Valid operators are In, NotIn, Exists\n                            and DoesNotExist.\n                          type: string\n                        values:\n                          description: values is an array of string values. If the\n                            operator is In or NotIn, the values array must be non-empty.\n                            If the operator is Exists or DoesNotExist, the values\n                            array must be empty. This array is replaced during a strategic\n                            merge patch.\n                          items:\n                            type: string\n                          type: array\n                      required:\n                      - key\n                      - operator\n                      type: object\n                    type: array\n                  matchLabels:\n                    additionalProperties:\n                      type: string\n                    description: matchLabels is a map of {key,value} pairs. A single\n                      {key,value} in the matchLabels map is equivalent to an element\n                      of matchExpressions, whose key field is \"key\", the operator\n                      is \"In\", and the values array contains only \"value\". The requirements\n                      are ANDed.\n                    type: object\n                type: object\n              ruleSelector:\n                description: A label selector to select which PrometheusRules to mount\n                  for alerting and recording.\n                properties:\n                  matchExpressions:\n                    description: matchExpressions is a list of label selector requirements.\n                      The requirements are ANDed.\n                    items:\n                      description: A label selector requirement is a selector that\n                        contains values, a key, and an operator that relates the key\n                        and values.\n                      properties:\n                        key:\n                          description: key is the label key that the selector applies\n                            to.\n                          type: string\n                        operator:\n                          description: operator represents a key's relationship to\n                            a set of values. Valid operators are In, NotIn, Exists\n                            and DoesNotExist.\n                          type: string\n                        values:\n                          description: values is an array of string values. If the\n                            operator is In or NotIn, the values array must be non-empty.\n                            If the operator is Exists or DoesNotExist, the values\n                            array must be empty. This array is replaced during a strategic\n                            merge patch.\n                          items:\n                            type: string\n                          type: array\n                      required:\n                      - key\n                      - operator\n                      type: object\n                    type: array\n                  matchLabels:\n                    additionalProperties:\n                      type: string\n                    description: matchLabels is a map of {key,value} pairs. A single\n                      {key,value} in the matchLabels map is equivalent to an element\n                      of matchExpressions, whose key field is \"key\", the operator\n                      is \"In\", and the values array contains only \"value\". The requirements\n                      are ANDed.\n                    type: object\n                type: object\n              securityContext:\n                description: SecurityContext holds pod-level security attributes and\n                  common container settings. This defaults to the default PodSecurityContext.\n                properties:\n                  fsGroup:\n                    description: \"A special supplemental group that applies to all\n                      containers in a pod. Some volume types allow the Kubelet to\n                      change the ownership of that volume to be owned by the pod:\n                      \\n 1. The owning GID will be the FSGroup 2. The setgid bit is\n                      set (new files created in the volume will be owned by FSGroup)\n                      3. The permission bits are OR'd with rw-rw---- \\n If unset,\n                      the Kubelet will not modify the ownership and permissions of\n                      any volume.\"\n                    format: int64\n                    type: integer\n                  fsGroupChangePolicy:\n                    description: 'fsGroupChangePolicy defines behavior of changing\n                      ownership and permission of the volume before being exposed\n                      inside Pod. This field will only apply to volume types which\n                      support fsGroup based ownership(and permissions). It will have\n                      no effect on ephemeral volume types such as: secret, configmaps\n                      and emptydir. Valid values are \"OnRootMismatch\" and \"Always\".\n                      If not specified defaults to \"Always\".'\n                    type: string\n                  runAsGroup:\n                    description: The GID to run the entrypoint of the container process.\n                      Uses runtime default if unset. May also be set in SecurityContext.  If\n                      set in both SecurityContext and PodSecurityContext, the value\n                      specified in SecurityContext takes precedence for that container.\n                    format: int64\n                    type: integer\n                  runAsNonRoot:\n                    description: Indicates that the container must run as a non-root\n                      user. If true, the Kubelet will validate the image at runtime\n                      to ensure that it does not run as UID 0 (root) and fail to start\n                      the container if it does. If unset or false, no such validation\n                      will be performed. May also be set in SecurityContext.  If set\n                      in both SecurityContext and PodSecurityContext, the value specified\n                      in SecurityContext takes precedence.\n                    type: boolean\n                  runAsUser:\n                    description: The UID to run the entrypoint of the container process.\n                      Defaults to user specified in image metadata if unspecified.\n                      May also be set in SecurityContext.  If set in both SecurityContext\n                      and PodSecurityContext, the value specified in SecurityContext\n                      takes precedence for that container.\n                    format: int64\n                    type: integer\n                  seLinuxOptions:\n                    description: The SELinux context to be applied to all containers.\n                      If unspecified, the container runtime will allocate a random\n                      SELinux context for each container.  May also be set in SecurityContext.  If\n                      set in both SecurityContext and PodSecurityContext, the value\n                      specified in SecurityContext takes precedence for that container.\n                    properties:\n                      level:\n                        description: Level is SELinux level label that applies to\n                          the container.\n                        type: string\n                      role:\n                        description: Role is a SELinux role label that applies to\n                          the container.\n                        type: string\n                      type:\n                        description: Type is a SELinux type label that applies to\n                          the container.\n                        type: string\n                      user:\n                        description: User is a SELinux user label that applies to\n                          the container.\n                        type: string\n                    type: object\n                  supplementalGroups:\n                    description: A list of groups applied to the first process run\n                      in each container, in addition to the container's primary GID.  If\n                      unspecified, no groups will be added to any container.\n                    items:\n                      format: int64\n                      type: integer\n                    type: array\n                  sysctls:\n                    description: Sysctls hold a list of namespaced sysctls used for\n                      the pod. Pods with unsupported sysctls (by the container runtime)\n                      might fail to launch.\n                    items:\n                      description: Sysctl defines a kernel parameter to be set\n                      properties:\n                        name:\n                          description: Name of a property to set\n                          type: string\n                        value:\n                          description: Value of a property to set\n                          type: string\n                      required:\n                      - name\n                      - value\n                      type: object\n                    type: array\n                  windowsOptions:\n                    description: The Windows specific settings applied to all containers.\n                      If unspecified, the options within a container's SecurityContext\n                      will be used. If set in both SecurityContext and PodSecurityContext,\n                      the value specified in SecurityContext takes precedence.\n                    properties:\n                      gmsaCredentialSpec:\n                        description: GMSACredentialSpec is where the GMSA admission\n                          webhook (https://github.com/kubernetes-sigs/windows-gmsa)\n                          inlines the contents of the GMSA credential spec named by\n                          the GMSACredentialSpecName field.\n                        type: string\n                      gmsaCredentialSpecName:\n                        description: GMSACredentialSpecName is the name of the GMSA\n                          credential spec to use.\n                        type: string\n                      runAsUserName:\n                        description: The UserName in Windows to run the entrypoint\n                          of the container process. Defaults to the user specified\n                          in image metadata if unspecified. May also be set in PodSecurityContext.\n                          If set in both SecurityContext and PodSecurityContext, the\n                          value specified in SecurityContext takes precedence.\n                        type: string\n                    type: object\n                type: object\n              serviceAccountName:\n                description: ServiceAccountName is the name of the ServiceAccount\n                  to use to run the Thanos Ruler Pods.\n                type: string\n              storage:\n                description: Storage spec to specify how storage shall be used.\n                properties:\n                  disableMountSubPath:\n                    description: 'Deprecated: subPath usage will be disabled by default\n                      in a future release, this option will become unnecessary. DisableMountSubPath\n                      allows to remove any subPath usage in volume mounts.'\n                    type: boolean\n                  emptyDir:\n                    description: 'EmptyDirVolumeSource to be used by the Prometheus\n                      StatefulSets. If specified, used in place of any volumeClaimTemplate.\n                      More info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir'\n                    properties:\n                      medium:\n                        description: 'What type of storage medium should back this\n                          directory. The default is \"\" which means to use the node''s\n                          default medium. Must be an empty string (default) or Memory.\n                          More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir'\n                        type: string\n                      sizeLimit:\n                        anyOf:\n                        - type: integer\n                        - type: string\n                        description: 'Total amount of local storage required for this\n                          EmptyDir volume. The size limit is also applicable for memory\n                          medium. The maximum usage on memory medium EmptyDir would\n                          be the minimum value between the SizeLimit specified here\n                          and the sum of memory limits of all containers in a pod.\n                          The default is nil which means that the limit is undefined.\n                          More info: http://kubernetes.io/docs/user-guide/volumes#emptydir'\n                        pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                        x-kubernetes-int-or-string: true\n                    type: object\n                  volumeClaimTemplate:\n                    description: A PVC spec to be used by the Prometheus StatefulSets.\n                    properties:\n                      apiVersion:\n                        description: 'APIVersion defines the versioned schema of this\n                          representation of an object. Servers should convert recognized\n                          schemas to the latest internal value, and may reject unrecognized\n                          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\n                          resource this object represents. Servers may infer this\n                          from the endpoint the client submits requests to. Cannot\n                          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                        description: EmbeddedMetadata contains metadata relevant to\n                          an EmbeddedResource.\n                        properties:\n                          annotations:\n                            additionalProperties:\n                              type: string\n                            description: 'Annotations is an unstructured key value\n                              map stored with a resource that may be set by external\n                              tools to store and retrieve arbitrary metadata. They\n                              are not queryable and should be preserved when modifying\n                              objects. More info: http://kubernetes.io/docs/user-guide/annotations'\n                            type: object\n                          labels:\n                            additionalProperties:\n                              type: string\n                            description: 'Map of string keys and values that can be\n                              used to organize and categorize (scope and select) objects.\n                              May match selectors of replication controllers and services.\n                              More info: http://kubernetes.io/docs/user-guide/labels'\n                            type: object\n                          name:\n                            description: 'Name must be unique within a namespace.\n                              Is required when creating resources, although some resources\n                              may allow a client to request the generation of an appropriate\n                              name automatically. Name is primarily intended for creation\n                              idempotence and configuration definition. Cannot be\n                              updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names'\n                            type: string\n                        type: object\n                      spec:\n                        description: 'Spec defines the desired characteristics of\n                          a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'\n                        properties:\n                          accessModes:\n                            description: 'AccessModes contains the desired access\n                              modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'\n                            items:\n                              type: string\n                            type: array\n                          dataSource:\n                            description: 'This field can be used to specify either:\n                              * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot\n                              - Beta) * An existing PVC (PersistentVolumeClaim) *\n                              An existing custom resource/object that implements data\n                              population (Alpha) In order to use VolumeSnapshot object\n                              types, the appropriate feature gate must be enabled\n                              (VolumeSnapshotDataSource or AnyVolumeDataSource) If\n                              the provisioner or an external controller can support\n                              the specified data source, it will create a new volume\n                              based on the contents of the specified data source.\n                              If the specified data source is not supported, the volume\n                              will not be created and the failure will be reported\n                              as an event. In the future, we plan to support more\n                              data source types and the behavior of the provisioner\n                              may change.'\n                            properties:\n                              apiGroup:\n                                description: APIGroup is the group for the resource\n                                  being referenced. If APIGroup is not specified,\n                                  the specified Kind must be in the core API group.\n                                  For any other third-party types, APIGroup is required.\n                                type: string\n                              kind:\n                                description: Kind is the type of resource being referenced\n                                type: string\n                              name:\n                                description: Name is the name of resource being referenced\n                                type: string\n                            required:\n                            - kind\n                            - name\n                            type: object\n                          resources:\n                            description: 'Resources represents the minimum resources\n                              the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources'\n                            properties:\n                              limits:\n                                additionalProperties:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                  x-kubernetes-int-or-string: true\n                                description: 'Limits describes the maximum amount\n                                  of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                                type: object\n                              requests:\n                                additionalProperties:\n                                  anyOf:\n                                  - type: integer\n                                  - type: string\n                                  pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                  x-kubernetes-int-or-string: true\n                                description: 'Requests describes the minimum amount\n                                  of compute resources required. If Requests is omitted\n                                  for a container, it defaults to Limits if that is\n                                  explicitly specified, otherwise to an implementation-defined\n                                  value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'\n                                type: object\n                            type: object\n                          selector:\n                            description: A label query over volumes to consider for\n                              binding.\n                            properties:\n                              matchExpressions:\n                                description: matchExpressions is a list of label selector\n                                  requirements. The requirements are ANDed.\n                                items:\n                                  description: A label selector requirement is a selector\n                                    that contains values, a key, and an operator that\n                                    relates the key and values.\n                                  properties:\n                                    key:\n                                      description: key is the label key that the selector\n                                        applies to.\n                                      type: string\n                                    operator:\n                                      description: operator represents a key's relationship\n                                        to a set of values. Valid operators are In,\n                                        NotIn, Exists and DoesNotExist.\n                                      type: string\n                                    values:\n                                      description: values is an array of string values.\n                                        If the operator is In or NotIn, the values\n                                        array must be non-empty. If the operator is\n                                        Exists or DoesNotExist, the values array must\n                                        be empty. This array is replaced during a\n                                        strategic merge patch.\n                                      items:\n                                        type: string\n                                      type: array\n                                  required:\n                                  - key\n                                  - operator\n                                  type: object\n                                type: array\n                              matchLabels:\n                                additionalProperties:\n                                  type: string\n                                description: matchLabels is a map of {key,value} pairs.\n                                  A single {key,value} in the matchLabels map is equivalent\n                                  to an element of matchExpressions, whose key field\n                                  is \"key\", the operator is \"In\", and the values array\n                                  contains only \"value\". The requirements are ANDed.\n                                type: object\n                            type: object\n                          storageClassName:\n                            description: 'Name of the StorageClass required by the\n                              claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1'\n                            type: string\n                          volumeMode:\n                            description: volumeMode defines what type of volume is\n                              required by the claim. Value of Filesystem is implied\n                              when not included in claim spec.\n                            type: string\n                          volumeName:\n                            description: VolumeName is the binding reference to the\n                              PersistentVolume backing this claim.\n                            type: string\n                        type: object\n                      status:\n                        description: 'Status represents the current information/status\n                          of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'\n                        properties:\n                          accessModes:\n                            description: 'AccessModes contains the actual access modes\n                              the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'\n                            items:\n                              type: string\n                            type: array\n                          capacity:\n                            additionalProperties:\n                              anyOf:\n                              - type: integer\n                              - type: string\n                              pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                              x-kubernetes-int-or-string: true\n                            description: Represents the actual resources of the underlying\n                              volume.\n                            type: object\n                          conditions:\n                            description: Current Condition of persistent volume claim.\n                              If underlying persistent volume is being resized then\n                              the Condition will be set to 'ResizeStarted'.\n                            items:\n                              description: PersistentVolumeClaimCondition contails\n                                details about state of pvc\n                              properties:\n                                lastProbeTime:\n                                  description: Last time we probed the condition.\n                                  format: date-time\n                                  type: string\n                                lastTransitionTime:\n                                  description: Last time the condition transitioned\n                                    from one status to another.\n                                  format: date-time\n                                  type: string\n                                message:\n                                  description: Human-readable message indicating details\n                                    about last transition.\n                                  type: string\n                                reason:\n                                  description: Unique, this should be a short, machine\n                                    understandable string that gives the reason for\n                                    condition's last transition. If it reports \"ResizeStarted\"\n                                    that means the underlying persistent volume is\n                                    being resized.\n                                  type: string\n                                status:\n                                  type: string\n                                type:\n                                  description: PersistentVolumeClaimConditionType\n                                    is a valid value of PersistentVolumeClaimCondition.Type\n                                  type: string\n                              required:\n                              - status\n                              - type\n                              type: object\n                            type: array\n                          phase:\n                            description: Phase represents the current phase of PersistentVolumeClaim.\n                            type: string\n                        type: object\n                    type: object\n                type: object\n              tolerations:\n                description: If specified, the pod's tolerations.\n                items:\n                  description: The pod this Toleration is attached to tolerates any\n                    taint that matches the triple <key,value,effect> using the matching\n                    operator <operator>.\n                  properties:\n                    effect:\n                      description: Effect indicates the taint effect to match. Empty\n                        means match all taint effects. When specified, allowed values\n                        are NoSchedule, PreferNoSchedule and NoExecute.\n                      type: string\n                    key:\n                      description: Key is the taint key that the toleration applies\n                        to. Empty means match all taint keys. If the key is empty,\n                        operator must be Exists; this combination means to match all\n                        values and all keys.\n                      type: string\n                    operator:\n                      description: Operator represents a key's relationship to the\n                        value. Valid operators are Exists and Equal. Defaults to Equal.\n                        Exists is equivalent to wildcard for value, so that a pod\n                        can tolerate all taints of a particular category.\n                      type: string\n                    tolerationSeconds:\n                      description: TolerationSeconds represents the period of time\n                        the toleration (which must be of effect NoExecute, otherwise\n                        this field is ignored) tolerates the taint. By default, it\n                        is not set, which means tolerate the taint forever (do not\n                        evict). Zero and negative values will be treated as 0 (evict\n                        immediately) by the system.\n                      format: int64\n                      type: integer\n                    value:\n                      description: Value is the taint value the toleration matches\n                        to. If the operator is Exists, the value should be empty,\n                        otherwise just a regular string.\n                      type: string\n                  type: object\n                type: array\n              topologySpreadConstraints:\n                description: If specified, the pod's topology spread constraints.\n                items:\n                  description: TopologySpreadConstraint specifies how to spread matching\n                    pods among the given topology.\n                  properties:\n                    labelSelector:\n                      description: LabelSelector is used to find matching pods. Pods\n                        that match this label selector are counted to determine the\n                        number of pods in their corresponding topology domain.\n                      properties:\n                        matchExpressions:\n                          description: matchExpressions is a list of label selector\n                            requirements. The requirements are ANDed.\n                          items:\n                            description: A label selector requirement is a selector\n                              that contains values, a key, and an operator that relates\n                              the key and values.\n                            properties:\n                              key:\n                                description: key is the label key that the selector\n                                  applies to.\n                                type: string\n                              operator:\n                                description: operator represents a key's relationship\n                                  to a set of values. Valid operators are In, NotIn,\n                                  Exists and DoesNotExist.\n                                type: string\n                              values:\n                                description: values is an array of string values.\n                                  If the operator is In or NotIn, the values array\n                                  must be non-empty. If the operator is Exists or\n                                  DoesNotExist, the values array must be empty. This\n                                  array is replaced during a strategic merge patch.\n                                items:\n                                  type: string\n                                type: array\n                            required:\n                            - key\n                            - operator\n                            type: object\n                          type: array\n                        matchLabels:\n                          additionalProperties:\n                            type: string\n                          description: matchLabels is a map of {key,value} pairs.\n                            A single {key,value} in the matchLabels map is equivalent\n                            to an element of matchExpressions, whose key field is\n                            \"key\", the operator is \"In\", and the values array contains\n                            only \"value\". The requirements are ANDed.\n                          type: object\n                      type: object\n                    maxSkew:\n                      description: 'MaxSkew describes the degree to which pods may\n                        be unevenly distributed. It''s the maximum permitted difference\n                        between the number of matching pods in any two topology domains\n                        of a given topology type. For example, in a 3-zone cluster,\n                        MaxSkew is set to 1, and pods with the same labelSelector\n                        spread as 1/1/0: | zone1 | zone2 | zone3 | |   P   |   P   |       |\n                        - if MaxSkew is 1, incoming pod can only be scheduled to zone3\n                        to become 1/1/1; scheduling it onto zone1(zone2) would make\n                        the ActualSkew(2-0) on zone1(zone2) violate MaxSkew(1). -\n                        if MaxSkew is 2, incoming pod can be scheduled onto any zone.\n                        It''s a required field. Default value is 1 and 0 is not allowed.'\n                      format: int32\n                      type: integer\n                    topologyKey:\n                      description: TopologyKey is the key of node labels. Nodes that\n                        have a label with this key and identical values are considered\n                        to be in the same topology. We consider each <key, value>\n                        as a \"bucket\", and try to put balanced number of pods into\n                        each bucket. It's a required field.\n                      type: string\n                    whenUnsatisfiable:\n                      description: 'WhenUnsatisfiable indicates how to deal with a\n                        pod if it doesn''t satisfy the spread constraint. - DoNotSchedule\n                        (default) tells the scheduler not to schedule it - ScheduleAnyway\n                        tells the scheduler to still schedule it It''s considered\n                        as \"Unsatisfiable\" if and only if placing incoming pod on\n                        any topology violates \"MaxSkew\". For example, in a 3-zone\n                        cluster, MaxSkew is set to 1, and pods with the same labelSelector\n                        spread as 3/1/1: | zone1 | zone2 | zone3 | | P P P |   P   |   P   |\n                        If WhenUnsatisfiable is set to DoNotSchedule, incoming pod\n                        can only be scheduled to zone2(zone3) to become 3/2/1(3/1/2)\n                        as ActualSkew(2-1) on zone2(zone3) satisfies MaxSkew(1). In\n                        other words, the cluster can still be imbalanced, but scheduler\n                        won''t make it *more* imbalanced. It''s a required field.'\n                      type: string\n                  required:\n                  - maxSkew\n                  - topologyKey\n                  - whenUnsatisfiable\n                  type: object\n                type: array\n              tracingConfig:\n                description: TracingConfig configures tracing in Thanos. This is an\n                  experimental feature, it may change in any upcoming release in a\n                  breaking way.\n                properties:\n                  key:\n                    description: The key of the secret to select from.  Must be a\n                      valid secret key.\n                    type: string\n                  name:\n                    description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                      TODO: Add other useful fields. apiVersion, kind, uid?'\n                    type: string\n                  optional:\n                    description: Specify whether the Secret or its key must be defined\n                    type: boolean\n                required:\n                - key\n                type: object\n              volumes:\n                description: Volumes allows configuration of additional volumes on\n                  the output StatefulSet definition. Volumes specified will be appended\n                  to other volumes that are generated as a result of StorageSpec objects.\n                items:\n                  description: Volume represents a named volume in a pod that may\n                    be accessed by any container in the pod.\n                  properties:\n                    awsElasticBlockStore:\n                      description: 'AWSElasticBlockStore represents an AWS Disk resource\n                        that is attached to a kubelet''s host machine and then exposed\n                        to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore'\n                      properties:\n                        fsType:\n                          description: 'Filesystem type of the volume that you want\n                            to mount. Tip: Ensure that the filesystem type is supported\n                            by the host operating system. Examples: \"ext4\", \"xfs\",\n                            \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore\n                            TODO: how do we prevent errors in the filesystem from\n                            compromising the machine'\n                          type: string\n                        partition:\n                          description: 'The partition in the volume that you want\n                            to mount. If omitted, the default is to mount by volume\n                            name. Examples: For volume /dev/sda1, you specify the\n                            partition as \"1\". Similarly, the volume partition for\n                            /dev/sda is \"0\" (or you can leave the property empty).'\n                          format: int32\n                          type: integer\n                        readOnly:\n                          description: 'Specify \"true\" to force and set the ReadOnly\n                            property in VolumeMounts to \"true\". If omitted, the default\n                            is \"false\". More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore'\n                          type: boolean\n                        volumeID:\n                          description: 'Unique ID of the persistent disk resource\n                            in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore'\n                          type: string\n                      required:\n                      - volumeID\n                      type: object\n                    azureDisk:\n                      description: AzureDisk represents an Azure Data Disk mount on\n                        the host and bind mount to the pod.\n                      properties:\n                        cachingMode:\n                          description: 'Host Caching mode: None, Read Only, Read Write.'\n                          type: string\n                        diskName:\n                          description: The Name of the data disk in the blob storage\n                          type: string\n                        diskURI:\n                          description: The URI the data disk in the blob storage\n                          type: string\n                        fsType:\n                          description: Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                          type: string\n                        kind:\n                          description: 'Expected values Shared: multiple blob disks\n                            per storage account  Dedicated: single blob disk per storage\n                            account  Managed: azure managed data disk (only in managed\n                            availability set). defaults to shared'\n                          type: string\n                        readOnly:\n                          description: Defaults to false (read/write). ReadOnly here\n                            will force the ReadOnly setting in VolumeMounts.\n                          type: boolean\n                      required:\n                      - diskName\n                      - diskURI\n                      type: object\n                    azureFile:\n                      description: AzureFile represents an Azure File Service mount\n                        on the host and bind mount to the pod.\n                      properties:\n                        readOnly:\n                          description: Defaults to false (read/write). ReadOnly here\n                            will force the ReadOnly setting in VolumeMounts.\n                          type: boolean\n                        secretName:\n                          description: the name of secret that contains Azure Storage\n                            Account Name and Key\n                          type: string\n                        shareName:\n                          description: Share Name\n                          type: string\n                      required:\n                      - secretName\n                      - shareName\n                      type: object\n                    cephfs:\n                      description: CephFS represents a Ceph FS mount on the host that\n                        shares a pod's lifetime\n                      properties:\n                        monitors:\n                          description: 'Required: Monitors is a collection of Ceph\n                            monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it'\n                          items:\n                            type: string\n                          type: array\n                        path:\n                          description: 'Optional: Used as the mounted root, rather\n                            than the full Ceph tree, default is /'\n                          type: string\n                        readOnly:\n                          description: 'Optional: Defaults to false (read/write).\n                            ReadOnly here will force the ReadOnly setting in VolumeMounts.\n                            More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it'\n                          type: boolean\n                        secretFile:\n                          description: 'Optional: SecretFile is the path to key ring\n                            for User, default is /etc/ceph/user.secret More info:\n                            https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it'\n                          type: string\n                        secretRef:\n                          description: 'Optional: SecretRef is reference to the authentication\n                            secret for User, default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it'\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        user:\n                          description: 'Optional: User is the rados user name, default\n                            is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it'\n                          type: string\n                      required:\n                      - monitors\n                      type: object\n                    cinder:\n                      description: 'Cinder represents a cinder volume attached and\n                        mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md'\n                      properties:\n                        fsType:\n                          description: 'Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Examples:\n                            \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\"\n                            if unspecified. More info: https://examples.k8s.io/mysql-cinder-pd/README.md'\n                          type: string\n                        readOnly:\n                          description: 'Optional: Defaults to false (read/write).\n                            ReadOnly here will force the ReadOnly setting in VolumeMounts.\n                            More info: https://examples.k8s.io/mysql-cinder-pd/README.md'\n                          type: boolean\n                        secretRef:\n                          description: 'Optional: points to a secret object containing\n                            parameters used to connect to OpenStack.'\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        volumeID:\n                          description: 'volume id used to identify the volume in cinder.\n                            More info: https://examples.k8s.io/mysql-cinder-pd/README.md'\n                          type: string\n                      required:\n                      - volumeID\n                      type: object\n                    configMap:\n                      description: ConfigMap represents a configMap that should populate\n                        this volume\n                      properties:\n                        defaultMode:\n                          description: 'Optional: mode bits to use on created files\n                            by default. Must be a value between 0 and 0777. Defaults\n                            to 0644. Directories within the path are not affected\n                            by this setting. This might be in conflict with other\n                            options that affect the file mode, like fsGroup, and the\n                            result can be other mode bits set.'\n                          format: int32\n                          type: integer\n                        items:\n                          description: If unspecified, each key-value pair in the\n                            Data field of the referenced ConfigMap will be projected\n                            into the volume as a file whose name is the key and content\n                            is the value. If specified, the listed keys will be projected\n                            into the specified paths, and unlisted keys will not be\n                            present. If a key is specified which is not present in\n                            the ConfigMap, the volume setup will error unless it is\n                            marked optional. Paths must be relative and may not contain\n                            the '..' path or start with '..'.\n                          items:\n                            description: Maps a string key to a path within a volume.\n                            properties:\n                              key:\n                                description: The key to project.\n                                type: string\n                              mode:\n                                description: 'Optional: mode bits to use on this file,\n                                  must be a value between 0 and 0777. If not specified,\n                                  the volume defaultMode will be used. This might\n                                  be in conflict with other options that affect the\n                                  file mode, like fsGroup, and the result can be other\n                                  mode bits set.'\n                                format: int32\n                                type: integer\n                              path:\n                                description: The relative path of the file to map\n                                  the key to. May not be an absolute path. May not\n                                  contain the path element '..'. May not start with\n                                  the string '..'.\n                                type: string\n                            required:\n                            - key\n                            - path\n                            type: object\n                          type: array\n                        name:\n                          description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                            TODO: Add other useful fields. apiVersion, kind, uid?'\n                          type: string\n                        optional:\n                          description: Specify whether the ConfigMap or its keys must\n                            be defined\n                          type: boolean\n                      type: object\n                    csi:\n                      description: CSI (Container Storage Interface) represents storage\n                        that is handled by an external CSI driver (Alpha feature).\n                      properties:\n                        driver:\n                          description: Driver is the name of the CSI driver that handles\n                            this volume. Consult with your admin for the correct name\n                            as registered in the cluster.\n                          type: string\n                        fsType:\n                          description: Filesystem type to mount. Ex. \"ext4\", \"xfs\",\n                            \"ntfs\". If not provided, the empty value is passed to\n                            the associated CSI driver which will determine the default\n                            filesystem to apply.\n                          type: string\n                        nodePublishSecretRef:\n                          description: NodePublishSecretRef is a reference to the\n                            secret object containing sensitive information to pass\n                            to the CSI driver to complete the CSI NodePublishVolume\n                            and NodeUnpublishVolume calls. This field is optional,\n                            and  may be empty if no secret is required. If the secret\n                            object contains more than one secret, all secret references\n                            are passed.\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        readOnly:\n                          description: Specifies a read-only configuration for the\n                            volume. Defaults to false (read/write).\n                          type: boolean\n                        volumeAttributes:\n                          additionalProperties:\n                            type: string\n                          description: VolumeAttributes stores driver-specific properties\n                            that are passed to the CSI driver. Consult your driver's\n                            documentation for supported values.\n                          type: object\n                      required:\n                      - driver\n                      type: object\n                    downwardAPI:\n                      description: DownwardAPI represents downward API about the pod\n                        that should populate this volume\n                      properties:\n                        defaultMode:\n                          description: 'Optional: mode bits to use on created files\n                            by default. Must be a value between 0 and 0777. Defaults\n                            to 0644. Directories within the path are not affected\n                            by this setting. This might be in conflict with other\n                            options that affect the file mode, like fsGroup, and the\n                            result can be other mode bits set.'\n                          format: int32\n                          type: integer\n                        items:\n                          description: Items is a list of downward API volume file\n                          items:\n                            description: DownwardAPIVolumeFile represents information\n                              to create the file containing the pod field\n                            properties:\n                              fieldRef:\n                                description: 'Required: Selects a field of the pod:\n                                  only annotations, labels, name and namespace are\n                                  supported.'\n                                properties:\n                                  apiVersion:\n                                    description: Version of the schema the FieldPath\n                                      is written in terms of, defaults to \"v1\".\n                                    type: string\n                                  fieldPath:\n                                    description: Path of the field to select in the\n                                      specified API version.\n                                    type: string\n                                required:\n                                - fieldPath\n                                type: object\n                              mode:\n                                description: 'Optional: mode bits to use on this file,\n                                  must be a value between 0 and 0777. If not specified,\n                                  the volume defaultMode will be used. This might\n                                  be in conflict with other options that affect the\n                                  file mode, like fsGroup, and the result can be other\n                                  mode bits set.'\n                                format: int32\n                                type: integer\n                              path:\n                                description: 'Required: Path is  the relative path\n                                  name of the file to be created. Must not be absolute\n                                  or contain the ''..'' path. Must be utf-8 encoded.\n                                  The first item of the relative path must not start\n                                  with ''..'''\n                                type: string\n                              resourceFieldRef:\n                                description: 'Selects a resource of the container:\n                                  only resources limits and requests (limits.cpu,\n                                  limits.memory, requests.cpu and requests.memory)\n                                  are currently supported.'\n                                properties:\n                                  containerName:\n                                    description: 'Container name: required for volumes,\n                                      optional for env vars'\n                                    type: string\n                                  divisor:\n                                    anyOf:\n                                    - type: integer\n                                    - type: string\n                                    description: Specifies the output format of the\n                                      exposed resources, defaults to \"1\"\n                                    pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                    x-kubernetes-int-or-string: true\n                                  resource:\n                                    description: 'Required: resource to select'\n                                    type: string\n                                required:\n                                - resource\n                                type: object\n                            required:\n                            - path\n                            type: object\n                          type: array\n                      type: object\n                    emptyDir:\n                      description: 'EmptyDir represents a temporary directory that\n                        shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir'\n                      properties:\n                        medium:\n                          description: 'What type of storage medium should back this\n                            directory. The default is \"\" which means to use the node''s\n                            default medium. Must be an empty string (default) or Memory.\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir'\n                          type: string\n                        sizeLimit:\n                          anyOf:\n                          - type: integer\n                          - type: string\n                          description: 'Total amount of local storage required for\n                            this EmptyDir volume. The size limit is also applicable\n                            for memory medium. The maximum usage on memory medium\n                            EmptyDir would be the minimum value between the SizeLimit\n                            specified here and the sum of memory limits of all containers\n                            in a pod. The default is nil which means that the limit\n                            is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir'\n                          pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                          x-kubernetes-int-or-string: true\n                      type: object\n                    fc:\n                      description: FC represents a Fibre Channel resource that is\n                        attached to a kubelet's host machine and then exposed to the\n                        pod.\n                      properties:\n                        fsType:\n                          description: 'Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                            TODO: how do we prevent errors in the filesystem from\n                            compromising the machine'\n                          type: string\n                        lun:\n                          description: 'Optional: FC target lun number'\n                          format: int32\n                          type: integer\n                        readOnly:\n                          description: 'Optional: Defaults to false (read/write).\n                            ReadOnly here will force the ReadOnly setting in VolumeMounts.'\n                          type: boolean\n                        targetWWNs:\n                          description: 'Optional: FC target worldwide names (WWNs)'\n                          items:\n                            type: string\n                          type: array\n                        wwids:\n                          description: 'Optional: FC volume world wide identifiers\n                            (wwids) Either wwids or combination of targetWWNs and\n                            lun must be set, but not both simultaneously.'\n                          items:\n                            type: string\n                          type: array\n                      type: object\n                    flexVolume:\n                      description: FlexVolume represents a generic volume resource\n                        that is provisioned/attached using an exec based plugin.\n                      properties:\n                        driver:\n                          description: Driver is the name of the driver to use for\n                            this volume.\n                          type: string\n                        fsType:\n                          description: Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". The default filesystem depends on FlexVolume\n                            script.\n                          type: string\n                        options:\n                          additionalProperties:\n                            type: string\n                          description: 'Optional: Extra command options if any.'\n                          type: object\n                        readOnly:\n                          description: 'Optional: Defaults to false (read/write).\n                            ReadOnly here will force the ReadOnly setting in VolumeMounts.'\n                          type: boolean\n                        secretRef:\n                          description: 'Optional: SecretRef is reference to the secret\n                            object containing sensitive information to pass to the\n                            plugin scripts. This may be empty if no secret object\n                            is specified. If the secret object contains more than\n                            one secret, all secrets are passed to the plugin scripts.'\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                      required:\n                      - driver\n                      type: object\n                    flocker:\n                      description: Flocker represents a Flocker volume attached to\n                        a kubelet's host machine. This depends on the Flocker control\n                        service being running\n                      properties:\n                        datasetName:\n                          description: Name of the dataset stored as metadata -> name\n                            on the dataset for Flocker should be considered as deprecated\n                          type: string\n                        datasetUUID:\n                          description: UUID of the dataset. This is unique identifier\n                            of a Flocker dataset\n                          type: string\n                      type: object\n                    gcePersistentDisk:\n                      description: 'GCEPersistentDisk represents a GCE Disk resource\n                        that is attached to a kubelet''s host machine and then exposed\n                        to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk'\n                      properties:\n                        fsType:\n                          description: 'Filesystem type of the volume that you want\n                            to mount. Tip: Ensure that the filesystem type is supported\n                            by the host operating system. Examples: \"ext4\", \"xfs\",\n                            \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk\n                            TODO: how do we prevent errors in the filesystem from\n                            compromising the machine'\n                          type: string\n                        partition:\n                          description: 'The partition in the volume that you want\n                            to mount. If omitted, the default is to mount by volume\n                            name. Examples: For volume /dev/sda1, you specify the\n                            partition as \"1\". Similarly, the volume partition for\n                            /dev/sda is \"0\" (or you can leave the property empty).\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk'\n                          format: int32\n                          type: integer\n                        pdName:\n                          description: 'Unique name of the PD resource in GCE. Used\n                            to identify the disk in GCE. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk'\n                          type: string\n                        readOnly:\n                          description: 'ReadOnly here will force the ReadOnly setting\n                            in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk'\n                          type: boolean\n                      required:\n                      - pdName\n                      type: object\n                    gitRepo:\n                      description: 'GitRepo represents a git repository at a particular\n                        revision. DEPRECATED: GitRepo is deprecated. To provision\n                        a container with a git repo, mount an EmptyDir into an InitContainer\n                        that clones the repo using git, then mount the EmptyDir into\n                        the Pod''s container.'\n                      properties:\n                        directory:\n                          description: Target directory name. Must not contain or\n                            start with '..'.  If '.' is supplied, the volume directory\n                            will be the git repository.  Otherwise, if specified,\n                            the volume will contain the git repository in the subdirectory\n                            with the given name.\n                          type: string\n                        repository:\n                          description: Repository URL\n                          type: string\n                        revision:\n                          description: Commit hash for the specified revision.\n                          type: string\n                      required:\n                      - repository\n                      type: object\n                    glusterfs:\n                      description: 'Glusterfs represents a Glusterfs mount on the\n                        host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md'\n                      properties:\n                        endpoints:\n                          description: 'EndpointsName is the endpoint name that details\n                            Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod'\n                          type: string\n                        path:\n                          description: 'Path is the Glusterfs volume path. More info:\n                            https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod'\n                          type: string\n                        readOnly:\n                          description: 'ReadOnly here will force the Glusterfs volume\n                            to be mounted with read-only permissions. Defaults to\n                            false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod'\n                          type: boolean\n                      required:\n                      - endpoints\n                      - path\n                      type: object\n                    hostPath:\n                      description: 'HostPath represents a pre-existing file or directory\n                        on the host machine that is directly exposed to the container.\n                        This is generally used for system agents or other privileged\n                        things that are allowed to see the host machine. Most containers\n                        will NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath\n                        --- TODO(jonesdl) We need to restrict who can use host directory\n                        mounts and who can/can not mount host directories as read/write.'\n                      properties:\n                        path:\n                          description: 'Path of the directory on the host. If the\n                            path is a symlink, it will follow the link to the real\n                            path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath'\n                          type: string\n                        type:\n                          description: 'Type for HostPath Volume Defaults to \"\" More\n                            info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath'\n                          type: string\n                      required:\n                      - path\n                      type: object\n                    iscsi:\n                      description: 'ISCSI represents an ISCSI Disk resource that is\n                        attached to a kubelet''s host machine and then exposed to\n                        the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md'\n                      properties:\n                        chapAuthDiscovery:\n                          description: whether support iSCSI Discovery CHAP authentication\n                          type: boolean\n                        chapAuthSession:\n                          description: whether support iSCSI Session CHAP authentication\n                          type: boolean\n                        fsType:\n                          description: 'Filesystem type of the volume that you want\n                            to mount. Tip: Ensure that the filesystem type is supported\n                            by the host operating system. Examples: \"ext4\", \"xfs\",\n                            \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi\n                            TODO: how do we prevent errors in the filesystem from\n                            compromising the machine'\n                          type: string\n                        initiatorName:\n                          description: Custom iSCSI Initiator Name. If initiatorName\n                            is specified with iscsiInterface simultaneously, new iSCSI\n                            interface <target portal>:<volume name> will be created\n                            for the connection.\n                          type: string\n                        iqn:\n                          description: Target iSCSI Qualified Name.\n                          type: string\n                        iscsiInterface:\n                          description: iSCSI Interface Name that uses an iSCSI transport.\n                            Defaults to 'default' (tcp).\n                          type: string\n                        lun:\n                          description: iSCSI Target Lun number.\n                          format: int32\n                          type: integer\n                        portals:\n                          description: iSCSI Target Portal List. The portal is either\n                            an IP or ip_addr:port if the port is other than default\n                            (typically TCP ports 860 and 3260).\n                          items:\n                            type: string\n                          type: array\n                        readOnly:\n                          description: ReadOnly here will force the ReadOnly setting\n                            in VolumeMounts. Defaults to false.\n                          type: boolean\n                        secretRef:\n                          description: CHAP Secret for iSCSI target and initiator\n                            authentication\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        targetPortal:\n                          description: iSCSI Target Portal. The Portal is either an\n                            IP or ip_addr:port if the port is other than default (typically\n                            TCP ports 860 and 3260).\n                          type: string\n                      required:\n                      - iqn\n                      - lun\n                      - targetPortal\n                      type: object\n                    name:\n                      description: 'Volume''s name. Must be a DNS_LABEL and unique\n                        within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'\n                      type: string\n                    nfs:\n                      description: 'NFS represents an NFS mount on the host that shares\n                        a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs'\n                      properties:\n                        path:\n                          description: 'Path that is exported by the NFS server. More\n                            info: https://kubernetes.io/docs/concepts/storage/volumes#nfs'\n                          type: string\n                        readOnly:\n                          description: 'ReadOnly here will force the NFS export to\n                            be mounted with read-only permissions. Defaults to false.\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs'\n                          type: boolean\n                        server:\n                          description: 'Server is the hostname or IP address of the\n                            NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs'\n                          type: string\n                      required:\n                      - path\n                      - server\n                      type: object\n                    persistentVolumeClaim:\n                      description: 'PersistentVolumeClaimVolumeSource represents a\n                        reference to a PersistentVolumeClaim in the same namespace.\n                        More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'\n                      properties:\n                        claimName:\n                          description: 'ClaimName is the name of a PersistentVolumeClaim\n                            in the same namespace as the pod using this volume. More\n                            info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'\n                          type: string\n                        readOnly:\n                          description: Will force the ReadOnly setting in VolumeMounts.\n                            Default false.\n                          type: boolean\n                      required:\n                      - claimName\n                      type: object\n                    photonPersistentDisk:\n                      description: PhotonPersistentDisk represents a PhotonController\n                        persistent disk attached and mounted on kubelets host machine\n                      properties:\n                        fsType:\n                          description: Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                          type: string\n                        pdID:\n                          description: ID that identifies Photon Controller persistent\n                            disk\n                          type: string\n                      required:\n                      - pdID\n                      type: object\n                    portworxVolume:\n                      description: PortworxVolume represents a portworx volume attached\n                        and mounted on kubelets host machine\n                      properties:\n                        fsType:\n                          description: FSType represents the filesystem type to mount\n                            Must be a filesystem type supported by the host operating\n                            system. Ex. \"ext4\", \"xfs\". Implicitly inferred to be \"ext4\"\n                            if unspecified.\n                          type: string\n                        readOnly:\n                          description: Defaults to false (read/write). ReadOnly here\n                            will force the ReadOnly setting in VolumeMounts.\n                          type: boolean\n                        volumeID:\n                          description: VolumeID uniquely identifies a Portworx volume\n                          type: string\n                      required:\n                      - volumeID\n                      type: object\n                    projected:\n                      description: Items for all in one resources secrets, configmaps,\n                        and downward API\n                      properties:\n                        defaultMode:\n                          description: Mode bits to use on created files by default.\n                            Must be a value between 0 and 0777. Directories within\n                            the path are not affected by this setting. This might\n                            be in conflict with other options that affect the file\n                            mode, like fsGroup, and the result can be other mode bits\n                            set.\n                          format: int32\n                          type: integer\n                        sources:\n                          description: list of volume projections\n                          items:\n                            description: Projection that may be projected along with\n                              other supported volume types\n                            properties:\n                              configMap:\n                                description: information about the configMap data\n                                  to project\n                                properties:\n                                  items:\n                                    description: If unspecified, each key-value pair\n                                      in the Data field of the referenced ConfigMap\n                                      will be projected into the volume as a file\n                                      whose name is the key and content is the value.\n                                      If specified, the listed keys will be projected\n                                      into the specified paths, and unlisted keys\n                                      will not be present. If a key is specified which\n                                      is not present in the ConfigMap, the volume\n                                      setup will error unless it is marked optional.\n                                      Paths must be relative and may not contain the\n                                      '..' path or start with '..'.\n                                    items:\n                                      description: Maps a string key to a path within\n                                        a volume.\n                                      properties:\n                                        key:\n                                          description: The key to project.\n                                          type: string\n                                        mode:\n                                          description: 'Optional: mode bits to use\n                                            on this file, must be a value between\n                                            0 and 0777. If not specified, the volume\n                                            defaultMode will be used. This might be\n                                            in conflict with other options that affect\n                                            the file mode, like fsGroup, and the result\n                                            can be other mode bits set.'\n                                          format: int32\n                                          type: integer\n                                        path:\n                                          description: The relative path of the file\n                                            to map the key to. May not be an absolute\n                                            path. May not contain the path element\n                                            '..'. May not start with the string '..'.\n                                          type: string\n                                      required:\n                                      - key\n                                      - path\n                                      type: object\n                                    type: array\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the ConfigMap or\n                                      its keys must be defined\n                                    type: boolean\n                                type: object\n                              downwardAPI:\n                                description: information about the downwardAPI data\n                                  to project\n                                properties:\n                                  items:\n                                    description: Items is a list of DownwardAPIVolume\n                                      file\n                                    items:\n                                      description: DownwardAPIVolumeFile represents\n                                        information to create the file containing\n                                        the pod field\n                                      properties:\n                                        fieldRef:\n                                          description: 'Required: Selects a field\n                                            of the pod: only annotations, labels,\n                                            name and namespace are supported.'\n                                          properties:\n                                            apiVersion:\n                                              description: Version of the schema the\n                                                FieldPath is written in terms of,\n                                                defaults to \"v1\".\n                                              type: string\n                                            fieldPath:\n                                              description: Path of the field to select\n                                                in the specified API version.\n                                              type: string\n                                          required:\n                                          - fieldPath\n                                          type: object\n                                        mode:\n                                          description: 'Optional: mode bits to use\n                                            on this file, must be a value between\n                                            0 and 0777. If not specified, the volume\n                                            defaultMode will be used. This might be\n                                            in conflict with other options that affect\n                                            the file mode, like fsGroup, and the result\n                                            can be other mode bits set.'\n                                          format: int32\n                                          type: integer\n                                        path:\n                                          description: 'Required: Path is  the relative\n                                            path name of the file to be created. Must\n                                            not be absolute or contain the ''..''\n                                            path. Must be utf-8 encoded. The first\n                                            item of the relative path must not start\n                                            with ''..'''\n                                          type: string\n                                        resourceFieldRef:\n                                          description: 'Selects a resource of the\n                                            container: only resources limits and requests\n                                            (limits.cpu, limits.memory, requests.cpu\n                                            and requests.memory) are currently supported.'\n                                          properties:\n                                            containerName:\n                                              description: 'Container name: required\n                                                for volumes, optional for env vars'\n                                              type: string\n                                            divisor:\n                                              anyOf:\n                                              - type: integer\n                                              - type: string\n                                              description: Specifies the output format\n                                                of the exposed resources, defaults\n                                                to \"1\"\n                                              pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                              x-kubernetes-int-or-string: true\n                                            resource:\n                                              description: 'Required: resource to\n                                                select'\n                                              type: string\n                                          required:\n                                          - resource\n                                          type: object\n                                      required:\n                                      - path\n                                      type: object\n                                    type: array\n                                type: object\n                              secret:\n                                description: information about the secret data to\n                                  project\n                                properties:\n                                  items:\n                                    description: If unspecified, each key-value pair\n                                      in the Data field of the referenced Secret will\n                                      be projected into the volume as a file whose\n                                      name is the key and content is the value. If\n                                      specified, the listed keys will be projected\n                                      into the specified paths, and unlisted keys\n                                      will not be present. If a key is specified which\n                                      is not present in the Secret, the volume setup\n                                      will error unless it is marked optional. Paths\n                                      must be relative and may not contain the '..'\n                                      path or start with '..'.\n                                    items:\n                                      description: Maps a string key to a path within\n                                        a volume.\n                                      properties:\n                                        key:\n                                          description: The key to project.\n                                          type: string\n                                        mode:\n                                          description: 'Optional: mode bits to use\n                                            on this file, must be a value between\n                                            0 and 0777. If not specified, the volume\n                                            defaultMode will be used. This might be\n                                            in conflict with other options that affect\n                                            the file mode, like fsGroup, and the result\n                                            can be other mode bits set.'\n                                          format: int32\n                                          type: integer\n                                        path:\n                                          description: The relative path of the file\n                                            to map the key to. May not be an absolute\n                                            path. May not contain the path element\n                                            '..'. May not start with the string '..'.\n                                          type: string\n                                      required:\n                                      - key\n                                      - path\n                                      type: object\n                                    type: array\n                                  name:\n                                    description: 'Name of the referent. More info:\n                                      https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                      TODO: Add other useful fields. apiVersion, kind,\n                                      uid?'\n                                    type: string\n                                  optional:\n                                    description: Specify whether the Secret or its\n                                      key must be defined\n                                    type: boolean\n                                type: object\n                              serviceAccountToken:\n                                description: information about the serviceAccountToken\n                                  data to project\n                                properties:\n                                  audience:\n                                    description: Audience is the intended audience\n                                      of the token. A recipient of a token must identify\n                                      itself with an identifier specified in the audience\n                                      of the token, and otherwise should reject the\n                                      token. The audience defaults to the identifier\n                                      of the apiserver.\n                                    type: string\n                                  expirationSeconds:\n                                    description: ExpirationSeconds is the requested\n                                      duration of validity of the service account\n                                      token. As the token approaches expiration, the\n                                      kubelet volume plugin will proactively rotate\n                                      the service account token. The kubelet will\n                                      start trying to rotate the token if the token\n                                      is older than 80 percent of its time to live\n                                      or if the token is older than 24 hours.Defaults\n                                      to 1 hour and must be at least 10 minutes.\n                                    format: int64\n                                    type: integer\n                                  path:\n                                    description: Path is the path relative to the\n                                      mount point of the file to project the token\n                                      into.\n                                    type: string\n                                required:\n                                - path\n                                type: object\n                            type: object\n                          type: array\n                      required:\n                      - sources\n                      type: object\n                    quobyte:\n                      description: Quobyte represents a Quobyte mount on the host\n                        that shares a pod's lifetime\n                      properties:\n                        group:\n                          description: Group to map volume access to Default is no\n                            group\n                          type: string\n                        readOnly:\n                          description: ReadOnly here will force the Quobyte volume\n                            to be mounted with read-only permissions. Defaults to\n                            false.\n                          type: boolean\n                        registry:\n                          description: Registry represents a single or multiple Quobyte\n                            Registry services specified as a string as host:port pair\n                            (multiple entries are separated with commas) which acts\n                            as the central registry for volumes\n                          type: string\n                        tenant:\n                          description: Tenant owning the given Quobyte volume in the\n                            Backend Used with dynamically provisioned Quobyte volumes,\n                            value is set by the plugin\n                          type: string\n                        user:\n                          description: User to map volume access to Defaults to serivceaccount\n                            user\n                          type: string\n                        volume:\n                          description: Volume is a string that references an already\n                            created Quobyte volume by name.\n                          type: string\n                      required:\n                      - registry\n                      - volume\n                      type: object\n                    rbd:\n                      description: 'RBD represents a Rados Block Device mount on the\n                        host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md'\n                      properties:\n                        fsType:\n                          description: 'Filesystem type of the volume that you want\n                            to mount. Tip: Ensure that the filesystem type is supported\n                            by the host operating system. Examples: \"ext4\", \"xfs\",\n                            \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                            More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd\n                            TODO: how do we prevent errors in the filesystem from\n                            compromising the machine'\n                          type: string\n                        image:\n                          description: 'The rados image name. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          type: string\n                        keyring:\n                          description: 'Keyring is the path to key ring for RBDUser.\n                            Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          type: string\n                        monitors:\n                          description: 'A collection of Ceph monitors. More info:\n                            https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          items:\n                            type: string\n                          type: array\n                        pool:\n                          description: 'The rados pool name. Default is rbd. More\n                            info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          type: string\n                        readOnly:\n                          description: 'ReadOnly here will force the ReadOnly setting\n                            in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          type: boolean\n                        secretRef:\n                          description: 'SecretRef is name of the authentication secret\n                            for RBDUser. If provided overrides keyring. Default is\n                            nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        user:\n                          description: 'The rados user name. Default is admin. More\n                            info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it'\n                          type: string\n                      required:\n                      - image\n                      - monitors\n                      type: object\n                    scaleIO:\n                      description: ScaleIO represents a ScaleIO persistent volume\n                        attached and mounted on Kubernetes nodes.\n                      properties:\n                        fsType:\n                          description: Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". Default is \"xfs\".\n                          type: string\n                        gateway:\n                          description: The host address of the ScaleIO API Gateway.\n                          type: string\n                        protectionDomain:\n                          description: The name of the ScaleIO Protection Domain for\n                            the configured storage.\n                          type: string\n                        readOnly:\n                          description: Defaults to false (read/write). ReadOnly here\n                            will force the ReadOnly setting in VolumeMounts.\n                          type: boolean\n                        secretRef:\n                          description: SecretRef references to the secret for ScaleIO\n                            user and other sensitive information. If this is not provided,\n                            Login operation will fail.\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        sslEnabled:\n                          description: Flag to enable/disable SSL communication with\n                            Gateway, default false\n                          type: boolean\n                        storageMode:\n                          description: Indicates whether the storage for a volume\n                            should be ThickProvisioned or ThinProvisioned. Default\n                            is ThinProvisioned.\n                          type: string\n                        storagePool:\n                          description: The ScaleIO Storage Pool associated with the\n                            protection domain.\n                          type: string\n                        system:\n                          description: The name of the storage system as configured\n                            in ScaleIO.\n                          type: string\n                        volumeName:\n                          description: The name of a volume already created in the\n                            ScaleIO system that is associated with this volume source.\n                          type: string\n                      required:\n                      - gateway\n                      - secretRef\n                      - system\n                      type: object\n                    secret:\n                      description: 'Secret represents a secret that should populate\n                        this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret'\n                      properties:\n                        defaultMode:\n                          description: 'Optional: mode bits to use on created files\n                            by default. Must be a value between 0 and 0777. Defaults\n                            to 0644. Directories within the path are not affected\n                            by this setting. This might be in conflict with other\n                            options that affect the file mode, like fsGroup, and the\n                            result can be other mode bits set.'\n                          format: int32\n                          type: integer\n                        items:\n                          description: If unspecified, each key-value pair in the\n                            Data field of the referenced Secret will be projected\n                            into the volume as a file whose name is the key and content\n                            is the value. If specified, the listed keys will be projected\n                            into the specified paths, and unlisted keys will not be\n                            present. If a key is specified which is not present in\n                            the Secret, the volume setup will error unless it is marked\n                            optional. Paths must be relative and may not contain the\n                            '..' path or start with '..'.\n                          items:\n                            description: Maps a string key to a path within a volume.\n                            properties:\n                              key:\n                                description: The key to project.\n                                type: string\n                              mode:\n                                description: 'Optional: mode bits to use on this file,\n                                  must be a value between 0 and 0777. If not specified,\n                                  the volume defaultMode will be used. This might\n                                  be in conflict with other options that affect the\n                                  file mode, like fsGroup, and the result can be other\n                                  mode bits set.'\n                                format: int32\n                                type: integer\n                              path:\n                                description: The relative path of the file to map\n                                  the key to. May not be an absolute path. May not\n                                  contain the path element '..'. May not start with\n                                  the string '..'.\n                                type: string\n                            required:\n                            - key\n                            - path\n                            type: object\n                          type: array\n                        optional:\n                          description: Specify whether the Secret or its keys must\n                            be defined\n                          type: boolean\n                        secretName:\n                          description: 'Name of the secret in the pod''s namespace\n                            to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret'\n                          type: string\n                      type: object\n                    storageos:\n                      description: StorageOS represents a StorageOS volume attached\n                        and mounted on Kubernetes nodes.\n                      properties:\n                        fsType:\n                          description: Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                          type: string\n                        readOnly:\n                          description: Defaults to false (read/write). ReadOnly here\n                            will force the ReadOnly setting in VolumeMounts.\n                          type: boolean\n                        secretRef:\n                          description: SecretRef specifies the secret to use for obtaining\n                            the StorageOS API credentials.  If not specified, default\n                            values will be attempted.\n                          properties:\n                            name:\n                              description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                              type: string\n                          type: object\n                        volumeName:\n                          description: VolumeName is the human-readable name of the\n                            StorageOS volume.  Volume names are only unique within\n                            a namespace.\n                          type: string\n                        volumeNamespace:\n                          description: VolumeNamespace specifies the scope of the\n                            volume within StorageOS.  If no namespace is specified\n                            then the Pod's namespace will be used.  This allows the\n                            Kubernetes name scoping to be mirrored within StorageOS\n                            for tighter integration. Set VolumeName to any name to\n                            override the default behaviour. Set to \"default\" if you\n                            are not using namespaces within StorageOS. Namespaces\n                            that do not pre-exist within StorageOS will be created.\n                          type: string\n                      type: object\n                    vsphereVolume:\n                      description: VsphereVolume represents a vSphere volume attached\n                        and mounted on kubelets host machine\n                      properties:\n                        fsType:\n                          description: Filesystem type to mount. Must be a filesystem\n                            type supported by the host operating system. Ex. \"ext4\",\n                            \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.\n                          type: string\n                        storagePolicyID:\n                          description: Storage Policy Based Management (SPBM) profile\n                            ID associated with the StoragePolicyName.\n                          type: string\n                        storagePolicyName:\n                          description: Storage Policy Based Management (SPBM) profile\n                            name.\n                          type: string\n                        volumePath:\n                          description: Path that identifies vSphere volume vmdk\n                          type: string\n                      required:\n                      - volumePath\n                      type: object\n                  required:\n                  - name\n                  type: object\n                type: array\n            type: object\n          status:\n            description: 'Most recent observed status of the ThanosRuler cluster.\n              Read-only. Not included when requesting from the apiserver, only from\n              the ThanosRuler Operator API itself. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status'\n            properties:\n              availableReplicas:\n                description: Total number of available pods (ready for at least minReadySeconds)\n                  targeted by this ThanosRuler deployment.\n                format: int32\n                type: integer\n              paused:\n                description: Represents whether any actions on the underlying managed\n                  objects are being performed. Only delete actions will be performed.\n                type: boolean\n              replicas:\n                description: Total number of non-terminated pods targeted by this\n                  ThanosRuler deployment (their labels match the selector).\n                format: int32\n                type: integer\n              unavailableReplicas:\n                description: Total number of unavailable pods targeted by this ThanosRuler\n                  deployment.\n                format: int32\n                type: integer\n              updatedReplicas:\n                description: Total number of non-terminated pods targeted by this\n                  ThanosRuler deployment that have the desired version spec.\n                format: int32\n                type: integer\n            required:\n            - availableReplicas\n            - paused\n            - replicas\n            - unavailableReplicas\n            - updatedReplicas\n            type: object\n        required:\n        - spec\n        type: object\n    served: true\n    storage: true\nstatus:\n  acceptedNames:\n    kind: \"\"\n    plural: \"\"\n  conditions: []\n  storedVersions: []\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/hack/README.md",
    "content": "# kube-prometheus-stack hacks\n\n## [sync_prometheus_rules.py](sync_prometheus_rules.py)\n\nThis script generates prometheus rules set for alertmanager from any properly formatted kubernetes yaml based on defined input, splitting rules to separate files based on group name.\n\nCurrently following imported:\n\n- [prometheus-operator/kube-prometheus rules set](https://github.com/prometheus-operator/kube-prometheus/tree/master/manifests/kubernetes-prometheusRule.yaml)\n  - In order to modify these rules:\n    - prepare and merge PR into [kubernetes-mixin](https://github.com/kubernetes-monitoring/kubernetes-mixin/tree/master/rules) master and/or release branch\n    - run import inside your fork of [prometheus-operator/kube-prometheus](https://github.com/prometheus-operator/kube-prometheus/tree/master)\n\n     ```bash\n     jb update\n     make generate\n     ```\n\n    - prepare and merge PR with imported changes into `prometheus-operator/kube-prometheus` master and/or release branch\n    - run sync_prometheus_rules.py inside your fork of this repo\n    - send PR with changes to this repo\n- [etcd-io/website rules set](https://github.com/etcd-io/website/tree/master/content/docs/v3.4.0/etcd-mixin/README.md)\n  - In order to modify these rules:\n    - prepare and merge PR into [etcd-io/website](https://github.com/etcd-io/website/blob/master/content/docs/v3.4.0/etcd-mixin/mixin.libsonnet) repo\n    - run sync_prometheus_rules.py inside your fork of this repo\n    - send PR with changes to this repo\n\n## [sync_grafana_dashboards.py](sync_grafana_dashboards.py)\n\nThis script generates grafana dashboards from json files, splitting them to separate files based on group name.\n\nCurrently following imported:\n\n- [prometheus-operator/kube-prometheus dashboards](https://github.com/prometheus-operator/kube-prometheus/tree/master/manifests/grafana-deployment.yaml)\n  - In order to modify these dashboards:\n    - prepare and merge PR into [kubernetes-mixin](https://github.com/kubernetes-monitoring/kubernetes-mixin/tree/master/dashboards) master and/or release branch\n    - run import inside your fork of [prometheus-operator/kube-prometheus](https://github.com/prometheus-operator/kube-prometheus/tree/master)\n\n     ```bash\n     jb update\n     make generate\n     ```\n\n    - prepare and merge PR with imported changes into `prometheus-operator/kube-prometheus` master and/or release branch\n    - run sync_grafana_dashboards.py inside your fork of this repo\n    - send PR with changes to this repo\n- [etcd-io/website dashboard](https://github.com/etcd-io/website/blob/master/content/docs/v3.4.0/op-guide/grafana.json)\n  - In order to modify this dashboard:\n    - prepare and merge PR into [etcd-io/website](https://github.com/etcd-io/website/blob/master/content/docs/v3.4.0/op-guide/grafana.json) repo\n    - run sync_grafana_dashboards.py inside your fork of this repo\n    - send PR with changes to this repo\n\n[CoreDNS dashboard](https://github.com/prometheus-community/helm-charts/blob/main/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-coredns.yaml) is the only dashboard which is maintained in this repo and can be changed without import.\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/hack/minikube/README.md",
    "content": "# Testing on Minikube\n\nThe configuration in this folder lets you locally test the setup on minikube. Use cmd.sh to set up components and hack a working etcd scrape configuration. Run the commands in the sequence listed in the script to get a local working minikube cluster.\n\nIf you're using windows, there's a commented-out section that you should add to the minikube command.\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/hack/minikube/cmd.sh",
    "content": "#!/usr/bin/env bash\n\nHELM_RELEASE_NAME=prom-op\nCHART=./\nNAMESPACE=monitoring\nVALUES_FILES=./hack/minikube/values.yaml\n\nif [ \"$1\" = \"reset-minikube\" ]; then\n  minikube delete\n  minikube start  \\\n    #--vm-driver hyperv --hyperv-virtual-switch \"Default Switch\" \\\n    --kubernetes-version=v1.13.3 \\\n    --memory=4096 --bootstrapper=kubeadm \\\n    --extra-config=kubelet.authentication-token-webhook=true \\\n    --extra-config=kubelet.authorization-mode=Webhook \\\n    --extra-config=scheduler.address=0.0.0.0 \\\n    --extra-config=controller-manager.address=0.0.0.0\n  exit 0\nfi\n\nif [ \"$1\" = \"init-helm\" ]; then\n  helm init\n  helm repo update\n  exit 0\nfi\n\nif [ \"$1\" = \"init-etcd-secret\" ]; then\n  kubectl create namespace monitoring\n  kubectl delete secret etcd-certs -nmonitoring\n  kubectl create secret generic etcd-certs -nmonitoring \\\n  --from-literal=ca.crt=\"$(kubectl exec kube-apiserver-minikube -nkube-system -- cat /var/lib/minikube/certs/etcd/ca.crt)\" \\\n  --from-literal=client.crt=\"$(kubectl exec kube-apiserver-minikube -nkube-system -- cat /var/lib/minikube/certs/apiserver-etcd-client.crt)\" \\\n  --from-literal=client.key=\"$(kubectl exec kube-apiserver-minikube -nkube-system -- cat /var/lib/minikube/certs/apiserver-etcd-client.key)\"\n\n  exit 0\nfi\n\n\nif [ \"$1\" = \"upgrade-install\" ]; then\n  helm upgrade $HELM_RELEASE_NAME $CHART \\\n    --namespace $NAMESPACE     \\\n    --values    $VALUES_FILES  \\\n    --set       grafana.podAnnotations.redeploy-hack=\"$(cat /proc/sys/kernel/random/uuid)\" \\\n    --install --debug\n  exit 0\nfi\n\nif [ \"$1\" = \"port-forward\" ]; then\n  killall kubectl &>/dev/null\n  kubectl port-forward service/prom-op-prometheus-operato-prometheus 9090 &>/dev/null &\n  kubectl port-forward service/prom-op-prometheus-operato-alertmanager 9093 &>/dev/null &\n  kubectl port-forward service/prom-op-grafana 3000:80 &>/dev/null &\n  echo \"Started port-forward commands\"\n  echo \"localhost:9090 - prometheus\"\n  echo \"localhost:9093 - alertmanager\"\n  echo \"localhost:3000 - grafana\"\n  exit 0\nfi\n\ncat << EOF\nUsage:\n  install.sh <COMMAND>\n\nCommands:\n  reset-minikube      - resets minikube with values suitable for running prometheus operator\n                        the normal installation will not allow scraping of the kubelet,\n                        scheduler or controller-manager components\n  init-helm           - initialize helm and update repository so that we can install\n                        the kube-prometheus-stack chart. This has to be run only once after\n                        a minikube installation is done\n  init-etcd-secret    - pulls the certs used to access etcd from the api server and creates\n                        a secret in the monitoring namespace with them. The values files\n                        in the install command assume that this secret exists and is valid.\n                        If not, then prometheus will not start\n  upgrade-install     - install or upgrade the kube-prometheus-stack chart in the cluster\n  port-forward        - starts port-forwarding for prometheus, alertmanager, grafana\n                        localhost:9090 - prometheus\n                        localhost:9093 - alertmanager\n                        localhost:3000 - grafana\nEOF\n\nexit 0\n}\n\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/hack/minikube/values.yaml",
    "content": "prometheus:\n  prometheusSpec:\n    secrets: [etcd-certs]\nkubeEtcd:\n  serviceMonitor:\n    scheme: https\n    caFile:   /etc/prometheus/secrets/etcd-certs/ca.crt\n    certFile: /etc/prometheus/secrets/etcd-certs/client.crt\n    keyFile:  /etc/prometheus/secrets/etcd-certs/client.key"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/hack/requirements.txt",
    "content": "PyYAML==5.4\nrequests==2.22.0\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/hack/sync_grafana_dashboards.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Fetch dashboards from provided urls into this chart.\"\"\"\nimport json\nimport textwrap\nfrom os import makedirs, path\n\nimport requests\nimport yaml\nfrom yaml.representer import SafeRepresenter\n\n\n# https://stackoverflow.com/a/20863889/961092\nclass LiteralStr(str):\n    pass\n\n\ndef change_style(style, representer):\n    def new_representer(dumper, data):\n        scalar = representer(dumper, data)\n        scalar.style = style\n        return scalar\n\n    return new_representer\n\n\n# Source files list\ncharts = [\n    {\n        'source': 'https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml',\n        'destination': '../templates/grafana/dashboards-1.14',\n        'type': 'yaml',\n        'min_kubernetes': '1.14.0-0'\n    },\n    {\n        'source': 'https://raw.githubusercontent.com/etcd-io/website/master/content/en/docs/v3.4/op-guide/grafana.json',\n        'destination': '../templates/grafana/dashboards-1.14',\n        'type': 'json',\n        'min_kubernetes': '1.14.0-0'\n    },\n]\n\n# Additional conditions map\ncondition_map = {\n    'grafana-coredns-k8s': ' .Values.coreDns.enabled',\n    'etcd': ' .Values.kubeEtcd.enabled',\n    'apiserver': ' .Values.kubeApiServer.enabled',\n    'controller-manager': ' .Values.kubeControllerManager.enabled',\n    'kubelet': ' .Values.kubelet.enabled',\n    'proxy': ' .Values.kubeProxy.enabled',\n    'scheduler': ' .Values.kubeScheduler.enabled',\n    'node-rsrc-use': ' .Values.nodeExporter.enabled',\n    'node-cluster-rsrc-use': ' .Values.nodeExporter.enabled',\n    'prometheus-remote-write': ' .Values.prometheus.prometheusSpec.remoteWriteDashboards'\n}\n\n# standard header\nheader = '''{{- /*\nGenerated from '%(name)s' from %(url)s\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=%(min_kubernetes)s\" $kubeTargetVersion) (semverCompare \"<%(max_kubernetes)s\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled%(condition)s }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%%s-%%s\" (include \"kube-prometheus-stack.fullname\" $) \"%(name)s\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n'''\n\n\ndef init_yaml_styles():\n    represent_literal_str = change_style('|', SafeRepresenter.represent_str)\n    yaml.add_representer(LiteralStr, represent_literal_str)\n\n\ndef escape(s):\n    return s.replace(\"{{\", \"{{`{{\").replace(\"}}\", \"}}`}}\").replace(\"{{`{{\", \"{{`{{`}}\").replace(\"}}`}}\", \"{{`}}`}}\")\n\n\ndef unescape(s):\n    return s.replace(\"\\{\\{\", \"{{\").replace(\"\\}\\}\", \"}}\")\n\n\ndef yaml_str_repr(struct, indent=2):\n    \"\"\"represent yaml as a string\"\"\"\n    text = yaml.dump(\n        struct,\n        width=1000,  # to disable line wrapping\n        default_flow_style=False  # to disable multiple items on single line\n    )\n    text = escape(text)  # escape {{ and }} for helm\n    text = unescape(text)  # unescape \\{\\{ and \\}\\} for templating\n    text = textwrap.indent(text, ' ' * indent)\n    return text\n\n\ndef patch_json_for_multicluster_configuration(content):\n    try:\n        content_struct = json.loads(content)\n        overwrite_list = []\n        for variable in content_struct['templating']['list']:\n            if variable['name'] == 'cluster':\n                variable['hide'] = ':multicluster:'\n            overwrite_list.append(variable)\n        content_struct['templating']['list'] = overwrite_list\n        content_array = []\n        original_content_lines = content.split('\\n')\n        for i, line in enumerate(json.dumps(content_struct, indent=4).split('\\n')):\n            if (' []' not in line and ' {}' not in line) or line == original_content_lines[i]:\n                content_array.append(line)\n                continue\n\n            append = ''\n            if line.endswith(','):\n                line = line[:-1]\n                append = ','\n\n            if line.endswith('{}') or line.endswith('[]'):\n                content_array.append(line[:-1])\n                content_array.append('')\n                content_array.append(' ' * (len(line) - len(line.lstrip())) + line[-1] + append)\n\n        content = '\\n'.join(content_array)\n\n        multicluster = content.find(':multicluster:')\n        if multicluster != -1:\n            content = ''.join((\n                content[:multicluster-1],\n                '\\{\\{ if .Values.grafana.sidecar.dashboards.multicluster \\}\\}0\\{\\{ else \\}\\}2\\{\\{ end \\}\\}',\n                content[multicluster + 15:]\n            ))\n    except (ValueError, KeyError):\n        pass\n\n    return content\n\n\ndef write_group_to_file(resource_name, content, url, destination, min_kubernetes, max_kubernetes):\n    # initialize header\n    lines = header % {\n        'name': resource_name,\n        'url': url,\n        'condition': condition_map.get(resource_name, ''),\n        'min_kubernetes': min_kubernetes,\n        'max_kubernetes': max_kubernetes\n    }\n\n    content = patch_json_for_multicluster_configuration(content)\n\n    filename_struct = {resource_name + '.json': (LiteralStr(content))}\n    # rules themselves\n    lines += yaml_str_repr(filename_struct)\n\n    # footer\n    lines += '{{- end }}'\n\n    filename = resource_name + '.yaml'\n    new_filename = \"%s/%s\" % (destination, filename)\n\n    # make sure directories to store the file exist\n    makedirs(destination, exist_ok=True)\n\n    # recreate the file\n    with open(new_filename, 'w') as f:\n        f.write(lines)\n\n    print(\"Generated %s\" % new_filename)\n\n\ndef main():\n    init_yaml_styles()\n    # read the rules, create a new template file per group\n    for chart in charts:\n        print(\"Generating rules from %s\" % chart['source'])\n        response = requests.get(chart['source'])\n        if response.status_code != 200:\n            print('Skipping the file, response code %s not equals 200' % response.status_code)\n            continue\n        raw_text = response.text\n\n        if ('max_kubernetes' not in chart):\n            chart['max_kubernetes']=\"9.9.9-9\"\n\n        if chart['type'] == 'yaml':\n            yaml_text = yaml.full_load(raw_text)\n            groups = yaml_text['items']\n            for group in groups:\n                for resource, content in group['data'].items():\n                    write_group_to_file(resource.replace('.json', ''), content, chart['source'], chart['destination'], chart['min_kubernetes'], chart['max_kubernetes'])\n        elif chart['type'] == 'json':\n            json_text = json.loads(raw_text)\n            # is it already a dashboard structure or is it nested (etcd case)?\n            flat_structure = bool(json_text.get('annotations'))\n            if flat_structure:\n                resource = path.basename(chart['source']).replace('.json', '')\n                write_group_to_file(resource, json.dumps(json_text, indent=4), chart['source'], chart['destination'], chart['min_kubernetes'], chart['max_kubernetes'])\n            else:\n                for resource, content in json_text.items():\n                    write_group_to_file(resource.replace('.json', ''), json.dumps(content, indent=4), chart['source'], chart['destination'], chart['min_kubernetes'], chart['max_kubernetes'])\n    print(\"Finished\")\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/hack/sync_prometheus_rules.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Fetch alerting and aggregation rules from provided urls into this chart.\"\"\"\nimport textwrap\nfrom os import makedirs\n\nimport requests\nimport yaml\nfrom yaml.representer import SafeRepresenter\nimport re\n\n# https://stackoverflow.com/a/20863889/961092\nclass LiteralStr(str):\n    pass\n\n\ndef change_style(style, representer):\n    def new_representer(dumper, data):\n        scalar = representer(dumper, data)\n        scalar.style = style\n        return scalar\n\n    return new_representer\n\n\n# Source files list\ncharts = [\n    {\n        'source': 'https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/alertmanager-prometheusRule.yaml',\n        'destination': '../templates/prometheus/rules-1.14',\n        'min_kubernetes': '1.14.0-0'\n    },\n    {\n        'source': 'https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kube-prometheus-prometheusRule.yaml',\n        'destination': '../templates/prometheus/rules-1.14',\n        'min_kubernetes': '1.14.0-0'\n    },\n    {\n        'source': 'https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetes-prometheusRule.yaml',\n        'destination': '../templates/prometheus/rules-1.14',\n        'min_kubernetes': '1.14.0-0'\n    },\n    {\n        'source': 'https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kube-state-metrics-prometheusRule.yaml',\n        'destination': '../templates/prometheus/rules-1.14',\n        'min_kubernetes': '1.14.0-0'\n    },\n    {\n        'source': 'https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/node-exporter-prometheusRule.yaml',\n        'destination': '../templates/prometheus/rules-1.14',\n        'min_kubernetes': '1.14.0-0'\n    },\n    {\n        'source': 'https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/prometheus-prometheusRule.yaml',\n        'destination': '../templates/prometheus/rules-1.14',\n        'min_kubernetes': '1.14.0-0'\n    },\n    {\n        'source': 'https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/prometheus-operator-prometheusRule.yaml',\n        'destination': '../templates/prometheus/rules-1.14',\n        'min_kubernetes': '1.14.0-0'\n    },\n    {\n        'source': 'https://raw.githubusercontent.com/etcd-io/website/master/content/en/docs/v3.4/op-guide/etcd3_alert.rules.yml',\n        'destination': '../templates/prometheus/rules-1.14',\n        'min_kubernetes': '1.14.0-0'\n    },\n]\n\n# Additional conditions map\ncondition_map = {\n    'alertmanager.rules': ' .Values.defaultRules.rules.alertmanager',\n    'general.rules': ' .Values.defaultRules.rules.general',\n    'k8s.rules': ' .Values.defaultRules.rules.k8s',\n    'kube-apiserver.rules': ' .Values.kubeApiServer.enabled .Values.defaultRules.rules.kubeApiserver',\n    'kube-apiserver-availability.rules': ' .Values.kubeApiServer.enabled .Values.defaultRules.rules.kubeApiserverAvailability',\n    'kube-apiserver-error': ' .Values.kubeApiServer.enabled .Values.defaultRules.rules.kubeApiserverError',\n    'kube-apiserver-slos': ' .Values.kubeApiServer.enabled .Values.defaultRules.rules.kubeApiserverSlos',\n    'kube-prometheus-general.rules': ' .Values.defaultRules.rules.kubePrometheusGeneral',\n    'kube-prometheus-node-alerting.rules': ' .Values.defaultRules.rules.kubePrometheusNodeAlerting',\n    'kube-prometheus-node-recording.rules': ' .Values.defaultRules.rules.kubePrometheusNodeRecording',\n    'kube-scheduler.rules': ' .Values.kubeScheduler.enabled .Values.defaultRules.rules.kubeScheduler',\n    'kube-state-metrics': ' .Values.defaultRules.rules.kubeStateMetrics',\n    'kubelet.rules': ' .Values.kubelet.enabled .Values.defaultRules.rules.kubelet',\n    'kubernetes-absent': ' .Values.defaultRules.rules.kubernetesAbsent',\n    'kubernetes-resources': ' .Values.defaultRules.rules.kubernetesResources',\n    'kubernetes-storage': ' .Values.defaultRules.rules.kubernetesStorage',\n    'kubernetes-system': ' .Values.defaultRules.rules.kubernetesSystem',\n    'kubernetes-system-apiserver': ' .Values.defaultRules.rules.kubernetesSystem', # kubernetes-system was split into more groups in 1.14, one of them is kubernetes-system-apiserver\n    'kubernetes-system-kubelet': ' .Values.defaultRules.rules.kubernetesSystem', # kubernetes-system was split into more groups in 1.14, one of them is kubernetes-system-kubelet\n    'kubernetes-system-controller-manager': ' .Values.kubeControllerManager.enabled',\n    'kubernetes-system-scheduler': ' .Values.kubeScheduler.enabled .Values.defaultRules.rules.kubeScheduler',\n    'node-exporter.rules': ' .Values.defaultRules.rules.node',\n    'node-exporter': ' .Values.defaultRules.rules.node',\n    'node.rules': ' .Values.defaultRules.rules.node',\n    'node-network': ' .Values.defaultRules.rules.network',\n    'node-time': ' .Values.defaultRules.rules.time',\n    'prometheus-operator': ' .Values.defaultRules.rules.prometheusOperator',\n    'prometheus.rules': ' .Values.defaultRules.rules.prometheus',\n    'prometheus': ' .Values.defaultRules.rules.prometheus', # kube-prometheus >= 1.14 uses prometheus as group instead of prometheus.rules\n    'kubernetes-apps': ' .Values.defaultRules.rules.kubernetesApps',\n    'etcd': ' .Values.kubeEtcd.enabled .Values.defaultRules.rules.etcd',\n}\n\nalert_condition_map = {\n    'KubeAPIDown': '.Values.kubeApiServer.enabled',  # there are more alerts which are left enabled, because they'll never fire without metrics\n    'KubeControllerManagerDown': '.Values.kubeControllerManager.enabled',\n    'KubeSchedulerDown': '.Values.kubeScheduler.enabled',\n    'KubeStateMetricsDown': '.Values.kubeStateMetrics.enabled',  # there are more alerts which are left enabled, because they'll never fire without metrics\n    'KubeletDown': '.Values.prometheusOperator.kubeletService.enabled',  # there are more alerts which are left enabled, because they'll never fire without metrics\n    'PrometheusOperatorDown': '.Values.prometheusOperator.enabled',\n    'NodeExporterDown': '.Values.nodeExporter.enabled',\n    'CoreDNSDown': '.Values.kubeDns.enabled',\n    'AlertmanagerDown': '.Values.alertmanager.enabled',\n    'AggregatedAPIDown': 'semverCompare \">=1.18.0-0\" $kubeTargetVersion',\n}\n\nreplacement_map = {\n    'job=\"prometheus-operator\"': {\n        'replacement': 'job=\"{{ $operatorJob }}\"',\n        'init': '{{- $operatorJob := printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"operator\" }}'},\n    'job=\"prometheus-k8s\"': {\n        'replacement': 'job=\"{{ $prometheusJob }}\"',\n        'init': '{{- $prometheusJob := printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"prometheus\" }}'},\n    'job=\"alertmanager-main\"': {\n        'replacement': 'job=\"{{ $alertmanagerJob }}\"',\n        'init': '{{- $alertmanagerJob := printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"alertmanager\" }}'},\n    'namespace=\"monitoring\"': {\n        'replacement': 'namespace=\"{{ $namespace }}\"',\n        'init': '{{- $namespace := printf \"%s\" (include \"kube-prometheus-stack.namespace\" .) }}'},\n    'alertmanager-$1': {\n        'replacement': '$1',\n        'init': ''},\n    'https://github.com/kubernetes-monitoring/kubernetes-mixin/tree/master/runbook.md#': {\n        'replacement': '{{ .Values.defaultRules.runbookUrl }}',\n        'init': ''},\n    'https://github.com/prometheus-operator/kube-prometheus/wiki/': {\n        'replacement': '{{ .Values.defaultRules.runbookUrl }}alert-name-',\n        'init': ''},\n    'job=\"kube-state-metrics\"': {\n        'replacement': 'job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"',\n        'limitGroup': ['kubernetes-apps'],\n        'init': '{{- $targetNamespace := .Values.defaultRules.appNamespacesTarget }}'},\n    'job=\"kubelet\"': {\n        'replacement': 'job=\"kubelet\", namespace=~\"{{ $targetNamespace }}\"',\n        'limitGroup': ['kubernetes-storage'],\n        'init': '{{- $targetNamespace := .Values.defaultRules.appNamespacesTarget }}'},\n}\n\n# standard header\nheader = '''{{- /*\nGenerated from '%(name)s' group from %(url)s\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=%(min_kubernetes)s\" $kubeTargetVersion) (semverCompare \"<%(max_kubernetes)s\" $kubeTargetVersion) .Values.defaultRules.create%(condition)s }}%(init_line)s\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%%s-%%s\" (include \"kube-prometheus-stack.fullname\" .) \"%(name)s\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  -'''\n\n\ndef init_yaml_styles():\n    represent_literal_str = change_style('|', SafeRepresenter.represent_str)\n    yaml.add_representer(LiteralStr, represent_literal_str)\n\n\ndef escape(s):\n    return s.replace(\"{{\", \"{{`{{\").replace(\"}}\", \"}}`}}\").replace(\"{{`{{\", \"{{`{{`}}\").replace(\"}}`}}\", \"{{`}}`}}\")\n\n\ndef fix_expr(rules):\n    \"\"\"Remove trailing whitespaces and line breaks, which happen to creep in\n     due to yaml import specifics;\n     convert multiline expressions to literal style, |-\"\"\"\n    for rule in rules:\n        rule['expr'] = rule['expr'].rstrip()\n        if '\\n' in rule['expr']:\n            rule['expr'] = LiteralStr(rule['expr'])\n\n\ndef yaml_str_repr(struct, indent=4):\n    \"\"\"represent yaml as a string\"\"\"\n    text = yaml.dump(\n        struct,\n        width=1000,  # to disable line wrapping\n        default_flow_style=False  # to disable multiple items on single line\n    )\n    text = escape(text)  # escape {{ and }} for helm\n    text = textwrap.indent(text, ' ' * indent)[indent - 1:]  # indent everything, and remove very first line extra indentation\n    return text\n\n\ndef add_rules_conditions(rules, indent=4):\n    \"\"\"Add if wrapper for rules, listed in alert_condition_map\"\"\"\n    rule_condition = '{{- if %s }}\\n'\n    for alert_name in alert_condition_map:\n        line_start = ' ' * indent + '- alert: '\n        if line_start + alert_name in rules:\n            rule_text = rule_condition % alert_condition_map[alert_name]\n            # add if condition\n            index = rules.index(line_start + alert_name)\n            rules = rules[:index] + rule_text + rules[index:]\n            # add end of if\n            try:\n                next_index = rules.index(line_start, index + len(rule_text) + 1)\n            except ValueError:\n                # we found the last alert in file if there are no alerts after it\n                next_index = len(rules)\n\n            # depending on the rule ordering in alert_condition_map it's possible that an if statement from another rule is present at the end of this block.\n            found_block_end = False\n            last_line_index = next_index\n            while not found_block_end:\n                last_line_index = rules.rindex('\\n', index, last_line_index - 1)  # find the starting position of the last line\n                last_line = rules[last_line_index + 1:next_index]\n\n                if last_line.startswith('{{- if'):\n                    next_index = last_line_index + 1  # move next_index back if the current block ends in an if statement\n                    continue\n\n                found_block_end = True\n\n            rules = rules[:next_index] + '{{- end }}\\n' + rules[next_index:]\n    return rules\n\n\ndef add_custom_labels(rules, indent=4):\n    \"\"\"Add if wrapper for additional rules labels\"\"\"\n    rule_condition = '{{- if .Values.defaultRules.additionalRuleLabels }}\\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\\n{{- end }}'\n    rule_condition_len = len(rule_condition) + 1\n\n    separator = \" \" * indent + \"- alert:.*\"\n    alerts_positions = re.finditer(separator,rules)\n    alert=-1\n    for alert_position in alerts_positions:\n        # add rule_condition at the end of the alert block\n        if alert >= 0 :\n            index = alert_position.start() + rule_condition_len * alert - 1\n            rules = rules[:index] + \"\\n\" + rule_condition + rules[index:]\n        alert += 1\n\n    # add rule_condition at the end of the last alert\n    if alert >= 0:\n        index = len(rules) - 1\n        rules = rules[:index] + \"\\n\" + rule_condition + rules[index:]\n    return rules\n\ndef write_group_to_file(group, url, destination, min_kubernetes, max_kubernetes):\n    fix_expr(group['rules'])\n    group_name = group['name']\n\n    # prepare rules string representation\n    rules = yaml_str_repr(group)\n    # add replacements of custom variables and include their initialisation in case it's needed\n    init_line = ''\n    for line in replacement_map:\n        if group_name in replacement_map[line].get('limitGroup', [group_name]) and line in rules:\n            rules = rules.replace(line, replacement_map[line]['replacement'])\n            if replacement_map[line]['init']:\n                init_line += '\\n' + replacement_map[line]['init']\n    # append per-alert rules\n    rules = add_custom_labels(rules)\n    rules = add_rules_conditions(rules)\n    # initialize header\n    lines = header % {\n        'name': group['name'],\n        'url': url,\n        'condition': condition_map.get(group['name'], ''),\n        'init_line': init_line,\n        'min_kubernetes': min_kubernetes,\n        'max_kubernetes': max_kubernetes\n    }\n\n    # rules themselves\n    lines += rules\n\n    # footer\n    lines += '{{- end }}'\n\n    filename = group['name'] + '.yaml'\n    new_filename = \"%s/%s\" % (destination, filename)\n\n    # make sure directories to store the file exist\n    makedirs(destination, exist_ok=True)\n\n    # recreate the file\n    with open(new_filename, 'w') as f:\n        f.write(lines)\n\n    print(\"Generated %s\" % new_filename)\n\ndef write_rules_names_template():\n    with open('../templates/prometheus/_rules.tpl', 'w') as f:\n        f.write('''{{- /*\nGenerated file. Do not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\\n''')\n        f.write('{{- define \"rules.names\" }}\\n')\n        f.write('rules:\\n')\n        for rule in condition_map:\n            f.write('  - \"%s\"\\n' % rule)\n        f.write('{{- end }}')\n\ndef main():\n    init_yaml_styles()\n    # read the rules, create a new template file per group\n    for chart in charts:\n        print(\"Generating rules from %s\" % chart['source'])\n        response = requests.get(chart['source'])\n        if response.status_code != 200:\n            print('Skipping the file, response code %s not equals 200' % response.status_code)\n            continue\n        raw_text = response.text\n        yaml_text = yaml.full_load(raw_text)\n\n        if ('max_kubernetes' not in chart):\n            chart['max_kubernetes']=\"9.9.9-9\"\n\n        # etcd workaround, their file don't have spec level\n        groups = yaml_text['spec']['groups'] if yaml_text.get('spec') else yaml_text['groups']\n        for group in groups:\n            write_group_to_file(group, chart['source'], chart['destination'], chart['min_kubernetes'], chart['max_kubernetes'])\n\n    # write rules.names named template\n    write_rules_names_template()\n\n    print(\"Finished\")\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/hack/update_crds.sh",
    "content": "#!/bin/bash -eu\n\nVERSION=$1\n\n[ -z \"${VERSION}\" ] && echo \"Pass prometheus-operator version as first comandline argument\" && exit 1\n\nFILES=(\n  \"crd-alertmanagerconfigs.yaml :  monitoring.coreos.com_alertmanagerconfigs.yaml\"\n  \"crd-alertmanagers.yaml       :  monitoring.coreos.com_alertmanagers.yaml\"\n  \"crd-podmonitors.yaml         :  monitoring.coreos.com_podmonitors.yaml\"\n  \"crd-probes.yaml              :  monitoring.coreos.com_probes.yaml\"\n  \"crd-prometheuses.yaml        :  monitoring.coreos.com_prometheuses.yaml\"\n  \"crd-prometheusrules.yaml     :  monitoring.coreos.com_prometheusrules.yaml\"\n  \"crd-servicemonitors.yaml     :  monitoring.coreos.com_servicemonitors.yaml\"\n  \"crd-thanosrulers.yaml        :  monitoring.coreos.com_thanosrulers.yaml\"\n)\n\nfor line in \"${FILES[@]}\" ; do\n    DESTINATION=$(echo \"${line%%:*}\" | xargs)\n    SOURCE=$(echo \"${line##*:}\" | xargs)\n\n    URL=\"https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/$VERSION/example/prometheus-operator-crd/$SOURCE\"\n    echo \"# ${URL}\" > ../crds/\"${DESTINATION}\"\n    curl -L \"${URL}\" >> ../crds/\"${DESTINATION}\"\n\ndone\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/NOTES.txt",
    "content": "{{ $.Chart.Name }} has been installed. Check its status by running:\n  kubectl --namespace {{ template \"kube-prometheus-stack.namespace\" . }} get pods -l \"release={{ $.Release.Name }}\"\n\nVisit https://github.com/prometheus-operator/kube-prometheus for instructions on how to create & configure Alertmanager and Prometheus instances using the Operator.\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/_helpers.tpl",
    "content": "{{/* vim: set filetype=mustache: */}}\n{{/* Expand the name of the chart. This is suffixed with -alertmanager, which means subtract 13 from longest 63 available */}}\n{{- define \"kube-prometheus-stack.name\" -}}\n{{- default .Chart.Name .Values.nameOverride | trunc 50 | 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.\nThe components in this chart create additional resources that expand the longest created name strings.\nThe longest name that gets created adds and extra 37 characters, so truncation should be 63-35=26.\n*/}}\n{{- define \"kube-prometheus-stack.fullname\" -}}\n{{- if .Values.fullnameOverride -}}\n{{- .Values.fullnameOverride | trunc 26 | trimSuffix \"-\" -}}\n{{- else -}}\n{{- $name := default .Chart.Name .Values.nameOverride -}}\n{{- if contains $name .Release.Name -}}\n{{- .Release.Name | trunc 26 | trimSuffix \"-\" -}}\n{{- else -}}\n{{- printf \"%s-%s\" .Release.Name $name | trunc 26 | trimSuffix \"-\" -}}\n{{- end -}}\n{{- end -}}\n{{- end -}}\n\n{{/* Fullname suffixed with operator */}}\n{{- define \"kube-prometheus-stack.operator.fullname\" -}}\n{{- printf \"%s-operator\" (include \"kube-prometheus-stack.fullname\" .) -}}\n{{- end }}\n\n{{/* Fullname suffixed with prometheus */}}\n{{- define \"kube-prometheus-stack.prometheus.fullname\" -}}\n{{- printf \"%s-prometheus\" (include \"kube-prometheus-stack.fullname\" .) -}}\n{{- end }}\n\n{{/* Fullname suffixed with alertmanager */}}\n{{- define \"kube-prometheus-stack.alertmanager.fullname\" -}}\n{{- printf \"%s-alertmanager\" (include \"kube-prometheus-stack.fullname\" .) -}}\n{{- end }}\n\n{{/* Create chart name and version as used by the chart label. */}}\n{{- define \"kube-prometheus-stack.chartref\" -}}\n{{- replace \"+\" \"_\" .Chart.Version | printf \"%s-%s\" .Chart.Name -}}\n{{- end }}\n\n{{/* Generate basic labels */}}\n{{- define \"kube-prometheus-stack.labels\" }}\napp.kubernetes.io/managed-by: {{ .Release.Service }}\napp.kubernetes.io/instance: {{ .Release.Name }}\napp.kubernetes.io/version: \"{{ .Chart.Version }}\"\napp.kubernetes.io/part-of: {{ template \"kube-prometheus-stack.name\" . }}\nchart: {{ template \"kube-prometheus-stack.chartref\" . }}\nrelease: {{ $.Release.Name | quote }}\nheritage: {{ $.Release.Service | quote }}\n{{- if .Values.commonLabels}}\n{{ toYaml .Values.commonLabels }}\n{{- end }}\n{{- end }}\n\n{{/* Create the name of kube-prometheus-stack service account to use */}}\n{{- define \"kube-prometheus-stack.operator.serviceAccountName\" -}}\n{{- if .Values.prometheusOperator.serviceAccount.create -}}\n    {{ default (include \"kube-prometheus-stack.operator.fullname\" .) .Values.prometheusOperator.serviceAccount.name }}\n{{- else -}}\n    {{ default \"default\" .Values.prometheusOperator.serviceAccount.name }}\n{{- end -}}\n{{- end -}}\n\n{{/* Create the name of prometheus service account to use */}}\n{{- define \"kube-prometheus-stack.prometheus.serviceAccountName\" -}}\n{{- if .Values.prometheus.serviceAccount.create -}}\n    {{ default (include \"kube-prometheus-stack.prometheus.fullname\" .) .Values.prometheus.serviceAccount.name }}\n{{- else -}}\n    {{ default \"default\" .Values.prometheus.serviceAccount.name }}\n{{- end -}}\n{{- end -}}\n\n{{/* Create the name of alertmanager service account to use */}}\n{{- define \"kube-prometheus-stack.alertmanager.serviceAccountName\" -}}\n{{- if .Values.alertmanager.serviceAccount.create -}}\n    {{ default (include \"kube-prometheus-stack.alertmanager.fullname\" .) .Values.alertmanager.serviceAccount.name }}\n{{- else -}}\n    {{ default \"default\" .Values.alertmanager.serviceAccount.name }}\n{{- end -}}\n{{- end -}}\n\n{{/*\nAllow the release namespace to be overridden for multi-namespace deployments in combined charts\n*/}}\n{{- define \"kube-prometheus-stack.namespace\" -}}\n  {{- if .Values.namespaceOverride -}}\n    {{- .Values.namespaceOverride -}}\n  {{- else -}}\n    {{- .Release.Namespace -}}\n  {{- end -}}\n{{- end -}}\n\n{{/* Allow KubeVersion to be overridden. */}}\n{{- define \"kube-prometheus-stack.ingress.kubeVersion\" -}}\n  {{- $kubeVersion := default .Capabilities.KubeVersion.Version .Values.kubeVersionOverride -}}\n  {{/* Special use case for Amazon EKS, Google GKE */}}\n  {{- if and (regexMatch \"\\\\d+\\\\.\\\\d+\\\\.\\\\d+-(?:eks|gke).+\" $kubeVersion) (not .Values.kubeVersionOverride) -}}\n    {{- $kubeVersion = regexFind \"\\\\d+\\\\.\\\\d+\\\\.\\\\d+\" $kubeVersion -}}\n  {{- end -}}\n  {{- $kubeVersion -}}\n{{- end -}}\n\n{{/* Get Ingress API Version */}}\n{{- define \"kube-prometheus-stack.ingress.apiVersion\" -}}\n  {{- if and (.Capabilities.APIVersions.Has \"networking.k8s.io/v1\") (semverCompare \">= 1.19.x\" (include \"kube-prometheus-stack.ingress.kubeVersion\" .)) -}}\n      {{- print \"networking.k8s.io/v1\" -}}\n  {{- else if .Capabilities.APIVersions.Has \"networking.k8s.io/v1beta1\" -}}\n    {{- print \"networking.k8s.io/v1beta1\" -}}\n  {{- else -}}\n    {{- print \"extensions/v1beta1\" -}}\n  {{- end -}}\n{{- end -}}\n\n{{/* Check Ingress stability */}}\n{{- define \"kube-prometheus-stack.ingress.isStable\" -}}\n  {{- eq (include \"kube-prometheus-stack.ingress.apiVersion\" .) \"networking.k8s.io/v1\" -}}\n{{- end -}}\n\n{{/* Check Ingress supports pathType */}}\n{{/* pathType was added to networking.k8s.io/v1beta1 in Kubernetes 1.18 */}}\n{{- define \"kube-prometheus-stack.ingress.supportsPathType\" -}}\n  {{- or (eq (include \"kube-prometheus-stack.ingress.isStable\" .) \"true\") (and (eq (include \"kube-prometheus-stack.ingress.apiVersion\" .) \"networking.k8s.io/v1beta1\") (semverCompare \">= 1.18.x\" (include \"kube-prometheus-stack.ingress.kubeVersion\" .))) -}}\n{{- end -}}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/alertmanager/alertmanager.yaml",
    "content": "{{- if .Values.alertmanager.enabled }}\napiVersion: monitoring.coreos.com/v1\nkind: Alertmanager\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-alertmanager\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-alertmanager\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.alertmanager.annotations }}\n  annotations:\n{{ toYaml .Values.alertmanager.annotations | indent 4 }}\n{{- end }}\nspec:\n{{- if .Values.alertmanager.alertmanagerSpec.image }}\n  image: {{ .Values.alertmanager.alertmanagerSpec.image.repository }}:{{ .Values.alertmanager.alertmanagerSpec.image.tag }}\n  version: {{ .Values.alertmanager.alertmanagerSpec.image.tag }}\n  {{- if .Values.alertmanager.alertmanagerSpec.image.sha }}\n  sha: {{ .Values.alertmanager.alertmanagerSpec.image.sha }}\n  {{- end }}\n{{- end }}\n  replicas: {{ .Values.alertmanager.alertmanagerSpec.replicas }}\n  listenLocal: {{ .Values.alertmanager.alertmanagerSpec.listenLocal }}\n  serviceAccountName: {{ template \"kube-prometheus-stack.alertmanager.serviceAccountName\" . }}\n{{- if .Values.alertmanager.alertmanagerSpec.externalUrl }}\n  externalUrl: \"{{ tpl .Values.alertmanager.alertmanagerSpec.externalUrl . }}\"\n{{- else if and .Values.alertmanager.ingress.enabled .Values.alertmanager.ingress.hosts }}\n  externalUrl: \"http://{{ tpl (index .Values.alertmanager.ingress.hosts 0) . }}{{ .Values.alertmanager.alertmanagerSpec.routePrefix }}\"\n{{- else }}\n  externalUrl: http://{{ template \"kube-prometheus-stack.fullname\" . }}-alertmanager.{{ template \"kube-prometheus-stack.namespace\" . }}:{{ .Values.alertmanager.service.port }}\n{{- end }}\n{{- if .Values.alertmanager.alertmanagerSpec.nodeSelector }}\n  nodeSelector:\n{{ toYaml .Values.alertmanager.alertmanagerSpec.nodeSelector | indent 4 }}\n{{- end }}\n  paused: {{ .Values.alertmanager.alertmanagerSpec.paused }}\n  logFormat: {{ .Values.alertmanager.alertmanagerSpec.logFormat | quote  }}\n  logLevel:  {{ .Values.alertmanager.alertmanagerSpec.logLevel | quote  }}\n  retention: {{ .Values.alertmanager.alertmanagerSpec.retention | quote  }}\n{{- if .Values.alertmanager.alertmanagerSpec.secrets }}\n  secrets:\n{{ toYaml .Values.alertmanager.alertmanagerSpec.secrets | indent 4 }}\n{{- end }}\n{{- if .Values.alertmanager.alertmanagerSpec.configSecret }}\n  configSecret: {{ .Values.alertmanager.alertmanagerSpec.configSecret }}\n{{- end }}\n{{- if .Values.alertmanager.alertmanagerSpec.configMaps }}\n  configMaps:\n{{ toYaml .Values.alertmanager.alertmanagerSpec.configMaps | indent 4 }}\n{{- end }}\n{{- if .Values.alertmanager.alertmanagerSpec.alertmanagerConfigSelector }}\n  alertmanagerConfigSelector:\n{{ toYaml .Values.alertmanager.alertmanagerSpec.alertmanagerConfigSelector | indent 4}}\n{{ else }}\n  alertmanagerConfigSelector: {}\n{{- end }}\n{{- if .Values.alertmanager.alertmanagerSpec.alertmanagerConfigNamespaceSelector }}\n  alertmanagerConfigNamespaceSelector:\n{{ toYaml .Values.alertmanager.alertmanagerSpec.alertmanagerConfigNamespaceSelector | indent 4}}\n{{ else }}\n  alertmanagerConfigNamespaceSelector: {}\n{{- end }}\n{{- if .Values.alertmanager.alertmanagerSpec.resources }}\n  resources:\n{{ toYaml .Values.alertmanager.alertmanagerSpec.resources | indent 4 }}\n{{- end }}\n{{- if .Values.alertmanager.alertmanagerSpec.routePrefix }}\n  routePrefix: \"{{ .Values.alertmanager.alertmanagerSpec.routePrefix }}\"\n{{- end }}\n{{- if .Values.alertmanager.alertmanagerSpec.securityContext }}\n  securityContext:\n{{ toYaml .Values.alertmanager.alertmanagerSpec.securityContext | indent 4 }}\n{{- end }}\n{{- if .Values.alertmanager.alertmanagerSpec.storage }}\n  storage:\n{{ toYaml .Values.alertmanager.alertmanagerSpec.storage | indent 4 }}\n{{- end }}\n{{- if .Values.alertmanager.alertmanagerSpec.podMetadata }}\n  podMetadata:\n{{ toYaml .Values.alertmanager.alertmanagerSpec.podMetadata | indent 4 }}\n{{- end }}\n{{- if or .Values.alertmanager.alertmanagerSpec.podAntiAffinity .Values.alertmanager.alertmanagerSpec.affinity }}\n  affinity:\n{{- if .Values.alertmanager.alertmanagerSpec.affinity }}\n{{ toYaml .Values.alertmanager.alertmanagerSpec.affinity | indent 4 }}\n{{- end }}\n{{- if eq .Values.alertmanager.alertmanagerSpec.podAntiAffinity \"hard\" }}\n    podAntiAffinity:\n      requiredDuringSchedulingIgnoredDuringExecution:\n      - topologyKey: {{ .Values.alertmanager.alertmanagerSpec.podAntiAffinityTopologyKey }}\n        labelSelector:\n          matchExpressions:\n            - {key: app, operator: In, values: [alertmanager]}\n            - {key: alertmanager, operator: In, values: [{{ template \"kube-prometheus-stack.fullname\" . }}-alertmanager]}\n{{- else if eq .Values.alertmanager.alertmanagerSpec.podAntiAffinity \"soft\" }}\n    podAntiAffinity:\n      preferredDuringSchedulingIgnoredDuringExecution:\n      - weight: 100\n        podAffinityTerm:\n          topologyKey: {{ .Values.alertmanager.alertmanagerSpec.podAntiAffinityTopologyKey }}\n          labelSelector:\n            matchExpressions:\n              - {key: app, operator: In, values: [alertmanager]}\n              - {key: prometheus, operator: In, values: [{{ template \"kube-prometheus-stack.fullname\" . }}-alertmanager]}\n{{- end }}\n{{- end }}\n{{- if .Values.alertmanager.alertmanagerSpec.tolerations }}\n  tolerations:\n{{ toYaml .Values.alertmanager.alertmanagerSpec.tolerations | indent 4 }}\n{{- end }}\n{{- if .Values.alertmanager.alertmanagerSpec.topologySpreadConstraints }}\n  topologySpreadConstraints:\n{{ toYaml .Values.alertmanager.alertmanagerSpec.topologySpreadConstraints | indent 4 }}\n{{- end }}\n{{- if .Values.global.imagePullSecrets }}\n  imagePullSecrets:\n{{ toYaml .Values.global.imagePullSecrets | indent 4 }}\n{{- end }}\n{{- if .Values.alertmanager.alertmanagerSpec.containers }}\n  containers:\n{{ toYaml .Values.alertmanager.alertmanagerSpec.containers | indent 4 }}\n{{- end }}\n{{- if .Values.alertmanager.alertmanagerSpec.initContainers }}\n  initContainers:\n{{ toYaml .Values.alertmanager.alertmanagerSpec.initContainers | indent 4 }}\n{{- end }}\n{{- if .Values.alertmanager.alertmanagerSpec.priorityClassName }}\n  priorityClassName: {{.Values.alertmanager.alertmanagerSpec.priorityClassName }}\n{{- end }}\n{{- if .Values.alertmanager.alertmanagerSpec.additionalPeers }}\n  additionalPeers:\n{{ toYaml .Values.alertmanager.alertmanagerSpec.additionalPeers | indent 4 }}\n{{- end }}\n{{- if .Values.alertmanager.alertmanagerSpec.volumes }}\n  volumes:\n{{ toYaml .Values.alertmanager.alertmanagerSpec.volumes | indent 4 }}\n{{- end }}\n{{- if .Values.alertmanager.alertmanagerSpec.volumeMounts }}\n  volumeMounts:\n{{ toYaml .Values.alertmanager.alertmanagerSpec.volumeMounts | indent 4 }}\n{{- end }}\n  portName: {{ .Values.alertmanager.alertmanagerSpec.portName }}\n{{- end }}\n{{- if .Values.alertmanager.alertmanagerSpec.clusterAdvertiseAddress }}\n  clusterAdvertiseAddress: {{ .Values.alertmanager.alertmanagerSpec.clusterAdvertiseAddress }}\n{{- end }}\n{{- if .Values.alertmanager.alertmanagerSpec.forceEnableClusterMode }}\n  forceEnableClusterMode: {{ .Values.alertmanager.alertmanagerSpec.forceEnableClusterMode }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/alertmanager/ingress.yaml",
    "content": "{{- if and .Values.alertmanager.enabled .Values.alertmanager.ingress.enabled }}\n{{- $pathType := .Values.alertmanager.ingress.pathType | default \"\" }}\n{{- $serviceName := printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"alertmanager\" }}\n{{- $servicePort := .Values.alertmanager.service.port -}}\n{{- $routePrefix := list .Values.alertmanager.alertmanagerSpec.routePrefix }}\n{{- $paths := .Values.alertmanager.ingress.paths | default $routePrefix -}}\n{{- $apiIsStable := eq (include \"kube-prometheus-stack.ingress.isStable\" .) \"true\" -}}\n{{- $ingressSupportsPathType := eq (include \"kube-prometheus-stack.ingress.supportsPathType\" .) \"true\" -}}\napiVersion: {{ include \"kube-prometheus-stack.ingress.apiVersion\" . }}\nkind: Ingress\nmetadata:\n  name: {{ $serviceName }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n{{- if .Values.alertmanager.ingress.annotations }}\n  annotations:\n{{ toYaml .Values.alertmanager.ingress.annotations | indent 4 }}\n{{- end }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-alertmanager\n{{- if .Values.alertmanager.ingress.labels }}\n{{ toYaml .Values.alertmanager.ingress.labels | indent 4 }}\n{{- end }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  {{- if $apiIsStable }}\n  {{- if .Values.alertmanager.ingress.ingressClassName }}\n  ingressClassName: {{ .Values.alertmanager.ingress.ingressClassName }}\n  {{- end }}\n  {{- end }}\n  rules:\n  {{- if .Values.alertmanager.ingress.hosts }}\n  {{- range $host := .Values.alertmanager.ingress.hosts }}\n    - host: {{ tpl $host $ }}\n      http:\n        paths:\n  {{- range $p := $paths }}\n          - path: {{ tpl $p $ }}\n            {{- if and $pathType $ingressSupportsPathType }}\n            pathType: {{ $pathType }}\n            {{- end }}\n            backend:\n              {{- if $apiIsStable }}\n              service:\n                name: {{ $serviceName }}\n                port:\n                  number: {{ $servicePort }}\n              {{- else }}\n              serviceName: {{ $serviceName }}\n              servicePort: {{ $servicePort }}\n    {{- end }}\n    {{- end -}}\n  {{- end -}}\n  {{- else }}\n    - http:\n        paths:\n  {{- range $p := $paths }}\n          - path: {{ tpl $p $ }}\n            {{- if and $pathType $ingressSupportsPathType }}\n            pathType: {{ $pathType }}\n            {{- end }}\n            backend:\n              {{- if $apiIsStable }}\n              service:\n                name: {{ $serviceName }}\n                port:\n                  number: {{ $servicePort }}\n              {{- else }}\n              serviceName: {{ $serviceName }}\n              servicePort: {{ $servicePort }}\n  {{- end }}\n  {{- end -}}\n  {{- end -}}\n  {{- if .Values.alertmanager.ingress.tls }}\n  tls:\n{{ tpl (toYaml .Values.alertmanager.ingress.tls | indent 4) . }}\n  {{- end -}}\n{{- end -}}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/alertmanager/ingressperreplica.yaml",
    "content": "{{- if and .Values.alertmanager.enabled .Values.alertmanager.servicePerReplica.enabled .Values.alertmanager.ingressPerReplica.enabled }}\n{{- $pathType := .Values.alertmanager.ingressPerReplica.pathType | default \"\" }}\n{{- $count := .Values.alertmanager.alertmanagerSpec.replicas | int -}}\n{{- $servicePort := .Values.alertmanager.service.port -}}\n{{- $ingressValues := .Values.alertmanager.ingressPerReplica -}}\n{{- $apiIsStable := eq (include \"kube-prometheus-stack.ingress.isStable\" .) \"true\" -}}\n{{- $ingressSupportsPathType := eq (include \"kube-prometheus-stack.ingress.supportsPathType\" .) \"true\" -}}\napiVersion: v1\nkind: List\nmetadata:\n  name: {{ include \"kube-prometheus-stack.fullname\" $ }}-alertmanager-ingressperreplica\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\nitems:\n{{ range $i, $e := until $count }}\n  - kind: Ingress\n    apiVersion: {{ include \"kube-prometheus-stack.ingress.apiVersion\" $ }}\n    metadata:\n      name: {{ include \"kube-prometheus-stack.fullname\" $ }}-alertmanager-{{ $i }}\n      namespace: {{ template \"kube-prometheus-stack.namespace\" $ }}\n      labels:\n        app: {{ include \"kube-prometheus-stack.name\" $ }}-alertmanager\n      {{ include \"kube-prometheus-stack.labels\" $ | indent 8 }}\n      {{- if $ingressValues.labels }}\n{{ toYaml $ingressValues.labels | indent 8 }}\n      {{- end }}\n      {{- if $ingressValues.annotations }}\n      annotations:\n{{ toYaml $ingressValues.annotations | indent 8 }}\n      {{- end }}\n    spec:\n      {{- if $apiIsStable }}\n      {{- if $ingressValues.ingressClassName }}\n      ingressClassName: {{ $ingressValues.ingressClassName }}\n      {{- end }}\n      {{- end }}\n      rules:\n        - host: {{ $ingressValues.hostPrefix }}-{{ $i }}.{{ $ingressValues.hostDomain }}\n          http:\n            paths:\n      {{- range $p := $ingressValues.paths }}\n              - path: {{ tpl $p $ }}\n                {{- if and $pathType $ingressSupportsPathType }}\n                pathType: {{ $pathType }}\n                {{- end }}\n                backend:\n                  {{- if $apiIsStable }}\n                  service:\n                    name: {{ include \"kube-prometheus-stack.fullname\" $ }}-alertmanager-{{ $i }}\n                    port:\n                      number: {{ $servicePort }}\n                  {{- else }}\n                  serviceName: {{ include \"kube-prometheus-stack.fullname\" $ }}-alertmanager-{{ $i }}\n                  servicePort: {{ $servicePort }}\n      {{- end }}\n      {{- end -}}\n      {{- if or $ingressValues.tlsSecretName $ingressValues.tlsSecretPerReplica.enabled }}\n      tls:\n        - hosts:\n            - {{ $ingressValues.hostPrefix }}-{{ $i }}.{{ $ingressValues.hostDomain }}\n          {{- if $ingressValues.tlsSecretPerReplica.enabled }}\n          secretName: {{ $ingressValues.tlsSecretPerReplica.prefix }}-{{ $i }}\n          {{- else }}\n          secretName: {{ $ingressValues.tlsSecretName }}\n          {{- end }}\n      {{- end }}\n{{- end -}}\n{{- end -}}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/alertmanager/podDisruptionBudget.yaml",
    "content": "{{- if and .Values.alertmanager.enabled .Values.alertmanager.podDisruptionBudget.enabled }}\napiVersion: policy/v1beta1\nkind: PodDisruptionBudget\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-alertmanager\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-alertmanager\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  {{- if .Values.alertmanager.podDisruptionBudget.minAvailable }}\n  minAvailable: {{ .Values.alertmanager.podDisruptionBudget.minAvailable }}\n  {{- end }}\n  {{- if .Values.alertmanager.podDisruptionBudget.maxUnavailable }}\n  maxUnavailable: {{ .Values.alertmanager.podDisruptionBudget.maxUnavailable }}\n  {{- end }}\n  selector:\n    matchLabels:\n      app: alertmanager\n      alertmanager: {{ template \"kube-prometheus-stack.fullname\" . }}-alertmanager\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/alertmanager/psp-role.yaml",
    "content": "{{- if and .Values.alertmanager.enabled .Values.global.rbac.create .Values.global.rbac.pspEnabled }}\nkind: Role\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-alertmanager\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-alertmanager\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nrules:\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if semverCompare \"> 1.15.0-0\" $kubeTargetVersion }}\n- apiGroups: ['policy']\n{{- else }}\n- apiGroups: ['extensions']\n{{- end }}\n  resources: ['podsecuritypolicies']\n  verbs:     ['use']\n  resourceNames:\n  - {{ template \"kube-prometheus-stack.fullname\" . }}-alertmanager\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/alertmanager/psp-rolebinding.yaml",
    "content": "{{- if and .Values.alertmanager.enabled .Values.global.rbac.create .Values.global.rbac.pspEnabled }}\napiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-alertmanager\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-alertmanager\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: Role\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-alertmanager\nsubjects:\n  - kind: ServiceAccount\n    name: {{ template \"kube-prometheus-stack.alertmanager.serviceAccountName\" . }}\n    namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/alertmanager/psp.yaml",
    "content": "{{- if and .Values.alertmanager.enabled .Values.global.rbac.create .Values.global.rbac.pspEnabled }}\napiVersion: policy/v1beta1\nkind: PodSecurityPolicy\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-alertmanager\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-alertmanager\n{{- if .Values.global.rbac.pspAnnotations }}\n  annotations:\n{{ toYaml .Values.global.rbac.pspAnnotations | indent 4 }}\n{{- end }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  privileged: false\n  # Required to prevent escalations to root.\n  # allowPrivilegeEscalation: false\n  # This is redundant with non-root + disallow privilege escalation,\n  # but we can provide it for defense in depth.\n  #requiredDropCapabilities:\n  #  - ALL\n  # Allow core volume types.\n  volumes:\n    - 'configMap'\n    - 'emptyDir'\n    - 'projected'\n    - 'secret'\n    - 'downwardAPI'\n    - 'persistentVolumeClaim'\n  hostNetwork: false\n  hostIPC: false\n  hostPID: false\n  runAsUser:\n    # Permits the container to run with root privileges as well.\n    rule: 'RunAsAny'\n  seLinux:\n    # This policy assumes the nodes are using AppArmor rather than SELinux.\n    rule: 'RunAsAny'\n  supplementalGroups:\n    rule: 'MustRunAs'\n    ranges:\n      # Forbid adding the root group.\n      - min: 0\n        max: 65535\n  fsGroup:\n    rule: 'MustRunAs'\n    ranges:\n      # Forbid adding the root group.\n      - min: 0\n        max: 65535\n  readOnlyRootFilesystem: false\n{{- end }}\n\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/alertmanager/secret.yaml",
    "content": "{{- if and (.Values.alertmanager.enabled) (not .Values.alertmanager.alertmanagerSpec.useExistingSecret) }}\napiVersion: v1\nkind: Secret\nmetadata:\n  name: alertmanager-{{ template \"kube-prometheus-stack.fullname\" . }}-alertmanager\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n{{- if .Values.alertmanager.secret.annotations }}\n  annotations:\n{{ toYaml .Values.alertmanager.secret.annotations | indent 4 }}\n{{- end }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-alertmanager\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\ndata:\n{{- if .Values.alertmanager.tplConfig }}\n  alertmanager.yaml: {{ tpl (toYaml .Values.alertmanager.config) . | b64enc | quote }}\n{{- else }}\n  alertmanager.yaml: {{ toYaml .Values.alertmanager.config | b64enc | quote }}\n{{- end}}\n{{- range $key, $val := .Values.alertmanager.templateFiles }}\n  {{ $key }}: {{ $val | b64enc | quote }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/alertmanager/service.yaml",
    "content": "{{- if .Values.alertmanager.enabled }}\napiVersion: v1\nkind: Service\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-alertmanager\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-alertmanager\n    self-monitor: {{ .Values.alertmanager.serviceMonitor.selfMonitor | quote }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.alertmanager.service.labels }}\n{{ toYaml .Values.alertmanager.service.labels | indent 4 }}\n{{- end }}\n{{- if .Values.alertmanager.service.annotations }}\n  annotations:\n{{ toYaml .Values.alertmanager.service.annotations | indent 4 }}\n{{- end }}\nspec:\n{{- if .Values.alertmanager.service.clusterIP }}\n  clusterIP: {{ .Values.alertmanager.service.clusterIP }}\n{{- end }}\n{{- if .Values.alertmanager.service.externalIPs }}\n  externalIPs:\n{{ toYaml .Values.alertmanager.service.externalIPs | indent 4 }}\n{{- end }}\n{{- if .Values.alertmanager.service.loadBalancerIP }}\n  loadBalancerIP: {{ .Values.alertmanager.service.loadBalancerIP }}\n{{- end }}\n{{- if .Values.alertmanager.service.loadBalancerSourceRanges }}\n  loadBalancerSourceRanges:\n  {{- range $cidr := .Values.alertmanager.service.loadBalancerSourceRanges }}\n    - {{ $cidr }}\n  {{- end }}\n{{- end }}\n  ports:\n  - name: {{ .Values.alertmanager.alertmanagerSpec.portName }}\n  {{- if eq .Values.alertmanager.service.type \"NodePort\" }}\n    nodePort: {{ .Values.alertmanager.service.nodePort }}\n  {{- end }}\n    port: {{ .Values.alertmanager.service.port }}\n    targetPort: {{ .Values.alertmanager.service.targetPort }}\n    protocol: TCP\n{{- if .Values.alertmanager.service.additionalPorts }}\n{{ toYaml .Values.alertmanager.service.additionalPorts | indent 2 }}\n{{- end }}\n  selector:\n    app: alertmanager\n    alertmanager: {{ template \"kube-prometheus-stack.fullname\" . }}-alertmanager\n  type: \"{{ .Values.alertmanager.service.type }}\"\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/alertmanager/serviceaccount.yaml",
    "content": "{{- if and .Values.alertmanager.enabled .Values.alertmanager.serviceAccount.create }}\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: {{ template \"kube-prometheus-stack.alertmanager.serviceAccountName\" . }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-alertmanager\n    app.kubernetes.io/name: {{ template \"kube-prometheus-stack.name\" . }}-alertmanager\n    app.kubernetes.io/component: alertmanager\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.alertmanager.serviceAccount.annotations }}\n  annotations:\n{{ toYaml .Values.alertmanager.serviceAccount.annotations | indent 4 }}\n{{- end }}\n{{- if .Values.global.imagePullSecrets }}\nimagePullSecrets:\n{{ toYaml .Values.global.imagePullSecrets | indent 2 }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/alertmanager/servicemonitor.yaml",
    "content": "{{- if and .Values.alertmanager.enabled .Values.alertmanager.serviceMonitor.selfMonitor }}\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-alertmanager\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-alertmanager\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  selector:\n    matchLabels:\n      app: {{ template \"kube-prometheus-stack.name\" . }}-alertmanager\n      release: {{ $.Release.Name | quote }}\n      self-monitor: \"true\"\n  namespaceSelector:\n    matchNames:\n      - {{ printf \"%s\" (include \"kube-prometheus-stack.namespace\" .) | quote }}\n  endpoints:\n  - port: {{ .Values.alertmanager.alertmanagerSpec.portName }}\n    {{- if .Values.alertmanager.serviceMonitor.interval }}\n    interval: {{ .Values.alertmanager.serviceMonitor.interval }}\n    {{- end }}\n    {{- if .Values.alertmanager.serviceMonitor.proxyUrl }}\n    proxyUrl: {{ .Values.alertmanager.serviceMonitor.proxyUrl}}\n    {{- end }}\n    {{- if .Values.alertmanager.serviceMonitor.scheme }}\n    scheme: {{ .Values.alertmanager.serviceMonitor.scheme }}\n    {{- end }}\n    {{- if .Values.alertmanager.serviceMonitor.bearerTokenFile }}\n    bearerTokenFile: {{ .Values.alertmanager.serviceMonitor.bearerTokenFile }}\n    {{- end }}\n    {{- if .Values.alertmanager.serviceMonitor.tlsConfig }}\n    tlsConfig: {{ toYaml .Values.alertmanager.serviceMonitor.tlsConfig | nindent 6 }}\n    {{- end }}\n    path: \"{{ trimSuffix \"/\" .Values.alertmanager.alertmanagerSpec.routePrefix }}/metrics\"\n{{- if .Values.alertmanager.serviceMonitor.metricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.alertmanager.serviceMonitor.metricRelabelings | indent 6) . }}\n{{- end }}\n{{- if .Values.alertmanager.serviceMonitor.relabelings }}\n    relabelings:\n{{ toYaml .Values.alertmanager.serviceMonitor.relabelings | indent 6 }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/alertmanager/serviceperreplica.yaml",
    "content": "{{- if and .Values.alertmanager.enabled .Values.alertmanager.servicePerReplica.enabled }}\n{{- $count := .Values.alertmanager.alertmanagerSpec.replicas | int -}}\n{{- $serviceValues := .Values.alertmanager.servicePerReplica -}}\napiVersion: v1\nkind: List\nmetadata:\n  name: {{ include \"kube-prometheus-stack.fullname\" $ }}-alertmanager-serviceperreplica\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\nitems:\n{{- range $i, $e := until $count }}\n  - apiVersion: v1\n    kind: Service\n    metadata:\n      name: {{ include \"kube-prometheus-stack.fullname\" $ }}-alertmanager-{{ $i }}\n      namespace: {{ template \"kube-prometheus-stack.namespace\" $ }}\n      labels:\n        app: {{ include \"kube-prometheus-stack.name\" $ }}-alertmanager\n{{ include \"kube-prometheus-stack.labels\" $ | indent 8 }}\n      {{- if $serviceValues.annotations }}\n      annotations:\n{{ toYaml $serviceValues.annotations | indent 8 }}\n      {{- end }}\n    spec:\n      {{- if $serviceValues.clusterIP }}\n      clusterIP: {{ $serviceValues.clusterIP }}\n      {{- end }}\n      {{- if $serviceValues.loadBalancerSourceRanges }}\n      loadBalancerSourceRanges:\n      {{- range $cidr := $serviceValues.loadBalancerSourceRanges }}\n        - {{ $cidr }}\n      {{- end }}\n      {{- end }}\n      ports:\n        - name: {{ $.Values.alertmanager.alertmanagerSpec.portName }}\n          {{- if eq $serviceValues.type \"NodePort\" }}\n          nodePort: {{ $serviceValues.nodePort }}\n          {{- end }}\n          port: {{ $serviceValues.port }}\n          targetPort: {{ $serviceValues.targetPort }}\n      selector:\n        app: alertmanager\n        alertmanager: {{ template \"kube-prometheus-stack.fullname\" $ }}-alertmanager\n        statefulset.kubernetes.io/pod-name: alertmanager-{{ include \"kube-prometheus-stack.fullname\" $ }}-alertmanager-{{ $i }}\n      type: \"{{ $serviceValues.type }}\"\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/exporters/core-dns/service.yaml",
    "content": "{{- if .Values.coreDns.enabled }}\napiVersion: v1\nkind: Service\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-coredns\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-coredns\n    jobLabel: coredns\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n  namespace: kube-system\nspec:\n  clusterIP: None\n  ports:\n    - name: http-metrics\n      port: {{ .Values.coreDns.service.port }}\n      protocol: TCP\n      targetPort: {{ .Values.coreDns.service.targetPort }}\n  selector:\n    {{- if .Values.coreDns.service.selector }}\n{{ toYaml .Values.coreDns.service.selector | indent 4 }}\n    {{- else}}\n    k8s-app: kube-dns\n    {{- end}}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/exporters/core-dns/servicemonitor.yaml",
    "content": "{{- if .Values.coreDns.enabled }}\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-coredns\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-coredns\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  jobLabel: jobLabel\n  selector:\n    matchLabels:\n      app: {{ template \"kube-prometheus-stack.name\" . }}-coredns\n      release: {{ $.Release.Name | quote }}\n  namespaceSelector:\n    matchNames:\n      - \"kube-system\"\n  endpoints:\n  - port: http-metrics\n    {{- if .Values.coreDns.serviceMonitor.interval}}\n    interval: {{ .Values.coreDns.serviceMonitor.interval }}\n    {{- end }}\n    {{- if .Values.coreDns.serviceMonitor.proxyUrl }}\n    proxyUrl: {{ .Values.coreDns.serviceMonitor.proxyUrl}}\n    {{- end }}\n    bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n{{- if .Values.coreDns.serviceMonitor.metricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.coreDns.serviceMonitor.metricRelabelings | indent 4) . }}\n{{- end }}\n{{- if .Values.coreDns.serviceMonitor.relabelings }}\n    relabelings:\n{{ toYaml .Values.coreDns.serviceMonitor.relabelings | indent 4 }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/exporters/kube-api-server/servicemonitor.yaml",
    "content": "{{- if .Values.kubeApiServer.enabled }}\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-apiserver\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-apiserver\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  endpoints:\n  - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n    {{- if .Values.kubeApiServer.serviceMonitor.interval }}\n    interval: {{ .Values.kubeApiServer.serviceMonitor.interval }}\n    {{- end }}\n    {{- if .Values.kubeApiServer.serviceMonitor.proxyUrl }}\n    proxyUrl: {{ .Values.kubeApiServer.serviceMonitor.proxyUrl}}\n    {{- end }}\n    port: https\n    scheme: https\n{{- if .Values.kubeApiServer.serviceMonitor.metricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.kubeApiServer.serviceMonitor.metricRelabelings | indent 6) . }}\n{{- end }}\n{{- if .Values.kubeApiServer.serviceMonitor.relabelings }}\n    relabelings:\n{{ toYaml .Values.kubeApiServer.serviceMonitor.relabelings | indent 6 }}\n{{- end }}\n    tlsConfig:\n      caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt\n      serverName: {{ .Values.kubeApiServer.tlsConfig.serverName }}\n      insecureSkipVerify: {{ .Values.kubeApiServer.tlsConfig.insecureSkipVerify }}\n  jobLabel: {{ .Values.kubeApiServer.serviceMonitor.jobLabel }}\n  namespaceSelector:\n    matchNames:\n    - default\n  selector:\n{{ toYaml .Values.kubeApiServer.serviceMonitor.selector | indent 4 }}\n{{- end}}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/exporters/kube-controller-manager/endpoints.yaml",
    "content": "{{- if and .Values.kubeControllerManager.enabled .Values.kubeControllerManager.endpoints }}\napiVersion: v1\nkind: Endpoints\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-kube-controller-manager\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-kube-controller-manager\n    k8s-app: kube-controller-manager\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n  namespace: kube-system \nsubsets:\n  - addresses:\n      {{- range .Values.kubeControllerManager.endpoints }}\n      - ip: {{ . }}\n      {{- end }}\n    ports:\n      - name: http-metrics\n        port: {{ .Values.kubeControllerManager.service.port }}\n        protocol: TCP\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/exporters/kube-controller-manager/service.yaml",
    "content": "{{- if and .Values.kubeControllerManager.enabled .Values.kubeControllerManager.service.enabled }}\napiVersion: v1\nkind: Service\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-kube-controller-manager\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-kube-controller-manager\n    jobLabel: kube-controller-manager\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n  namespace: kube-system\nspec:\n  clusterIP: None\n  ports:\n    - name: http-metrics\n      port: {{ .Values.kubeControllerManager.service.port }}\n      protocol: TCP\n      targetPort: {{ .Values.kubeControllerManager.service.targetPort }}\n{{- if .Values.kubeControllerManager.endpoints }}{{- else }}\n  selector:\n    {{- if .Values.kubeControllerManager.service.selector }}\n{{ toYaml .Values.kubeControllerManager.service.selector | indent 4 }}\n    {{- else}}\n    component: kube-controller-manager\n    {{- end}}\n{{- end }}\n  type: ClusterIP\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/exporters/kube-controller-manager/servicemonitor.yaml",
    "content": "{{- if and .Values.kubeControllerManager.enabled .Values.kubeControllerManager.serviceMonitor.enabled }}\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-kube-controller-manager\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-kube-controller-manager\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  jobLabel: jobLabel\n  selector:\n    matchLabels:\n      app: {{ template \"kube-prometheus-stack.name\" . }}-kube-controller-manager\n      release: {{ $.Release.Name | quote }}\n  namespaceSelector:\n    matchNames:\n      - \"kube-system\"\n  endpoints:\n  - port: http-metrics\n    {{- if .Values.kubeControllerManager.serviceMonitor.interval }}\n    interval: {{ .Values.kubeControllerManager.serviceMonitor.interval }}\n    {{- end }}\n    bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n    {{- if .Values.kubeControllerManager.serviceMonitor.proxyUrl }}\n    proxyUrl: {{ .Values.kubeControllerManager.serviceMonitor.proxyUrl}}\n    {{- end }}\n    {{- if .Values.kubeControllerManager.serviceMonitor.https }}\n    scheme: https\n    tlsConfig:\n      caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt\n      {{- if .Values.kubeControllerManager.serviceMonitor.insecureSkipVerify }}\n      insecureSkipVerify: {{ .Values.kubeControllerManager.serviceMonitor.insecureSkipVerify }}\n      {{- end }}\n      {{- if .Values.kubeControllerManager.serviceMonitor.serverName }}\n      serverName: {{ .Values.kubeControllerManager.serviceMonitor.serverName }}\n      {{- end }}\n    {{- end }}\n{{- if .Values.kubeControllerManager.serviceMonitor.metricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.kubeControllerManager.serviceMonitor.metricRelabelings | indent 4) . }}\n{{- end }}\n{{- if .Values.kubeControllerManager.serviceMonitor.relabelings }}\n    relabelings:\n{{ toYaml .Values.kubeControllerManager.serviceMonitor.relabelings | indent 4 }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/exporters/kube-dns/service.yaml",
    "content": "{{- if .Values.kubeDns.enabled }}\napiVersion: v1\nkind: Service\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-kube-dns\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-kube-dns\n    jobLabel: kube-dns\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n  namespace: kube-system\nspec:\n  clusterIP: None\n  ports:\n    - name: http-metrics-dnsmasq\n      port: {{ .Values.kubeDns.service.dnsmasq.port }}\n      protocol: TCP\n      targetPort: {{ .Values.kubeDns.service.dnsmasq.targetPort }}\n    - name: http-metrics-skydns\n      port: {{ .Values.kubeDns.service.skydns.port }}\n      protocol: TCP\n      targetPort: {{ .Values.kubeDns.service.skydns.targetPort }}\n  selector:\n    {{- if .Values.kubeDns.service.selector }}\n{{ toYaml .Values.kubeDns.service.selector | indent 4 }}\n    {{- else}}\n    k8s-app: kube-dns\n    {{- end}}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/exporters/kube-dns/servicemonitor.yaml",
    "content": "{{- if .Values.kubeDns.enabled }}\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-kube-dns\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-kube-dns\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  jobLabel: jobLabel\n  selector:\n    matchLabels:\n      app: {{ template \"kube-prometheus-stack.name\" . }}-kube-dns\n      release: {{ $.Release.Name | quote }}\n  namespaceSelector:\n    matchNames:\n      - \"kube-system\"\n  endpoints:\n  - port: http-metrics-dnsmasq\n    {{- if .Values.kubeDns.serviceMonitor.interval }}\n    interval: {{ .Values.kubeDns.serviceMonitor.interval }}\n    {{- end }}\n    bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n    {{- if .Values.kubeDns.serviceMonitor.proxyUrl }}\n    proxyUrl: {{ .Values.kubeDns.serviceMonitor.proxyUrl}}\n    {{- end }}\n{{- if .Values.kubeDns.serviceMonitor.dnsmasqMetricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.kubeDns.serviceMonitor.dnsmasqMetricRelabelings | indent 4) . }}\n{{- end }}\n{{- if .Values.kubeDns.serviceMonitor.dnsmasqRelabelings }}\n    relabelings:\n{{ toYaml .Values.kubeDns.serviceMonitor.dnsmasqRelabelings | indent 4 }}\n{{- end }}\n  - port: http-metrics-skydns\n    {{- if .Values.kubeDns.serviceMonitor.interval }}\n    interval: {{ .Values.kubeDns.serviceMonitor.interval }}\n    {{- end }}\n    bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n{{- if .Values.kubeDns.serviceMonitor.metricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.kubeDns.serviceMonitor.metricRelabelings | indent 4) . }}\n{{- end }}\n{{- if .Values.kubeDns.serviceMonitor.relabelings }}\n    relabelings:\n{{ toYaml .Values.kubeDns.serviceMonitor.relabelings | indent 4 }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/exporters/kube-etcd/endpoints.yaml",
    "content": "{{- if and .Values.kubeEtcd.enabled .Values.kubeEtcd.endpoints }}\napiVersion: v1\nkind: Endpoints\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-kube-etcd\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-kube-etcd\n    k8s-app: etcd-server\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n  namespace: kube-system\nsubsets:\n  - addresses:\n      {{- range .Values.kubeEtcd.endpoints }}\n      - ip: {{ . }}\n      {{- end }}\n    ports:\n      - name: http-metrics\n        port: {{ .Values.kubeEtcd.service.port }}\n        protocol: TCP\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/exporters/kube-etcd/service.yaml",
    "content": "{{- if and .Values.kubeEtcd.enabled .Values.kubeEtcd.service.enabled }}\napiVersion: v1\nkind: Service\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-kube-etcd\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-kube-etcd\n    jobLabel: kube-etcd\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n  namespace: kube-system\nspec:\n  clusterIP: None\n  ports:\n    - name: http-metrics\n      port: {{ .Values.kubeEtcd.service.port }}\n      protocol: TCP\n      targetPort: {{ .Values.kubeEtcd.service.targetPort }}\n{{- if .Values.kubeEtcd.endpoints }}{{- else }}\n  selector:\n    {{- if .Values.kubeEtcd.service.selector }}\n{{ toYaml .Values.kubeEtcd.service.selector | indent 4 }}\n    {{- else}}\n    component: etcd\n    {{- end}}\n{{- end }}\n  type: ClusterIP\n{{- end -}}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/exporters/kube-etcd/servicemonitor.yaml",
    "content": "{{- if and .Values.kubeEtcd.enabled .Values.kubeEtcd.serviceMonitor.enabled }}\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-kube-etcd\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-kube-etcd\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  jobLabel: jobLabel\n  selector:\n    matchLabels:\n      app: {{ template \"kube-prometheus-stack.name\" . }}-kube-etcd\n      release: {{ $.Release.Name | quote }}\n  namespaceSelector:\n    matchNames:\n      - \"kube-system\"\n  endpoints:\n  - port: http-metrics\n    {{- if .Values.kubeEtcd.serviceMonitor.interval }}\n    interval: {{ .Values.kubeEtcd.serviceMonitor.interval }}\n    {{- end }}\n    bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n    {{- if .Values.kubeEtcd.serviceMonitor.proxyUrl }}\n    proxyUrl: {{ .Values.kubeEtcd.serviceMonitor.proxyUrl}}\n    {{- end }}\n    {{- if eq .Values.kubeEtcd.serviceMonitor.scheme \"https\" }}\n    scheme: https\n    tlsConfig:\n      {{- if .Values.kubeEtcd.serviceMonitor.serverName }}\n      serverName: {{ .Values.kubeEtcd.serviceMonitor.serverName }}\n      {{- end }}\n      {{- if .Values.kubeEtcd.serviceMonitor.caFile }}\n      caFile: {{ .Values.kubeEtcd.serviceMonitor.caFile }}\n      {{- end }}\n      {{- if  .Values.kubeEtcd.serviceMonitor.certFile }}\n      certFile: {{ .Values.kubeEtcd.serviceMonitor.certFile }}\n      {{- end }}\n      {{- if .Values.kubeEtcd.serviceMonitor.keyFile }}\n      keyFile: {{ .Values.kubeEtcd.serviceMonitor.keyFile }}\n      {{- end}}\n      insecureSkipVerify: {{ .Values.kubeEtcd.serviceMonitor.insecureSkipVerify }}\n    {{- end }}\n{{- if .Values.kubeEtcd.serviceMonitor.metricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.kubeEtcd.serviceMonitor.metricRelabelings | indent 4) . }}\n{{- end }}\n{{- if .Values.kubeEtcd.serviceMonitor.relabelings }}\n    relabelings:\n{{ toYaml .Values.kubeEtcd.serviceMonitor.relabelings | indent 4 }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/exporters/kube-proxy/endpoints.yaml",
    "content": "{{- if and .Values.kubeProxy.enabled .Values.kubeProxy.endpoints }}\napiVersion: v1\nkind: Endpoints\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-kube-proxy\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-kube-proxy\n    k8s-app: kube-proxy\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n  namespace: kube-system\nsubsets:\n  - addresses:\n      {{- range .Values.kubeProxy.endpoints }}\n      - ip: {{ . }}\n      {{- end }}\n    ports:\n      - name: http-metrics\n        port: {{ .Values.kubeProxy.service.port }}\n        protocol: TCP\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/exporters/kube-proxy/service.yaml",
    "content": "{{- if and .Values.kubeProxy.enabled .Values.kubeProxy.service.enabled }}\napiVersion: v1\nkind: Service\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-kube-proxy\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-kube-proxy\n    jobLabel: kube-proxy\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n  namespace: kube-system\nspec:\n  clusterIP: None\n  ports:\n    - name: http-metrics\n      port: {{ .Values.kubeProxy.service.port }}\n      protocol: TCP\n      targetPort: {{ .Values.kubeProxy.service.targetPort }}\n{{- if .Values.kubeProxy.endpoints }}{{- else }}\n  selector:\n    {{- if .Values.kubeProxy.service.selector }}\n{{ toYaml .Values.kubeProxy.service.selector | indent 4 }}\n    {{- else}}\n    k8s-app: kube-proxy\n    {{- end}}\n{{- end }}\n  type: ClusterIP\n{{- end -}}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/exporters/kube-proxy/servicemonitor.yaml",
    "content": "{{- if and .Values.kubeProxy.enabled .Values.kubeProxy.serviceMonitor.enabled }}\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-kube-proxy\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-kube-proxy\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  jobLabel: jobLabel\n  selector:\n    matchLabels:\n      app: {{ template \"kube-prometheus-stack.name\" . }}-kube-proxy\n      release: {{ $.Release.Name | quote }}\n  namespaceSelector:\n    matchNames:\n      - \"kube-system\"\n  endpoints:\n  - port: http-metrics\n    {{- if .Values.kubeProxy.serviceMonitor.interval }}\n    interval: {{ .Values.kubeProxy.serviceMonitor.interval }}\n    {{- end }}\n    bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n    {{- if .Values.kubeProxy.serviceMonitor.proxyUrl }}\n    proxyUrl: {{ .Values.kubeProxy.serviceMonitor.proxyUrl}}\n    {{- end }}\n    {{- if .Values.kubeProxy.serviceMonitor.https }}\n    scheme: https\n    tlsConfig:\n      caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt\n    {{- end}}\n{{- if .Values.kubeProxy.serviceMonitor.metricRelabelings }}\n    metricRelabelings:\n{{ toYaml .Values.kubeProxy.serviceMonitor.metricRelabelings | indent 4 }}\n{{- end }}\n{{- if .Values.kubeProxy.serviceMonitor.relabelings }}\n    relabelings:\n{{ toYaml .Values.kubeProxy.serviceMonitor.relabelings | indent 4 }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/exporters/kube-scheduler/endpoints.yaml",
    "content": "{{- if and .Values.kubeScheduler.enabled .Values.kubeScheduler.endpoints }}\napiVersion: v1\nkind: Endpoints\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-kube-scheduler\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-kube-scheduler\n    k8s-app: kube-scheduler\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n  namespace: kube-system\nsubsets:\n  - addresses:\n      {{- range .Values.kubeScheduler.endpoints }}\n      - ip: {{ . }}\n      {{- end }}\n    ports:\n      - name: http-metrics\n        port: {{ .Values.kubeScheduler.service.port }}\n        protocol: TCP\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/exporters/kube-scheduler/service.yaml",
    "content": "{{- if and .Values.kubeScheduler.enabled .Values.kubeScheduler.service.enabled }}\napiVersion: v1\nkind: Service\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-kube-scheduler\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-kube-scheduler\n    jobLabel: kube-scheduler\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n  namespace: kube-system\nspec:\n  clusterIP: None\n  ports:\n    - name: http-metrics\n      port: {{ .Values.kubeScheduler.service.port}}\n      protocol: TCP\n      targetPort: {{ .Values.kubeScheduler.service.targetPort}}\n{{- if .Values.kubeScheduler.endpoints }}{{- else }}\n  selector:\n    {{- if .Values.kubeScheduler.service.selector }}\n{{ toYaml .Values.kubeScheduler.service.selector | indent 4 }}\n    {{- else}}\n    component: kube-scheduler\n    {{- end}}\n{{- end }}\n  type: ClusterIP\n{{- end -}}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/exporters/kube-scheduler/servicemonitor.yaml",
    "content": "{{- if and .Values.kubeScheduler.enabled .Values.kubeScheduler.serviceMonitor.enabled }}\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-kube-scheduler\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-kube-scheduler\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  jobLabel: jobLabel\n  selector:\n    matchLabels:\n      app: {{ template \"kube-prometheus-stack.name\" . }}-kube-scheduler\n      release: {{ $.Release.Name | quote }}\n  namespaceSelector:\n    matchNames:\n      - \"kube-system\"\n  endpoints:\n  - port: http-metrics\n    {{- if .Values.kubeScheduler.serviceMonitor.interval }}\n    interval: {{ .Values.kubeScheduler.serviceMonitor.interval }}\n    {{- end }}\n    bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n    {{- if .Values.kubeScheduler.serviceMonitor.proxyUrl }}\n    proxyUrl: {{ .Values.kubeScheduler.serviceMonitor.proxyUrl}}\n    {{- end }}\n    {{- if .Values.kubeScheduler.serviceMonitor.https }}\n    scheme: https\n    tlsConfig:\n      caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt\n      {{- if .Values.kubeScheduler.serviceMonitor.insecureSkipVerify }}\n      insecureSkipVerify: {{ .Values.kubeScheduler.serviceMonitor.insecureSkipVerify }}\n      {{- end}}\n      {{- if .Values.kubeScheduler.serviceMonitor.serverName }}\n      serverName: {{ .Values.kubeScheduler.serviceMonitor.serverName }}\n      {{- end}}\n    {{- end}}\n{{- if .Values.kubeScheduler.serviceMonitor.metricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.kubeScheduler.serviceMonitor.metricRelabelings | indent 4) . }}\n{{- end }}\n{{- if .Values.kubeScheduler.serviceMonitor.relabelings }}\n    relabelings:\n{{ toYaml .Values.kubeScheduler.serviceMonitor.relabelings | indent 4 }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/exporters/kube-state-metrics/serviceMonitor.yaml",
    "content": "{{- if .Values.kubeStateMetrics.enabled }}\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-kube-state-metrics\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-kube-state-metrics\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  jobLabel: app.kubernetes.io/name\n  endpoints:\n  - port: http\n    {{- if .Values.kubeStateMetrics.serviceMonitor.interval }}\n    interval: {{ .Values.kubeStateMetrics.serviceMonitor.interval }}\n    {{- end }}\n    {{- if .Values.kubeStateMetrics.serviceMonitor.proxyUrl }}\n    proxyUrl: {{ .Values.kubeStateMetrics.serviceMonitor.proxyUrl}}\n    {{- end }}\n    honorLabels: true\n{{- if .Values.kubeStateMetrics.serviceMonitor.metricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.kubeStateMetrics.serviceMonitor.metricRelabelings | indent 4) . }}\n{{- end }}\n{{- if .Values.kubeStateMetrics.serviceMonitor.relabelings }}\n    relabelings:\n{{ toYaml .Values.kubeStateMetrics.serviceMonitor.relabelings | indent 4 }}\n{{- end }}\n{{- if .Values.kubeStateMetrics.serviceMonitor.selfMonitor.enabled }}\n  - port: metrics\n    {{- if .Values.kubeStateMetrics.serviceMonitor.interval }}\n    interval: {{ .Values.kubeStateMetrics.serviceMonitor.interval }}\n    {{- end }}\n    {{- if .Values.kubeStateMetrics.serviceMonitor.proxyUrl }}\n    proxyUrl: {{ .Values.kubeStateMetrics.serviceMonitor.proxyUrl}}\n    {{- end }}\n    honorLabels: true\n{{- if .Values.kubeStateMetrics.serviceMonitor.metricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.kubeStateMetrics.serviceMonitor.metricRelabelings | indent 4) . }}\n{{- end }}\n{{- if .Values.kubeStateMetrics.serviceMonitor.relabelings }}\n    relabelings:\n{{ toYaml .Values.kubeStateMetrics.serviceMonitor.relabelings | indent 4 }}\n{{- end }}\n{{- end }}\n{{- if .Values.kubeStateMetrics.serviceMonitor.namespaceOverride }}\n  namespaceSelector:\n    matchNames:\n      - {{ .Values.kubeStateMetrics.serviceMonitor.namespaceOverride }}\n{{- end }}\n  selector:\n    matchLabels:\n{{- if .Values.kubeStateMetrics.serviceMonitor.selectorOverride }}\n{{ toYaml .Values.kubeStateMetrics.serviceMonitor.selectorOverride | indent 6 }}\n{{ else }}\n      app.kubernetes.io/name: kube-state-metrics\n      app.kubernetes.io/instance: \"{{ $.Release.Name }}\"\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/exporters/kubelet/servicemonitor.yaml",
    "content": "{{- if .Values.kubelet.enabled }}\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-kubelet\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-kubelet\n{{- include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  endpoints:\n  {{- if .Values.kubelet.serviceMonitor.https }}\n  - port: https-metrics\n    scheme: https\n    {{- if .Values.kubelet.serviceMonitor.interval }}\n    interval: {{ .Values.kubelet.serviceMonitor.interval }}\n    {{- end }}\n    {{- if .Values.kubelet.serviceMonitor.proxyUrl }}\n    proxyUrl: {{ .Values.kubelet.serviceMonitor.proxyUrl }}\n    {{- end }}\n    tlsConfig:\n      caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt\n      insecureSkipVerify: true\n    bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n    honorLabels: true\n{{- if .Values.kubelet.serviceMonitor.metricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.kubelet.serviceMonitor.metricRelabelings | indent 4) . }}\n{{- end }}\n{{- if .Values.kubelet.serviceMonitor.relabelings }}\n    relabelings:\n{{ toYaml .Values.kubelet.serviceMonitor.relabelings | indent 4 }}\n{{- end }}\n{{- if .Values.kubelet.serviceMonitor.cAdvisor }}\n  - port: https-metrics\n    scheme: https\n    path: /metrics/cadvisor\n    {{- if .Values.kubelet.serviceMonitor.interval }}\n    interval: {{ .Values.kubelet.serviceMonitor.interval }}\n    {{- end }}\n    {{- if .Values.kubelet.serviceMonitor.proxyUrl }}\n    proxyUrl: {{ .Values.kubelet.serviceMonitor.proxyUrl }}\n    {{- end }}\n    {{- if .Values.kubelet.serviceMonitor.scrapeTimeout }}\n    scrapeTimeout: {{ .Values.kubelet.serviceMonitor.scrapeTimeout }}\n    {{- end }}\n    honorLabels: true\n    tlsConfig:\n      caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt\n      insecureSkipVerify: true\n    bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n{{- if .Values.kubelet.serviceMonitor.cAdvisorMetricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.kubelet.serviceMonitor.cAdvisorMetricRelabelings | indent 4) . }}\n{{- end }}\n{{- if .Values.kubelet.serviceMonitor.cAdvisorRelabelings }}\n    relabelings:\n{{ toYaml .Values.kubelet.serviceMonitor.cAdvisorRelabelings | indent 4 }}\n{{- end }}\n{{- end }}\n{{- if .Values.kubelet.serviceMonitor.probes }}\n  - port: https-metrics\n    scheme: https\n    path: /metrics/probes\n    {{- if .Values.kubelet.serviceMonitor.interval }}\n    interval: {{ .Values.kubelet.serviceMonitor.interval }}\n    {{- end }}\n    {{- if .Values.kubelet.serviceMonitor.proxyUrl }}\n    proxyUrl: {{ .Values.kubelet.serviceMonitor.proxyUrl }}\n    {{- end }}\n    honorLabels: true\n    tlsConfig:\n      caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt\n      insecureSkipVerify: true\n    bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n{{- if .Values.kubelet.serviceMonitor.probesMetricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.kubelet.serviceMonitor.probesMetricRelabelings | indent 4) . }}\n{{- end }}\n{{- if .Values.kubelet.serviceMonitor.probesRelabelings }}\n    relabelings:\n{{ toYaml .Values.kubelet.serviceMonitor.probesRelabelings | indent 4 }}\n{{- end }}\n{{- end }}\n{{- if .Values.kubelet.serviceMonitor.resource }}\n  - port: https-metrics\n    scheme: https\n    path: {{ .Values.kubelet.serviceMonitor.resourcePath }}\n    {{- if .Values.kubelet.serviceMonitor.interval }}\n    interval: {{ .Values.kubelet.serviceMonitor.interval }}\n    {{- end }}\n    {{- if .Values.kubelet.serviceMonitor.proxyUrl }}\n    proxyUrl: {{ .Values.kubelet.serviceMonitor.proxyUrl }}\n    {{- end }}\n    honorLabels: true\n    tlsConfig:\n      caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt\n      insecureSkipVerify: true\n    bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n{{- if .Values.kubelet.serviceMonitor.resourceMetricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.kubelet.serviceMonitor.resourceMetricRelabelings | indent 4) . }}\n{{- end }}\n{{- if .Values.kubelet.serviceMonitor.resourceRelabelings }}\n    relabelings:\n{{ toYaml .Values.kubelet.serviceMonitor.resourceRelabelings | indent 4 }}\n{{- end }}\n{{- end }}\n  {{- else }}\n  - port: http-metrics\n    {{- if .Values.kubelet.serviceMonitor.interval }}\n    interval: {{ .Values.kubelet.serviceMonitor.interval }}\n    {{- end }}\n    {{- if .Values.kubelet.serviceMonitor.proxyUrl }}\n    proxyUrl: {{ .Values.kubelet.serviceMonitor.proxyUrl }}\n    {{- end }}\n    honorLabels: true\n{{- if .Values.kubelet.serviceMonitor.metricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.kubelet.serviceMonitor.metricRelabelings | indent 4) . }}\n{{- end }}\n{{- if .Values.kubelet.serviceMonitor.relabelings }}\n    relabelings:\n{{ toYaml .Values.kubelet.serviceMonitor.relabelings | indent 4 }}\n{{- end }}\n{{- if .Values.kubelet.serviceMonitor.cAdvisor }}\n  - port: http-metrics\n    path: /metrics/cadvisor\n    {{- if .Values.kubelet.serviceMonitor.interval }}\n    interval: {{ .Values.kubelet.serviceMonitor.interval }}\n    {{- end }}\n    {{- if .Values.kubelet.serviceMonitor.proxyUrl }}\n    proxyUrl: {{ .Values.kubelet.serviceMonitor.proxyUrl }}\n    {{- end }}\n    honorLabels: true\n{{- if .Values.kubelet.serviceMonitor.cAdvisorMetricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.kubelet.serviceMonitor.cAdvisorMetricRelabelings | indent 4) . }}\n{{- end }}\n{{- if .Values.kubelet.serviceMonitor.cAdvisorRelabelings }}\n    relabelings:\n{{ toYaml .Values.kubelet.serviceMonitor.cAdvisorRelabelings | indent 4 }}\n{{- end }}\n{{- if .Values.kubelet.serviceMonitor.resource }}\n  - port: http-metrics\n    path: {{ .Values.kubelet.serviceMonitor.resourcePath }}\n    {{- if .Values.kubelet.serviceMonitor.interval }}\n    interval: {{ .Values.kubelet.serviceMonitor.interval }}\n    {{- end }}\n    {{- if .Values.kubelet.serviceMonitor.proxyUrl }}\n    proxyUrl: {{ .Values.kubelet.serviceMonitor.proxyUrl }}\n    {{- end }}\n    honorLabels: true\n{{- if .Values.kubelet.serviceMonitor.resourceMetricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.kubelet.serviceMonitor.resourceMetricRelabelings | indent 4) . }}\n{{- end }}\n{{- if .Values.kubelet.serviceMonitor.resourceRelabelings }}\n    relabelings:\n{{ toYaml .Values.kubelet.serviceMonitor.resourceRelabelings | indent 4 }}\n{{- end }}\n{{- end }}\n{{- end }}\n  {{- end }}\n  jobLabel: k8s-app\n  namespaceSelector:\n    matchNames:\n    - {{ .Values.kubelet.namespace }}\n  selector:\n    matchLabels:\n      app.kubernetes.io/name: kubelet\n      k8s-app: kubelet\n{{- end}}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/exporters/node-exporter/servicemonitor.yaml",
    "content": "{{- if .Values.nodeExporter.enabled }}\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-node-exporter\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-node-exporter\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  jobLabel: {{ .Values.nodeExporter.jobLabel }}\n  selector:\n    matchLabels:\n      app: prometheus-node-exporter\n      release: {{ $.Release.Name }}\n  {{- if (index .Values \"prometheus-node-exporter\" \"namespaceOverride\") }}\n  namespaceSelector:\n    matchNames:\n      - {{ index .Values \"prometheus-node-exporter\" \"namespaceOverride\" }}\n  {{- end }}\n  endpoints:\n  - port: metrics\n    {{- if .Values.nodeExporter.serviceMonitor.interval }}\n    interval: {{ .Values.nodeExporter.serviceMonitor.interval }}\n    {{- end }}\n    {{- if .Values.nodeExporter.serviceMonitor.proxyUrl }}\n    proxyUrl: {{ .Values.nodeExporter.serviceMonitor.proxyUrl}}\n    {{- end }}\n    {{- if .Values.nodeExporter.serviceMonitor.scrapeTimeout }}\n    scrapeTimeout: {{ .Values.nodeExporter.serviceMonitor.scrapeTimeout }}\n    {{- end }}\n{{- if .Values.nodeExporter.serviceMonitor.metricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.nodeExporter.serviceMonitor.metricRelabelings | indent 4) . }}\n{{- end }}\n{{- if .Values.nodeExporter.serviceMonitor.relabelings }}\n    relabelings:\n{{ toYaml .Values.nodeExporter.serviceMonitor.relabelings | indent 4 }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/configmap-dashboards.yaml",
    "content": "{{- if or (and .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled) .Values.grafana.forceDeployDashboards }}\n{{- $files := .Files.Glob \"dashboards-1.14/*.json\" }}\n{{- if $files }}\napiVersion: v1\nkind: ConfigMapList\nitems:\n{{- range $path, $fileContents := $files }}\n{{- $dashboardName := regexReplaceAll \"(^.*/)(.*)\\\\.json$\" $path \"${2}\" }}\n- apiVersion: v1\n  kind: ConfigMap\n  metadata:\n    name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) $dashboardName | trunc 63 | trimSuffix \"-\" }}\n    namespace: {{ template \"kube-prometheus-stack.namespace\" $ }}\n    labels:\n      {{- if $.Values.grafana.sidecar.dashboards.label }}\n      {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n      {{- end }}\n      app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 6 }}\n  data:\n    {{ $dashboardName }}.json: {{ $.Files.Get $path | toJson }}\n{{- end }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/configmaps-datasources.yaml",
    "content": "{{- if or (and .Values.grafana.enabled .Values.grafana.sidecar.datasources.enabled) .Values.grafana.forceDeployDatasources }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-grafana-datasource\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n{{- if .Values.grafana.sidecar.datasources.annotations }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.datasources.annotations | indent 4 }}\n{{- end }}\n  labels:\n    {{ $.Values.grafana.sidecar.datasources.label }}: \"1\"\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  datasource.yaml: |-\n    apiVersion: 1\n    datasources:\n{{- $scrapeInterval := .Values.grafana.sidecar.datasources.defaultDatasourceScrapeInterval | default .Values.prometheus.prometheusSpec.scrapeInterval | default \"30s\" }}\n{{- if .Values.grafana.sidecar.datasources.defaultDatasourceEnabled }}\n    - name: Prometheus\n      type: prometheus\n      {{- if .Values.grafana.sidecar.datasources.url }}\n      url: {{ .Values.grafana.sidecar.datasources.url }}\n      {{- else }}\n      url: http://{{ template \"kube-prometheus-stack.fullname\" . }}-prometheus:{{ .Values.prometheus.service.port }}/{{ trimPrefix \"/\" .Values.prometheus.prometheusSpec.routePrefix }}\n      {{- end }}\n      access: proxy\n      isDefault: true\n      jsonData:\n        timeInterval: {{ $scrapeInterval }}\n{{- if .Values.grafana.sidecar.datasources.createPrometheusReplicasDatasources }}\n{{- range until (int .Values.prometheus.prometheusSpec.replicas) }}\n    - name: Prometheus-{{ . }}\n      type: prometheus\n      url: http://prometheus-{{ template \"kube-prometheus-stack.fullname\" $ }}-prometheus-{{ . }}.prometheus-operated:9090/{{ trimPrefix \"/\" $.Values.prometheus.prometheusSpec.routePrefix }}\n      access: proxy\n      isDefault: false\n      jsonData:\n        timeInterval: {{ $scrapeInterval }}\n{{- end }}\n{{- end }}\n{{- end }}\n{{- if .Values.grafana.additionalDataSources }}\n{{ tpl (toYaml .Values.grafana.additionalDataSources | indent 4) . }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/alertmanager-overview.yaml",
    "content": "{{- /*\nGenerated from 'alertmanager-overview' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"alertmanager-overview\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  alertmanager-overview.json: |-\n    {\n        \"__inputs\": [\n\n        ],\n        \"__requires\": [\n\n        ],\n        \"annotations\": {\n            \"list\": [\n\n            ]\n        },\n        \"editable\": false,\n        \"gnetId\": null,\n        \"graphTooltip\": 1,\n        \"hideControls\": false,\n        \"id\": null,\n        \"links\": [\n\n        ],\n        \"refresh\": \"30s\",\n        \"rows\": [\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 2,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": false,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(alertmanager_alerts{namespace=\\\"$namespace\\\",service=\\\"$service\\\"}) by (namespace,service,instance)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Alerts\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"none\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"none\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 3,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": false,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(rate(alertmanager_alerts_received_total{namespace=\\\"$namespace\\\",service=\\\"$service\\\"}[5m])) by (namespace,service,instance)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} Received\",\n                                \"refId\": \"A\"\n                            },\n                            {\n                                \"expr\": \"sum(rate(alertmanager_alerts_invalid_total{namespace=\\\"$namespace\\\",service=\\\"$service\\\"}[5m])) by (namespace,service,instance)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} Invalid\",\n                                \"refId\": \"B\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Alerts receive rate\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Alerts\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 4,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": false,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": \"integration\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(rate(alertmanager_notifications_total{namespace=\\\"$namespace\\\",service=\\\"$service\\\", integration=\\\"$integration\\\"}[5m])) by (integration,namespace,service,instance)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} Total\",\n                                \"refId\": \"A\"\n                            },\n                            {\n                                \"expr\": \"sum(rate(alertmanager_notifications_failed_total{namespace=\\\"$namespace\\\",service=\\\"$service\\\", integration=\\\"$integration\\\"}[5m])) by (integration,namespace,service,instance)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} Failed\",\n                                \"refId\": \"B\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"$integration: Notifications Send Rate\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 5,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": false,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": \"integration\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"histogram_quantile(0.99,\\n  sum(rate(alertmanager_notification_latency_seconds_bucket{namespace=\\\"$namespace\\\",service=\\\"$service\\\", integration=\\\"$integration\\\"}[5m])) by (le,namespace,service,instance)\\n) \\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} 99th Percentile\",\n                                \"refId\": \"A\"\n                            },\n                            {\n                                \"expr\": \"histogram_quantile(0.50,\\n  sum(rate(alertmanager_notification_latency_seconds_bucket{namespace=\\\"$namespace\\\",service=\\\"$service\\\", integration=\\\"$integration\\\"}[5m])) by (le,namespace,service,instance)\\n) \\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} Median\",\n                                \"refId\": \"B\"\n                            },\n                            {\n                                \"expr\": \"sum(rate(alertmanager_notification_latency_seconds_sum{namespace=\\\"$namespace\\\",service=\\\"$service\\\", integration=\\\"$integration\\\"}[5m])) by (namespace,service,instance)\\n/\\nsum(rate(alertmanager_notification_latency_seconds_count{namespace=\\\"$namespace\\\",service=\\\"$service\\\", integration=\\\"$integration\\\"}[5m])) by (namespace,service,instance)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} Average\",\n                                \"refId\": \"C\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"$integration: Notification Duration\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Notifications\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            }\n        ],\n        \"schemaVersion\": 14,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"alertmanager-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"Prometheus\",\n                        \"value\": \"Prometheus\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": \"\",\n                        \"value\": \"\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"namespace\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(alertmanager_alerts, namespace)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": \"\",\n                        \"value\": \"\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"service\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(alertmanager_alerts, service)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": \"all\",\n                        \"value\": \"$__all\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 2,\n                    \"includeAll\": true,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"integration\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(alertmanager_notifications_total{integration=~\\\".*\\\"}, integration)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"utc\",\n        \"title\": \"Alertmanager / Overview\",\n        \"uid\": \"alertmanager-overview\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/apiserver.yaml",
    "content": "{{- /*\nGenerated from 'apiserver' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled .Values.kubeApiServer.enabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"apiserver\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  apiserver.json: |-\n    {\n        \"__inputs\": [\n\n        ],\n        \"__requires\": [\n\n        ],\n        \"annotations\": {\n            \"list\": [\n\n            ]\n        },\n        \"editable\": false,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"id\": null,\n        \"links\": [\n\n        ],\n        \"panels\": [\n            {\n                \"content\": \"The SLO (service level objective) and other metrics displayed on this dashboard are for informational purposes only.\",\n                \"datasource\": null,\n                \"description\": \"The SLO (service level objective) and other metrics displayed on this dashboard are for informational purposes only.\",\n                \"gridPos\": {\n                    \"h\": 2,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 0\n                },\n                \"id\": 2,\n                \"mode\": \"markdown\",\n                \"span\": 12,\n                \"title\": \"Notice\",\n                \"type\": \"text\"\n            }\n        ],\n        \"refresh\": \"10s\",\n        \"rows\": [\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"cacheTimeout\": null,\n                        \"colorBackground\": false,\n                        \"colorValue\": false,\n                        \"colors\": [\n                            \"#299c46\",\n                            \"rgba(237, 129, 40, 0.89)\",\n                            \"#d44a3a\"\n                        ],\n                        \"datasource\": \"$datasource\",\n                        \"decimals\": 3,\n                        \"description\": \"How many percent of requests (both read and write) in 30 days have been answered successfully and fast enough?\",\n                        \"format\": \"percentunit\",\n                        \"gauge\": {\n                            \"maxValue\": 100,\n                            \"minValue\": 0,\n                            \"show\": false,\n                            \"thresholdLabels\": false,\n                            \"thresholdMarkers\": true\n                        },\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 3,\n                        \"interval\": null,\n                        \"links\": [\n\n                        ],\n                        \"mappingType\": 1,\n                        \"mappingTypes\": [\n                            {\n                                \"name\": \"value to text\",\n                                \"value\": 1\n                            },\n                            {\n                                \"name\": \"range to text\",\n                                \"value\": 2\n                            }\n                        ],\n                        \"maxDataPoints\": 100,\n                        \"nullPointMode\": \"connected\",\n                        \"nullText\": null,\n                        \"postfix\": \"\",\n                        \"postfixFontSize\": \"50%\",\n                        \"prefix\": \"\",\n                        \"prefixFontSize\": \"50%\",\n                        \"rangeMaps\": [\n                            {\n                                \"from\": \"null\",\n                                \"text\": \"N/A\",\n                                \"to\": \"null\"\n                            }\n                        ],\n                        \"span\": 4,\n                        \"sparkline\": {\n                            \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                            \"full\": false,\n                            \"lineColor\": \"rgb(31, 120, 193)\",\n                            \"show\": false\n                        },\n                        \"tableColumn\": \"\",\n                        \"targets\": [\n                            {\n                                \"expr\": \"apiserver_request:availability30d{verb=\\\"all\\\", cluster=\\\"$cluster\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"\",\n                        \"title\": \"Availability (30d) > 99.000%\",\n                        \"tooltip\": {\n                            \"shared\": false\n                        },\n                        \"type\": \"singlestat\",\n                        \"valueFontSize\": \"80%\",\n                        \"valueMaps\": [\n                            {\n                                \"op\": \"=\",\n                                \"text\": \"N/A\",\n                                \"value\": \"null\"\n                            }\n                        ],\n                        \"valueName\": \"avg\"\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"decimals\": 3,\n                        \"description\": \"How much error budget is left looking at our 0.990% availability guarantees?\",\n                        \"fill\": 10,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 4,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 8,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"100 * (apiserver_request:availability30d{verb=\\\"all\\\", cluster=\\\"$cluster\\\"} - 0.990000)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"errorbudget\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"ErrorBudget (30d) > 99.000%\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"decimals\": 3,\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"decimals\": 3,\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"cacheTimeout\": null,\n                        \"colorBackground\": false,\n                        \"colorValue\": false,\n                        \"colors\": [\n                            \"#299c46\",\n                            \"rgba(237, 129, 40, 0.89)\",\n                            \"#d44a3a\"\n                        ],\n                        \"datasource\": \"$datasource\",\n                        \"decimals\": 3,\n                        \"description\": \"How many percent of read requests (LIST,GET) in 30 days have been answered successfully and fast enough?\",\n                        \"format\": \"percentunit\",\n                        \"gauge\": {\n                            \"maxValue\": 100,\n                            \"minValue\": 0,\n                            \"show\": false,\n                            \"thresholdLabels\": false,\n                            \"thresholdMarkers\": true\n                        },\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 5,\n                        \"interval\": null,\n                        \"links\": [\n\n                        ],\n                        \"mappingType\": 1,\n                        \"mappingTypes\": [\n                            {\n                                \"name\": \"value to text\",\n                                \"value\": 1\n                            },\n                            {\n                                \"name\": \"range to text\",\n                                \"value\": 2\n                            }\n                        ],\n                        \"maxDataPoints\": 100,\n                        \"nullPointMode\": \"connected\",\n                        \"nullText\": null,\n                        \"postfix\": \"\",\n                        \"postfixFontSize\": \"50%\",\n                        \"prefix\": \"\",\n                        \"prefixFontSize\": \"50%\",\n                        \"rangeMaps\": [\n                            {\n                                \"from\": \"null\",\n                                \"text\": \"N/A\",\n                                \"to\": \"null\"\n                            }\n                        ],\n                        \"span\": 3,\n                        \"sparkline\": {\n                            \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                            \"full\": false,\n                            \"lineColor\": \"rgb(31, 120, 193)\",\n                            \"show\": false\n                        },\n                        \"tableColumn\": \"\",\n                        \"targets\": [\n                            {\n                                \"expr\": \"apiserver_request:availability30d{verb=\\\"read\\\", cluster=\\\"$cluster\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"\",\n                        \"title\": \"Read Availability (30d)\",\n                        \"tooltip\": {\n                            \"shared\": false\n                        },\n                        \"type\": \"singlestat\",\n                        \"valueFontSize\": \"80%\",\n                        \"valueMaps\": [\n                            {\n                                \"op\": \"=\",\n                                \"text\": \"N/A\",\n                                \"value\": \"null\"\n                            }\n                        ],\n                        \"valueName\": \"avg\"\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"description\": \"How many read requests (LIST,GET) per second do the apiservers get by code?\",\n                        \"fill\": 10,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 6,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n                            {\n                                \"alias\": \"/2../i\",\n                                \"color\": \"#56A64B\"\n                            },\n                            {\n                                \"alias\": \"/3../i\",\n                                \"color\": \"#F2CC0C\"\n                            },\n                            {\n                                \"alias\": \"/4../i\",\n                                \"color\": \"#3274D9\"\n                            },\n                            {\n                                \"alias\": \"/5../i\",\n                                \"color\": \"#E02F44\"\n                            }\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 3,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum by (code) (code_resource:apiserver_request_total:rate5m{verb=\\\"read\\\", cluster=\\\"$cluster\\\"})\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}} code {{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Read SLI - Requests\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"reqps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"reqps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"description\": \"How many percent of read requests (LIST,GET) per second are returned with errors (5xx)?\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 7,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 3,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum by (resource) (code_resource:apiserver_request_total:rate5m{verb=\\\"read\\\",code=~\\\"5..\\\", cluster=\\\"$cluster\\\"}) / sum by (resource) (code_resource:apiserver_request_total:rate5m{verb=\\\"read\\\", cluster=\\\"$cluster\\\"})\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}} resource {{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Read SLI - Errors\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"description\": \"How many seconds is the 99th percentile for reading (LIST|GET) a given resource?\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 8,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 3,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"cluster_quantile:apiserver_request_duration_seconds:histogram_quantile{verb=\\\"read\\\", cluster=\\\"$cluster\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}} resource {{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Read SLI - Duration\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"cacheTimeout\": null,\n                        \"colorBackground\": false,\n                        \"colorValue\": false,\n                        \"colors\": [\n                            \"#299c46\",\n                            \"rgba(237, 129, 40, 0.89)\",\n                            \"#d44a3a\"\n                        ],\n                        \"datasource\": \"$datasource\",\n                        \"decimals\": 3,\n                        \"description\": \"How many percent of write requests (POST|PUT|PATCH|DELETE) in 30 days have been answered successfully and fast enough?\",\n                        \"format\": \"percentunit\",\n                        \"gauge\": {\n                            \"maxValue\": 100,\n                            \"minValue\": 0,\n                            \"show\": false,\n                            \"thresholdLabels\": false,\n                            \"thresholdMarkers\": true\n                        },\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 9,\n                        \"interval\": null,\n                        \"links\": [\n\n                        ],\n                        \"mappingType\": 1,\n                        \"mappingTypes\": [\n                            {\n                                \"name\": \"value to text\",\n                                \"value\": 1\n                            },\n                            {\n                                \"name\": \"range to text\",\n                                \"value\": 2\n                            }\n                        ],\n                        \"maxDataPoints\": 100,\n                        \"nullPointMode\": \"connected\",\n                        \"nullText\": null,\n                        \"postfix\": \"\",\n                        \"postfixFontSize\": \"50%\",\n                        \"prefix\": \"\",\n                        \"prefixFontSize\": \"50%\",\n                        \"rangeMaps\": [\n                            {\n                                \"from\": \"null\",\n                                \"text\": \"N/A\",\n                                \"to\": \"null\"\n                            }\n                        ],\n                        \"span\": 3,\n                        \"sparkline\": {\n                            \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                            \"full\": false,\n                            \"lineColor\": \"rgb(31, 120, 193)\",\n                            \"show\": false\n                        },\n                        \"tableColumn\": \"\",\n                        \"targets\": [\n                            {\n                                \"expr\": \"apiserver_request:availability30d{verb=\\\"write\\\", cluster=\\\"$cluster\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"\",\n                        \"title\": \"Write Availability (30d)\",\n                        \"tooltip\": {\n                            \"shared\": false\n                        },\n                        \"type\": \"singlestat\",\n                        \"valueFontSize\": \"80%\",\n                        \"valueMaps\": [\n                            {\n                                \"op\": \"=\",\n                                \"text\": \"N/A\",\n                                \"value\": \"null\"\n                            }\n                        ],\n                        \"valueName\": \"avg\"\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"description\": \"How many write requests (POST|PUT|PATCH|DELETE) per second do the apiservers get by code?\",\n                        \"fill\": 10,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 10,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n                            {\n                                \"alias\": \"/2../i\",\n                                \"color\": \"#56A64B\"\n                            },\n                            {\n                                \"alias\": \"/3../i\",\n                                \"color\": \"#F2CC0C\"\n                            },\n                            {\n                                \"alias\": \"/4../i\",\n                                \"color\": \"#3274D9\"\n                            },\n                            {\n                                \"alias\": \"/5../i\",\n                                \"color\": \"#E02F44\"\n                            }\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 3,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum by (code) (code_resource:apiserver_request_total:rate5m{verb=\\\"write\\\", cluster=\\\"$cluster\\\"})\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}} code {{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Write SLI - Requests\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"reqps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"reqps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"description\": \"How many percent of write requests (POST|PUT|PATCH|DELETE) per second are returned with errors (5xx)?\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 11,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 3,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum by (resource) (code_resource:apiserver_request_total:rate5m{verb=\\\"write\\\",code=~\\\"5..\\\", cluster=\\\"$cluster\\\"}) / sum by (resource) (code_resource:apiserver_request_total:rate5m{verb=\\\"write\\\", cluster=\\\"$cluster\\\"})\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}} resource {{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Write SLI - Errors\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"description\": \"How many seconds is the 99th percentile for writing (POST|PUT|PATCH|DELETE) a given resource?\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 12,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 3,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"cluster_quantile:apiserver_request_duration_seconds:histogram_quantile{verb=\\\"write\\\", cluster=\\\"$cluster\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}} resource {{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Write SLI - Duration\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 13,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": false,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(rate(workqueue_adds_total{job=\\\"apiserver\\\", instance=~\\\"$instance\\\", cluster=\\\"$cluster\\\"}[5m])) by (instance, name)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} {{`{{`}}name{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Work Queue Add Rate\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 14,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": false,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(rate(workqueue_depth{job=\\\"apiserver\\\", instance=~\\\"$instance\\\", cluster=\\\"$cluster\\\"}[5m])) by (instance, name)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} {{`{{`}}name{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Work Queue Depth\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 15,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": false,\n                            \"current\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"histogram_quantile(0.99, sum(rate(workqueue_queue_duration_seconds_bucket{job=\\\"apiserver\\\", instance=~\\\"$instance\\\", cluster=\\\"$cluster\\\"}[5m])) by (instance, name, le))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} {{`{{`}}name{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Work Queue Latency\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 16,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"process_resident_memory_bytes{job=\\\"apiserver\\\",instance=~\\\"$instance\\\", cluster=\\\"$cluster\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 17,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"rate(process_cpu_seconds_total{job=\\\"apiserver\\\",instance=~\\\"$instance\\\", cluster=\\\"$cluster\\\"}[5m])\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU usage\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 18,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"go_goroutines{job=\\\"apiserver\\\",instance=~\\\"$instance\\\", cluster=\\\"$cluster\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Goroutines\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            }\n        ],\n        \"schemaVersion\": 14,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"kubernetes-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }},\n                    \"includeAll\": false,\n                    \"label\": \"cluster\",\n                    \"multi\": false,\n                    \"name\": \"cluster\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(apiserver_request_total, cluster)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": true,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"instance\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(apiserver_request_total{job=\\\"apiserver\\\", cluster=\\\"$cluster\\\"}, instance)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"UTC\",\n        \"title\": \"Kubernetes / API server\",\n        \"uid\": \"09ec8aa1e996d6ffcd6817bbaff4db1b\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/cluster-total.yaml",
    "content": "{{- /*\nGenerated from 'cluster-total' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"cluster-total\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  cluster-total.json: |-\n    {\n        \"__inputs\": [\n\n        ],\n        \"__requires\": [\n\n        ],\n        \"annotations\": {\n            \"list\": [\n                {\n                    \"builtIn\": 1,\n                    \"datasource\": \"-- Grafana --\",\n                    \"enable\": true,\n                    \"hide\": true,\n                    \"iconColor\": \"rgba(0, 211, 255, 1)\",\n                    \"name\": \"Annotations & Alerts\",\n                    \"type\": \"dashboard\"\n                }\n            ]\n        },\n        \"editable\": true,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"id\": null,\n        \"links\": [\n\n        ],\n        \"panels\": [\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 0\n                },\n                \"id\": 2,\n                \"panels\": [\n\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Current Bandwidth\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": true,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 2,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 12,\n                    \"x\": 0,\n                    \"y\": 1\n                },\n                \"id\": 3,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": false,\n                    \"current\": true,\n                    \"hideEmpty\": true,\n                    \"hideZero\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"sort\": \"current\",\n                    \"sortDesc\": true,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": false,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"minSpan\": 24,\n                \"nullPointMode\": \"null\",\n                \"paceLength\": 10,\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"span\": 24,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\".+\\\"}[$interval:$resolution])) by (namespace))\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 1,\n                        \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                        \"refId\": \"A\",\n                        \"step\": 10\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Current Rate of Bytes Received\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 2,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"series\",\n                    \"name\": null,\n                    \"show\": false,\n                    \"values\": [\n                        \"current\"\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": true,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 2,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 12,\n                    \"x\": 12,\n                    \"y\": 1\n                },\n                \"id\": 4,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": false,\n                    \"current\": true,\n                    \"hideEmpty\": true,\n                    \"hideZero\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"sort\": \"current\",\n                    \"sortDesc\": true,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": false,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"minSpan\": 24,\n                \"nullPointMode\": \"null\",\n                \"paceLength\": 10,\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"span\": 24,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\".+\\\"}[$interval:$resolution])) by (namespace))\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 1,\n                        \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                        \"refId\": \"A\",\n                        \"step\": 10\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Current Rate of Bytes Transmitted\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 2,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"series\",\n                    \"name\": null,\n                    \"show\": false,\n                    \"values\": [\n                        \"current\"\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"columns\": [\n                    {\n                        \"text\": \"Time\",\n                        \"value\": \"Time\"\n                    },\n                    {\n                        \"text\": \"Value #A\",\n                        \"value\": \"Value #A\"\n                    },\n                    {\n                        \"text\": \"Value #B\",\n                        \"value\": \"Value #B\"\n                    },\n                    {\n                        \"text\": \"Value #C\",\n                        \"value\": \"Value #C\"\n                    },\n                    {\n                        \"text\": \"Value #D\",\n                        \"value\": \"Value #D\"\n                    },\n                    {\n                        \"text\": \"Value #E\",\n                        \"value\": \"Value #E\"\n                    },\n                    {\n                        \"text\": \"Value #F\",\n                        \"value\": \"Value #F\"\n                    },\n                    {\n                        \"text\": \"Value #G\",\n                        \"value\": \"Value #G\"\n                    },\n                    {\n                        \"text\": \"Value #H\",\n                        \"value\": \"Value #H\"\n                    },\n                    {\n                        \"text\": \"namespace\",\n                        \"value\": \"namespace\"\n                    }\n                ],\n                \"datasource\": \"$datasource\",\n                \"fill\": 1,\n                \"fontSize\": \"90%\",\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 10\n                },\n                \"id\": 5,\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"minSpan\": 24,\n                \"nullPointMode\": \"null as zero\",\n                \"renderer\": \"flot\",\n                \"scroll\": true,\n                \"showHeader\": true,\n                \"sort\": {\n                    \"col\": 0,\n                    \"desc\": false\n                },\n                \"spaceLength\": 10,\n                \"span\": 24,\n                \"styles\": [\n                    {\n                        \"alias\": \"Time\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Time\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"hidden\",\n                        \"unit\": \"short\"\n                    },\n                    {\n                        \"alias\": \"Current Bandwidth Received\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #A\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"Bps\"\n                    },\n                    {\n                        \"alias\": \"Current Bandwidth Transmitted\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #B\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"Bps\"\n                    },\n                    {\n                        \"alias\": \"Average Bandwidth Received\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #C\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"Bps\"\n                    },\n                    {\n                        \"alias\": \"Average Bandwidth Transmitted\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #D\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"Bps\"\n                    },\n                    {\n                        \"alias\": \"Rate of Received Packets\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #E\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"pps\"\n                    },\n                    {\n                        \"alias\": \"Rate of Transmitted Packets\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #F\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"pps\"\n                    },\n                    {\n                        \"alias\": \"Rate of Received Packets Dropped\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #G\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"pps\"\n                    },\n                    {\n                        \"alias\": \"Rate of Transmitted Packets Dropped\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #H\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"pps\"\n                    },\n                    {\n                        \"alias\": \"Namespace\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": true,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"d/8b7a8b326d7a6f1f04244066368c67af/kubernetes-networking-namespace-pods?orgId=1&refresh=30s&var-namespace=$__cell\",\n                        \"pattern\": \"namespace\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"short\"\n                    }\n                ],\n                \"targets\": [\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\".+\\\"}[$interval:$resolution])) by (namespace))\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"A\",\n                        \"step\": 10\n                    },\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\".+\\\"}[$interval:$resolution])) by (namespace))\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"B\",\n                        \"step\": 10\n                    },\n                    {\n                        \"expr\": \"sort_desc(avg(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\".+\\\"}[$interval:$resolution])) by (namespace))\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"C\",\n                        \"step\": 10\n                    },\n                    {\n                        \"expr\": \"sort_desc(avg(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\".+\\\"}[$interval:$resolution])) by (namespace))\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"D\",\n                        \"step\": 10\n                    },\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_receive_packets_total{cluster=\\\"$cluster\\\",namespace=~\\\".+\\\"}[$interval:$resolution])) by (namespace))\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"E\",\n                        \"step\": 10\n                    },\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_transmit_packets_total{cluster=\\\"$cluster\\\",namespace=~\\\".+\\\"}[$interval:$resolution])) by (namespace))\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"F\",\n                        \"step\": 10\n                    },\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_receive_packets_dropped_total{cluster=\\\"$cluster\\\",namespace=~\\\".+\\\"}[$interval:$resolution])) by (namespace))\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"G\",\n                        \"step\": 10\n                    },\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_transmit_packets_dropped_total{cluster=\\\"$cluster\\\",namespace=~\\\".+\\\"}[$interval:$resolution])) by (namespace))\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"H\",\n                        \"step\": 10\n                    }\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Current Status\",\n                \"type\": \"table\"\n            },\n            {\n                \"collapse\": true,\n                \"collapsed\": true,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 10\n                },\n                \"id\": 6,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": true,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 9,\n                            \"w\": 12,\n                            \"x\": 0,\n                            \"y\": 11\n                        },\n                        \"id\": 7,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": false,\n                            \"current\": true,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"sort\": \"current\",\n                            \"sortDesc\": true,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": false,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 24,\n                        \"nullPointMode\": \"null\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 24,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sort_desc(avg(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\".+\\\"}[$interval:$resolution])) by (namespace))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Average Rate of Bytes Received\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"series\",\n                            \"name\": null,\n                            \"show\": false,\n                            \"values\": [\n                                \"current\"\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": true,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 9,\n                            \"w\": 12,\n                            \"x\": 12,\n                            \"y\": 11\n                        },\n                        \"id\": 8,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": false,\n                            \"current\": true,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"sort\": \"current\",\n                            \"sortDesc\": true,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": false,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 24,\n                        \"nullPointMode\": \"null\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 24,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sort_desc(avg(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\".+\\\"}[$interval:$resolution])) by (namespace))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Average Rate of Bytes Transmitted\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"series\",\n                            \"name\": null,\n                            \"show\": false,\n                            \"values\": [\n                                \"current\"\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Average Bandwidth\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 11\n                },\n                \"id\": 9,\n                \"panels\": [\n\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Bandwidth History\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 2,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 12\n                },\n                \"id\": 10,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": true,\n                    \"current\": true,\n                    \"hideEmpty\": true,\n                    \"hideZero\": true,\n                    \"max\": true,\n                    \"min\": true,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": true,\n                \"linewidth\": 2,\n                \"links\": [\n\n                ],\n                \"minSpan\": 24,\n                \"nullPointMode\": \"connected\",\n                \"paceLength\": 10,\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"span\": 24,\n                \"stack\": true,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\".+\\\"}[$interval:$resolution])) by (namespace))\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 1,\n                        \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                        \"refId\": \"A\",\n                        \"step\": 10\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Receive Bandwidth\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 2,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 2,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 21\n                },\n                \"id\": 11,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": true,\n                    \"current\": true,\n                    \"hideEmpty\": true,\n                    \"hideZero\": true,\n                    \"max\": true,\n                    \"min\": true,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": true,\n                \"linewidth\": 2,\n                \"links\": [\n\n                ],\n                \"minSpan\": 24,\n                \"nullPointMode\": \"connected\",\n                \"paceLength\": 10,\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"span\": 24,\n                \"stack\": true,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\".+\\\"}[$interval:$resolution])) by (namespace))\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 1,\n                        \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                        \"refId\": \"A\",\n                        \"step\": 10\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Transmit Bandwidth\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 2,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"collapse\": true,\n                \"collapsed\": true,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 30\n                },\n                \"id\": 12,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 9,\n                            \"w\": 24,\n                            \"x\": 0,\n                            \"y\": 31\n                        },\n                        \"id\": 13,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": true,\n                            \"current\": true,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": true,\n                            \"min\": true,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 24,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 24,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sort_desc(sum(irate(container_network_receive_packets_total{cluster=\\\"$cluster\\\",namespace=~\\\".+\\\"}[$interval:$resolution])) by (namespace))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Received Packets\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 9,\n                            \"w\": 24,\n                            \"x\": 0,\n                            \"y\": 40\n                        },\n                        \"id\": 14,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": true,\n                            \"current\": true,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": true,\n                            \"min\": true,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 24,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 24,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sort_desc(sum(irate(container_network_transmit_packets_total{cluster=\\\"$cluster\\\",namespace=~\\\".+\\\"}[$interval:$resolution])) by (namespace))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Transmitted Packets\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Packets\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": true,\n                \"collapsed\": true,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 31\n                },\n                \"id\": 15,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 9,\n                            \"w\": 24,\n                            \"x\": 0,\n                            \"y\": 50\n                        },\n                        \"id\": 16,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": true,\n                            \"current\": true,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": true,\n                            \"min\": true,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 24,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 24,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sort_desc(sum(irate(container_network_receive_packets_dropped_total{cluster=\\\"$cluster\\\",namespace=~\\\".+\\\"}[$interval:$resolution])) by (namespace))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Received Packets Dropped\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 9,\n                            \"w\": 24,\n                            \"x\": 0,\n                            \"y\": 59\n                        },\n                        \"id\": 17,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": true,\n                            \"current\": true,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": true,\n                            \"min\": true,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 24,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 24,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sort_desc(sum(irate(container_network_transmit_packets_dropped_total{cluster=\\\"$cluster\\\",namespace=~\\\".+\\\"}[$interval:$resolution])) by (namespace))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Transmitted Packets Dropped\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 9,\n                            \"w\": 24,\n                            \"x\": 0,\n                            \"y\": 59\n                        },\n                        \"id\": 18,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": true,\n                            \"current\": true,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": true,\n                            \"min\": true,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n                            {\n                                \"targetBlank\": true,\n                                \"title\": \"What is TCP Retransmit?\",\n                                \"url\": \"https://accedian.com/enterprises/blog/network-packet-loss-retransmissions-and-duplicate-acknowledgements/\"\n                            }\n                        ],\n                        \"minSpan\": 24,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 24,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sort_desc(sum(rate(node_netstat_Tcp_RetransSegs{cluster=\\\"$cluster\\\"}[$interval:$resolution]) / rate(node_netstat_Tcp_OutSegs{cluster=\\\"$cluster\\\"}[$interval:$resolution])) by (instance))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of TCP Retransmits out of all sent segments\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 9,\n                            \"w\": 24,\n                            \"x\": 0,\n                            \"y\": 59\n                        },\n                        \"id\": 19,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": true,\n                            \"current\": true,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": true,\n                            \"min\": true,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n                            {\n                                \"targetBlank\": true,\n                                \"title\": \"Why monitor SYN retransmits?\",\n                                \"url\": \"https://github.com/prometheus/node_exporter/issues/1023#issuecomment-408128365\"\n                            }\n                        ],\n                        \"minSpan\": 24,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 24,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sort_desc(sum(rate(node_netstat_TcpExt_TCPSynRetrans{cluster=\\\"$cluster\\\"}[$interval:$resolution]) / rate(node_netstat_Tcp_RetransSegs{cluster=\\\"$cluster\\\"}[$interval:$resolution])) by (instance))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of TCP SYN Retransmits out of all retransmits\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Errors\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            }\n        ],\n        \"refresh\": \"10s\",\n        \"rows\": [\n\n        ],\n        \"schemaVersion\": 18,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"kubernetes-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"allValue\": null,\n                    \"auto\": false,\n                    \"auto_count\": 30,\n                    \"auto_min\": \"10s\",\n                    \"current\": {\n                        \"text\": \"5m\",\n                        \"value\": \"5m\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"resolution\",\n                    \"options\": [\n                        {\n                            \"selected\": false,\n                            \"text\": \"30s\",\n                            \"value\": \"30s\"\n                        },\n                        {\n                            \"selected\": true,\n                            \"text\": \"5m\",\n                            \"value\": \"5m\"\n                        },\n                        {\n                            \"selected\": false,\n                            \"text\": \"1h\",\n                            \"value\": \"1h\"\n                        }\n                    ],\n                    \"query\": \"30s,5m,1h\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"skipUrlSync\": false,\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"interval\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"auto\": false,\n                    \"auto_count\": 30,\n                    \"auto_min\": \"10s\",\n                    \"current\": {\n                        \"text\": \"5m\",\n                        \"value\": \"5m\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 2,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"interval\",\n                    \"options\": [\n                        {\n                            \"selected\": true,\n                            \"text\": \"4h\",\n                            \"value\": \"4h\"\n                        }\n                    ],\n                    \"query\": \"4h\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"skipUrlSync\": false,\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"interval\",\n                    \"useTags\": false\n                },\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }},\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"cluster\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_info, cluster)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 0,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"UTC\",\n        \"title\": \"Kubernetes / Networking / Cluster\",\n        \"uid\": \"ff635a025bcfea7bc3dd4f508990a3e9\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/controller-manager.yaml",
    "content": "{{- /*\nGenerated from 'controller-manager' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled .Values.kubeControllerManager.enabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"controller-manager\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  controller-manager.json: |-\n    {\n        \"__inputs\": [\n\n        ],\n        \"__requires\": [\n\n        ],\n        \"annotations\": {\n            \"list\": [\n\n            ]\n        },\n        \"editable\": false,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"id\": null,\n        \"links\": [\n\n        ],\n        \"refresh\": \"10s\",\n        \"rows\": [\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"cacheTimeout\": null,\n                        \"colorBackground\": false,\n                        \"colorValue\": false,\n                        \"colors\": [\n                            \"#299c46\",\n                            \"rgba(237, 129, 40, 0.89)\",\n                            \"#d44a3a\"\n                        ],\n                        \"datasource\": \"$datasource\",\n                        \"format\": \"none\",\n                        \"gauge\": {\n                            \"maxValue\": 100,\n                            \"minValue\": 0,\n                            \"show\": false,\n                            \"thresholdLabels\": false,\n                            \"thresholdMarkers\": true\n                        },\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 2,\n                        \"interval\": null,\n                        \"links\": [\n\n                        ],\n                        \"mappingType\": 1,\n                        \"mappingTypes\": [\n                            {\n                                \"name\": \"value to text\",\n                                \"value\": 1\n                            },\n                            {\n                                \"name\": \"range to text\",\n                                \"value\": 2\n                            }\n                        ],\n                        \"maxDataPoints\": 100,\n                        \"nullPointMode\": \"connected\",\n                        \"nullText\": null,\n                        \"postfix\": \"\",\n                        \"postfixFontSize\": \"50%\",\n                        \"prefix\": \"\",\n                        \"prefixFontSize\": \"50%\",\n                        \"rangeMaps\": [\n                            {\n                                \"from\": \"null\",\n                                \"text\": \"N/A\",\n                                \"to\": \"null\"\n                            }\n                        ],\n                        \"span\": 2,\n                        \"sparkline\": {\n                            \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                            \"full\": false,\n                            \"lineColor\": \"rgb(31, 120, 193)\",\n                            \"show\": false\n                        },\n                        \"tableColumn\": \"\",\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(up{cluster=\\\"$cluster\\\", job=\\\"kube-controller-manager\\\"})\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"\",\n                        \"title\": \"Up\",\n                        \"tooltip\": {\n                            \"shared\": false\n                        },\n                        \"type\": \"singlestat\",\n                        \"valueFontSize\": \"80%\",\n                        \"valueMaps\": [\n                            {\n                                \"op\": \"=\",\n                                \"text\": \"N/A\",\n                                \"value\": \"null\"\n                            }\n                        ],\n                        \"valueName\": \"min\"\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 3,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": false,\n                            \"current\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 10,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(rate(workqueue_adds_total{cluster=\\\"$cluster\\\", job=\\\"kube-controller-manager\\\", instance=~\\\"$instance\\\"}[5m])) by (cluster, instance, name)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}} {{`{{`}}instance{{`}}`}} {{`{{`}}name{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Work Queue Add Rate\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 4,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": false,\n                            \"current\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(rate(workqueue_depth{cluster=\\\"$cluster\\\", job=\\\"kube-controller-manager\\\", instance=~\\\"$instance\\\"}[5m])) by (cluster, instance, name)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}} {{`{{`}}instance{{`}}`}} {{`{{`}}name{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Work Queue Depth\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 5,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": false,\n                            \"current\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"histogram_quantile(0.99, sum(rate(workqueue_queue_duration_seconds_bucket{cluster=\\\"$cluster\\\", job=\\\"kube-controller-manager\\\", instance=~\\\"$instance\\\"}[5m])) by (cluster, instance, name, le))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}} {{`{{`}}instance{{`}}`}} {{`{{`}}name{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Work Queue Latency\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 6,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(rate(rest_client_requests_total{job=\\\"kube-controller-manager\\\", instance=~\\\"$instance\\\",code=~\\\"2..\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"2xx\",\n                                \"refId\": \"A\"\n                            },\n                            {\n                                \"expr\": \"sum(rate(rest_client_requests_total{job=\\\"kube-controller-manager\\\", instance=~\\\"$instance\\\",code=~\\\"3..\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"3xx\",\n                                \"refId\": \"B\"\n                            },\n                            {\n                                \"expr\": \"sum(rate(rest_client_requests_total{job=\\\"kube-controller-manager\\\", instance=~\\\"$instance\\\",code=~\\\"4..\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"4xx\",\n                                \"refId\": \"C\"\n                            },\n                            {\n                                \"expr\": \"sum(rate(rest_client_requests_total{job=\\\"kube-controller-manager\\\", instance=~\\\"$instance\\\",code=~\\\"5..\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"5xx\",\n                                \"refId\": \"D\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Kube API Request Rate\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 7,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 8,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{cluster=\\\"$cluster\\\", job=\\\"kube-controller-manager\\\", instance=~\\\"$instance\\\", verb=\\\"POST\\\"}[5m])) by (verb, url, le))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}verb{{`}}`}} {{`{{`}}url{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Post Request Latency 99th Quantile\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 8,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": false,\n                            \"current\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{cluster=\\\"$cluster\\\", job=\\\"kube-controller-manager\\\", instance=~\\\"$instance\\\", verb=\\\"GET\\\"}[5m])) by (verb, url, le))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}verb{{`}}`}} {{`{{`}}url{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Get Request Latency 99th Quantile\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 9,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"process_resident_memory_bytes{cluster=\\\"$cluster\\\", job=\\\"kube-controller-manager\\\",instance=~\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 10,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"rate(process_cpu_seconds_total{cluster=\\\"$cluster\\\", job=\\\"kube-controller-manager\\\",instance=~\\\"$instance\\\"}[5m])\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU usage\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 11,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"go_goroutines{cluster=\\\"$cluster\\\", job=\\\"kube-controller-manager\\\",instance=~\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Goroutines\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            }\n        ],\n        \"schemaVersion\": 14,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"kubernetes-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }},\n                    \"includeAll\": false,\n                    \"label\": \"cluster\",\n                    \"multi\": false,\n                    \"name\": \"cluster\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_info, cluster)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": true,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"instance\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(process_cpu_seconds_total{cluster=\\\"$cluster\\\", job=\\\"kube-controller-manager\\\"}, instance)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"UTC\",\n        \"title\": \"Kubernetes / Controller Manager\",\n        \"uid\": \"72e0e05bef5099e5f049b05fdc429ed4\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/etcd.yaml",
    "content": "{{- /*\nGenerated from 'etcd' from https://raw.githubusercontent.com/etcd-io/website/master/content/en/docs/v3.4/op-guide/grafana.json\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled .Values.kubeEtcd.enabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"etcd\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  etcd.json: |-\n    {\n        \"annotations\": {\n            \"list\": []\n        },\n        \"description\": \"etcd sample Grafana dashboard with Prometheus\",\n        \"editable\": true,\n        \"gnetId\": null,\n        \"hideControls\": false,\n        \"id\": 6,\n        \"links\": [],\n        \"refresh\": \"10s\",\n        \"rows\": [\n            {\n                \"collapse\": false,\n                \"editable\": true,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"cacheTimeout\": null,\n                        \"colorBackground\": false,\n                        \"colorValue\": false,\n                        \"colors\": [\n                            \"rgba(245, 54, 54, 0.9)\",\n                            \"rgba(237, 129, 40, 0.89)\",\n                            \"rgba(50, 172, 45, 0.97)\"\n                        ],\n                        \"datasource\": \"$datasource\",\n                        \"editable\": true,\n                        \"error\": false,\n                        \"format\": \"none\",\n                        \"gauge\": {\n                            \"maxValue\": 100,\n                            \"minValue\": 0,\n                            \"show\": false,\n                            \"thresholdLabels\": false,\n                            \"thresholdMarkers\": true\n                        },\n                        \"id\": 28,\n                        \"interval\": null,\n                        \"isNew\": true,\n                        \"links\": [],\n                        \"mappingType\": 1,\n                        \"mappingTypes\": [\n                            {\n                                \"name\": \"value to text\",\n                                \"value\": 1\n                            },\n                            {\n                                \"name\": \"range to text\",\n                                \"value\": 2\n                            }\n                        ],\n                        \"maxDataPoints\": 100,\n                        \"nullPointMode\": \"connected\",\n                        \"nullText\": null,\n                        \"postfix\": \"\",\n                        \"postfixFontSize\": \"50%\",\n                        \"prefix\": \"\",\n                        \"prefixFontSize\": \"50%\",\n                        \"rangeMaps\": [\n                            {\n                                \"from\": \"null\",\n                                \"text\": \"N/A\",\n                                \"to\": \"null\"\n                            }\n                        ],\n                        \"span\": 3,\n                        \"sparkline\": {\n                            \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                            \"full\": false,\n                            \"lineColor\": \"rgb(31, 120, 193)\",\n                            \"show\": false\n                        },\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(etcd_server_has_leader{job=\\\"$cluster\\\"})\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"metric\": \"etcd_server_has_leader\",\n                                \"refId\": \"A\",\n                                \"step\": 20\n                            }\n                        ],\n                        \"thresholds\": \"\",\n                        \"title\": \"Up\",\n                        \"type\": \"singlestat\",\n                        \"valueFontSize\": \"200%\",\n                        \"valueMaps\": [\n                            {\n                                \"op\": \"=\",\n                                \"text\": \"N/A\",\n                                \"value\": \"null\"\n                            }\n                        ],\n                        \"valueName\": \"avg\"\n                    },\n                    {\n                        \"aliasColors\": {},\n                        \"bars\": false,\n                        \"datasource\": \"$datasource\",\n                        \"editable\": true,\n                        \"error\": false,\n                        \"fill\": 0,\n                        \"id\": 23,\n                        \"isNew\": true,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": false,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [],\n                        \"nullPointMode\": \"connected\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [],\n                        \"span\": 5,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(rate(grpc_server_started_total{job=\\\"$cluster\\\",grpc_type=\\\"unary\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"RPC Rate\",\n                                \"metric\": \"grpc_server_started_total\",\n                                \"refId\": \"A\",\n                                \"step\": 2\n                            },\n                            {\n                                \"expr\": \"sum(rate(grpc_server_handled_total{job=\\\"$cluster\\\",grpc_type=\\\"unary\\\",grpc_code!=\\\"OK\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"RPC Failed Rate\",\n                                \"metric\": \"grpc_server_handled_total\",\n                                \"refId\": \"B\",\n                                \"step\": 2\n                            }\n                        ],\n                        \"thresholds\": [],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"RPC Rate\",\n                        \"tooltip\": {\n                            \"msResolution\": false,\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": []\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {},\n                        \"bars\": false,\n                        \"datasource\": \"$datasource\",\n                        \"editable\": true,\n                        \"error\": false,\n                        \"fill\": 0,\n                        \"id\": 41,\n                        \"isNew\": true,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": false,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [],\n                        \"nullPointMode\": \"connected\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [],\n                        \"span\": 4,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(grpc_server_started_total{job=\\\"$cluster\\\",grpc_service=\\\"etcdserverpb.Watch\\\",grpc_type=\\\"bidi_stream\\\"}) - sum(grpc_server_handled_total{job=\\\"$cluster\\\",grpc_service=\\\"etcdserverpb.Watch\\\",grpc_type=\\\"bidi_stream\\\"})\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"Watch Streams\",\n                                \"metric\": \"grpc_server_handled_total\",\n                                \"refId\": \"A\",\n                                \"step\": 4\n                            },\n                            {\n                                \"expr\": \"sum(grpc_server_started_total{job=\\\"$cluster\\\",grpc_service=\\\"etcdserverpb.Lease\\\",grpc_type=\\\"bidi_stream\\\"}) - sum(grpc_server_handled_total{job=\\\"$cluster\\\",grpc_service=\\\"etcdserverpb.Lease\\\",grpc_type=\\\"bidi_stream\\\"})\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"Lease Streams\",\n                                \"metric\": \"grpc_server_handled_total\",\n                                \"refId\": \"B\",\n                                \"step\": 4\n                            }\n                        ],\n                        \"thresholds\": [],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Active Streams\",\n                        \"tooltip\": {\n                            \"msResolution\": false,\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": []\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": \"\",\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"showTitle\": false,\n                \"title\": \"Row\"\n            },\n            {\n                \"collapse\": false,\n                \"editable\": true,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {},\n                        \"bars\": false,\n                        \"datasource\": \"$datasource\",\n                        \"decimals\": null,\n                        \"editable\": true,\n                        \"error\": false,\n                        \"fill\": 0,\n                        \"grid\": {},\n                        \"id\": 1,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": false,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [],\n                        \"nullPointMode\": \"connected\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [],\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"etcd_mvcc_db_total_size_in_bytes{job=\\\"$cluster\\\"}\",\n                                \"hide\": false,\n                                \"interval\": \"\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} DB Size\",\n                                \"metric\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 4\n                            }\n                        ],\n                        \"thresholds\": [],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"DB Size\",\n                        \"tooltip\": {\n                            \"msResolution\": false,\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"cumulative\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": []\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"bytes\",\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {},\n                        \"bars\": false,\n                        \"datasource\": \"$datasource\",\n                        \"editable\": true,\n                        \"error\": false,\n                        \"fill\": 0,\n                        \"grid\": {},\n                        \"id\": 3,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": false,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [],\n                        \"nullPointMode\": \"connected\",\n                        \"percentage\": false,\n                        \"pointradius\": 1,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [],\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": true,\n                        \"targets\": [\n                            {\n                                \"expr\": \"histogram_quantile(0.99, sum(rate(etcd_disk_wal_fsync_duration_seconds_bucket{job=\\\"$cluster\\\"}[5m])) by (instance, le))\",\n                                \"hide\": false,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} WAL fsync\",\n                                \"metric\": \"etcd_disk_wal_fsync_duration_seconds_bucket\",\n                                \"refId\": \"A\",\n                                \"step\": 4\n                            },\n                            {\n                                \"expr\": \"histogram_quantile(0.99, sum(rate(etcd_disk_backend_commit_duration_seconds_bucket{job=\\\"$cluster\\\"}[5m])) by (instance, le))\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} DB fsync\",\n                                \"metric\": \"etcd_disk_backend_commit_duration_seconds_bucket\",\n                                \"refId\": \"B\",\n                                \"step\": 4\n                            }\n                        ],\n                        \"thresholds\": [],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Disk Sync Duration\",\n                        \"tooltip\": {\n                            \"msResolution\": false,\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"cumulative\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": []\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"s\",\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {},\n                        \"bars\": false,\n                        \"datasource\": \"$datasource\",\n                        \"editable\": true,\n                        \"error\": false,\n                        \"fill\": 0,\n                        \"id\": 29,\n                        \"isNew\": true,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": false,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [],\n                        \"nullPointMode\": \"connected\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [],\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"process_resident_memory_bytes{job=\\\"$cluster\\\"}\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} Resident Memory\",\n                                \"metric\": \"process_resident_memory_bytes\",\n                                \"refId\": \"A\",\n                                \"step\": 4\n                            }\n                        ],\n                        \"thresholds\": [],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory\",\n                        \"tooltip\": {\n                            \"msResolution\": false,\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": []\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"title\": \"New row\"\n            },\n            {\n                \"collapse\": false,\n                \"editable\": true,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {},\n                        \"bars\": false,\n                        \"datasource\": \"$datasource\",\n                        \"editable\": true,\n                        \"error\": false,\n                        \"fill\": 5,\n                        \"id\": 22,\n                        \"isNew\": true,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": false,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [],\n                        \"nullPointMode\": \"connected\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [],\n                        \"span\": 3,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"rate(etcd_network_client_grpc_received_bytes_total{job=\\\"$cluster\\\"}[5m])\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} Client Traffic In\",\n                                \"metric\": \"etcd_network_client_grpc_received_bytes_total\",\n                                \"refId\": \"A\",\n                                \"step\": 4\n                            }\n                        ],\n                        \"thresholds\": [],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Client Traffic In\",\n                        \"tooltip\": {\n                            \"msResolution\": false,\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": []\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {},\n                        \"bars\": false,\n                        \"datasource\": \"$datasource\",\n                        \"editable\": true,\n                        \"error\": false,\n                        \"fill\": 5,\n                        \"id\": 21,\n                        \"isNew\": true,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": false,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [],\n                        \"nullPointMode\": \"connected\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [],\n                        \"span\": 3,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"rate(etcd_network_client_grpc_sent_bytes_total{job=\\\"$cluster\\\"}[5m])\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} Client Traffic Out\",\n                                \"metric\": \"etcd_network_client_grpc_sent_bytes_total\",\n                                \"refId\": \"A\",\n                                \"step\": 4\n                            }\n                        ],\n                        \"thresholds\": [],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Client Traffic Out\",\n                        \"tooltip\": {\n                            \"msResolution\": false,\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": []\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {},\n                        \"bars\": false,\n                        \"datasource\": \"$datasource\",\n                        \"editable\": true,\n                        \"error\": false,\n                        \"fill\": 0,\n                        \"id\": 20,\n                        \"isNew\": true,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": false,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [],\n                        \"nullPointMode\": \"connected\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [],\n                        \"span\": 3,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(rate(etcd_network_peer_received_bytes_total{job=\\\"$cluster\\\"}[5m])) by (instance)\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} Peer Traffic In\",\n                                \"metric\": \"etcd_network_peer_received_bytes_total\",\n                                \"refId\": \"A\",\n                                \"step\": 4\n                            }\n                        ],\n                        \"thresholds\": [],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Peer Traffic In\",\n                        \"tooltip\": {\n                            \"msResolution\": false,\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": []\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {},\n                        \"bars\": false,\n                        \"datasource\": \"$datasource\",\n                        \"decimals\": null,\n                        \"editable\": true,\n                        \"error\": false,\n                        \"fill\": 0,\n                        \"grid\": {},\n                        \"id\": 16,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": false,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [],\n                        \"nullPointMode\": \"connected\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [],\n                        \"span\": 3,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(rate(etcd_network_peer_sent_bytes_total{job=\\\"$cluster\\\"}[5m])) by (instance)\",\n                                \"hide\": false,\n                                \"interval\": \"\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} Peer Traffic Out\",\n                                \"metric\": \"etcd_network_peer_sent_bytes_total\",\n                                \"refId\": \"A\",\n                                \"step\": 4\n                            }\n                        ],\n                        \"thresholds\": [],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Peer Traffic Out\",\n                        \"tooltip\": {\n                            \"msResolution\": false,\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"cumulative\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": []\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"title\": \"New row\"\n            },\n            {\n                \"collapse\": false,\n                \"editable\": true,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {},\n                        \"bars\": false,\n                        \"datasource\": \"$datasource\",\n                        \"editable\": true,\n                        \"error\": false,\n                        \"fill\": 0,\n                        \"id\": 40,\n                        \"isNew\": true,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": false,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [],\n                        \"nullPointMode\": \"connected\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [],\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(rate(etcd_server_proposals_failed_total{job=\\\"$cluster\\\"}[5m]))\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"Proposal Failure Rate\",\n                                \"metric\": \"etcd_server_proposals_failed_total\",\n                                \"refId\": \"A\",\n                                \"step\": 2\n                            },\n                            {\n                                \"expr\": \"sum(etcd_server_proposals_pending{job=\\\"$cluster\\\"})\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"Proposal Pending Total\",\n                                \"metric\": \"etcd_server_proposals_pending\",\n                                \"refId\": \"B\",\n                                \"step\": 2\n                            },\n                            {\n                                \"expr\": \"sum(rate(etcd_server_proposals_committed_total{job=\\\"$cluster\\\"}[5m]))\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"Proposal Commit Rate\",\n                                \"metric\": \"etcd_server_proposals_committed_total\",\n                                \"refId\": \"C\",\n                                \"step\": 2\n                            },\n                            {\n                                \"expr\": \"sum(rate(etcd_server_proposals_applied_total{job=\\\"$cluster\\\"}[5m]))\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"Proposal Apply Rate\",\n                                \"refId\": \"D\",\n                                \"step\": 2\n                            }\n                        ],\n                        \"thresholds\": [],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Raft Proposals\",\n                        \"tooltip\": {\n                            \"msResolution\": false,\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": []\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": \"\",\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {},\n                        \"bars\": false,\n                        \"datasource\": \"$datasource\",\n                        \"decimals\": 0,\n                        \"editable\": true,\n                        \"error\": false,\n                        \"fill\": 0,\n                        \"id\": 19,\n                        \"isNew\": true,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": false,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [],\n                        \"nullPointMode\": \"connected\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [],\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"changes(etcd_server_leader_changes_seen_total{job=\\\"$cluster\\\"}[1d])\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} Total Leader Elections Per Day\",\n                                \"metric\": \"etcd_server_leader_changes_seen_total\",\n                                \"refId\": \"A\",\n                                \"step\": 2\n                            }\n                        ],\n                        \"thresholds\": [],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Total Leader Elections Per Day\",\n                        \"tooltip\": {\n                            \"msResolution\": false,\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": []\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"title\": \"New row\"\n            }\n        ],\n        \"schemaVersion\": 13,\n        \"sharedCrosshair\": false,\n        \"style\": \"dark\",\n        \"tags\": [],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"Prometheus\",\n                        \"value\": \"Prometheus\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": \"prod\",\n                        \"value\": \"prod\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }},\n                    \"includeAll\": false,\n                    \"label\": \"cluster\",\n                    \"multi\": false,\n                    \"name\": \"cluster\",\n                    \"options\": [],\n                    \"query\": \"label_values(etcd_server_has_leader, job)\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"sort\": 2,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-15m\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"now\": true,\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"browser\",\n        \"title\": \"etcd\",\n        \"version\": 215\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-coredns.yaml",
    "content": "{{- /* Added manually, can be changed in-place. */ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled .Values.coreDns.enabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"k8s-coredns\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  k8s-coredns.json: |-\n    {\n      \"annotations\": {\n        \"list\": [\n          {\n            \"builtIn\": 1,\n            \"datasource\": \"-- Grafana --\",\n            \"enable\": true,\n            \"hide\": true,\n            \"iconColor\": \"rgba(0, 211, 255, 1)\",\n            \"name\": \"Annotations & Alerts\",\n            \"type\": \"dashboard\"\n          }\n        ]\n      },\n      \"description\": \"A dashboard for the CoreDNS DNS server with updated metrics for version 1.7.0+.  Based on the CoreDNS dashboard by buhay.\",\n      \"editable\": true,\n      \"gnetId\": 12539,\n      \"graphTooltip\": 0,\n      \"iteration\": 1603798405693,\n      \"links\": [\n        {\n          \"icon\": \"external link\",\n          \"tags\": [],\n          \"targetBlank\": true,\n          \"title\": \"CoreDNS.io\",\n          \"type\": \"link\",\n          \"url\": \"https://coredns.io\"\n        }\n      ],\n      \"panels\": [\n        {\n          \"aliasColors\": {},\n          \"bars\": false,\n          \"dashLength\": 10,\n          \"dashes\": false,\n          \"datasource\": \"$datasource\",\n          \"editable\": true,\n          \"error\": false,\n          \"fieldConfig\": {\n            \"defaults\": {\n              \"custom\": {},\n              \"links\": [],\n              \"mappings\": [],\n              \"thresholds\": {\n                \"mode\": \"absolute\",\n                \"steps\": [\n                  {\n                    \"color\": \"green\",\n                    \"value\": null\n                  },\n                  {\n                    \"color\": \"red\",\n                    \"value\": 80\n                  }\n                ]\n              }\n            },\n            \"overrides\": []\n          },\n          \"fill\": 1,\n          \"fillGradient\": 0,\n          \"grid\": {},\n          \"gridPos\": {\n            \"h\": 7,\n            \"w\": 8,\n            \"x\": 0,\n            \"y\": 0\n          },\n          \"hiddenSeries\": false,\n          \"id\": 2,\n          \"legend\": {\n            \"avg\": false,\n            \"current\": false,\n            \"max\": false,\n            \"min\": false,\n            \"show\": true,\n            \"total\": false,\n            \"values\": false\n          },\n          \"lines\": true,\n          \"linewidth\": 2,\n          \"links\": [],\n          \"nullPointMode\": \"connected\",\n          \"options\": {\n            \"alertThreshold\": true\n          },\n          \"percentage\": false,\n          \"pluginVersion\": \"7.2.0\",\n          \"pointradius\": 5,\n          \"points\": false,\n          \"renderer\": \"flot\",\n          \"seriesOverrides\": [\n            {\n              \"alias\": \"total\",\n              \"yaxis\": 2\n            }\n          ],\n          \"spaceLength\": 10,\n          \"stack\": true,\n          \"steppedLine\": false,\n          \"targets\": [\n            {\n              \"expr\": \"sum(rate(coredns_dns_request_count_total{instance=~\\\"$instance\\\"}[5m])) by (proto) or\\nsum(rate(coredns_dns_requests_total{instance=~\\\"$instance\\\"}[5m])) by (proto)\",\n              \"format\": \"time_series\",\n              \"interval\": \"\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"{{\"{{proto}}\"}}\",\n              \"refId\": \"A\",\n              \"step\": 60\n            }\n          ],\n          \"thresholds\": [],\n          \"timeFrom\": null,\n          \"timeRegions\": [],\n          \"timeShift\": null,\n          \"title\": \"Requests (total)\",\n          \"tooltip\": {\n            \"shared\": true,\n            \"sort\": 2,\n            \"value_type\": \"individual\"\n          },\n          \"type\": \"graph\",\n          \"xaxis\": {\n            \"buckets\": null,\n            \"mode\": \"time\",\n            \"name\": null,\n            \"show\": true,\n            \"values\": []\n          },\n          \"yaxes\": [\n            {\n              \"format\": \"pps\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            },\n            {\n              \"format\": \"pps\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            }\n          ],\n          \"yaxis\": {\n            \"align\": false,\n            \"alignLevel\": null\n          }\n        },\n        {\n          \"aliasColors\": {},\n          \"bars\": false,\n          \"dashLength\": 10,\n          \"dashes\": false,\n          \"datasource\": \"$datasource\",\n          \"editable\": true,\n          \"error\": false,\n          \"fieldConfig\": {\n            \"defaults\": {\n              \"custom\": {},\n              \"links\": []\n            },\n            \"overrides\": []\n          },\n          \"fill\": 1,\n          \"fillGradient\": 0,\n          \"grid\": {},\n          \"gridPos\": {\n            \"h\": 7,\n            \"w\": 8,\n            \"x\": 8,\n            \"y\": 0\n          },\n          \"hiddenSeries\": false,\n          \"id\": 4,\n          \"legend\": {\n            \"avg\": false,\n            \"current\": false,\n            \"max\": false,\n            \"min\": false,\n            \"show\": true,\n            \"total\": false,\n            \"values\": false\n          },\n          \"lines\": true,\n          \"linewidth\": 2,\n          \"links\": [],\n          \"nullPointMode\": \"connected\",\n          \"options\": {\n            \"alertThreshold\": true\n          },\n          \"percentage\": false,\n          \"pluginVersion\": \"7.2.0\",\n          \"pointradius\": 5,\n          \"points\": false,\n          \"renderer\": \"flot\",\n          \"seriesOverrides\": [\n            {\n              \"alias\": \"total\",\n              \"yaxis\": 2\n            },\n            {\n              \"alias\": \"other\",\n              \"yaxis\": 2\n            }\n          ],\n          \"spaceLength\": 10,\n          \"stack\": true,\n          \"steppedLine\": false,\n          \"targets\": [\n            {\n              \"expr\": \"sum(rate(coredns_dns_request_type_count_total{instance=~\\\"$instance\\\"}[5m])) by (type) or \\nsum(rate(coredns_dns_requests_total{instance=~\\\"$instance\\\"}[5m])) by (type)\",\n              \"interval\": \"\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"{{\"{{type}}\"}}\",\n              \"refId\": \"A\",\n              \"step\": 60\n            }\n          ],\n          \"thresholds\": [],\n          \"timeFrom\": null,\n          \"timeRegions\": [],\n          \"timeShift\": null,\n          \"title\": \"Requests (by qtype)\",\n          \"tooltip\": {\n            \"shared\": true,\n            \"sort\": 2,\n            \"value_type\": \"individual\"\n          },\n          \"type\": \"graph\",\n          \"xaxis\": {\n            \"buckets\": null,\n            \"mode\": \"time\",\n            \"name\": null,\n            \"show\": true,\n            \"values\": []\n          },\n          \"yaxes\": [\n            {\n              \"format\": \"pps\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            },\n            {\n              \"format\": \"pps\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            }\n          ],\n          \"yaxis\": {\n            \"align\": false,\n            \"alignLevel\": null\n          }\n        },\n        {\n          \"aliasColors\": {},\n          \"bars\": false,\n          \"dashLength\": 10,\n          \"dashes\": false,\n          \"datasource\": \"$datasource\",\n          \"editable\": true,\n          \"error\": false,\n          \"fieldConfig\": {\n            \"defaults\": {\n              \"custom\": {},\n              \"links\": []\n            },\n            \"overrides\": []\n          },\n          \"fill\": 1,\n          \"fillGradient\": 0,\n          \"grid\": {},\n          \"gridPos\": {\n            \"h\": 7,\n            \"w\": 8,\n            \"x\": 16,\n            \"y\": 0\n          },\n          \"hiddenSeries\": false,\n          \"id\": 6,\n          \"legend\": {\n            \"avg\": false,\n            \"current\": false,\n            \"max\": false,\n            \"min\": false,\n            \"show\": true,\n            \"total\": false,\n            \"values\": false\n          },\n          \"lines\": true,\n          \"linewidth\": 2,\n          \"links\": [],\n          \"nullPointMode\": \"connected\",\n          \"options\": {\n            \"alertThreshold\": true\n          },\n          \"percentage\": false,\n          \"pluginVersion\": \"7.2.0\",\n          \"pointradius\": 5,\n          \"points\": false,\n          \"renderer\": \"flot\",\n          \"seriesOverrides\": [\n            {\n              \"alias\": \"total\",\n              \"yaxis\": 2\n            }\n          ],\n          \"spaceLength\": 10,\n          \"stack\": true,\n          \"steppedLine\": false,\n          \"targets\": [\n            {\n              \"expr\": \"sum(rate(coredns_dns_request_count_total{instance=~\\\"$instance\\\"}[5m])) by (zone) or\\nsum(rate(coredns_dns_requests_total{instance=~\\\"$instance\\\"}[5m])) by (zone)\",\n              \"interval\": \"\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"{{\"{{zone}}\"}}\",\n              \"refId\": \"A\",\n              \"step\": 60\n            }\n          ],\n          \"thresholds\": [],\n          \"timeFrom\": null,\n          \"timeRegions\": [],\n          \"timeShift\": null,\n          \"title\": \"Requests (by zone)\",\n          \"tooltip\": {\n            \"shared\": true,\n            \"sort\": 2,\n            \"value_type\": \"individual\"\n          },\n          \"type\": \"graph\",\n          \"xaxis\": {\n            \"buckets\": null,\n            \"mode\": \"time\",\n            \"name\": null,\n            \"show\": true,\n            \"values\": []\n          },\n          \"yaxes\": [\n            {\n              \"format\": \"pps\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            },\n            {\n              \"format\": \"pps\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            }\n          ],\n          \"yaxis\": {\n            \"align\": false,\n            \"alignLevel\": null\n          }\n        },\n        {\n          \"aliasColors\": {},\n          \"bars\": false,\n          \"dashLength\": 10,\n          \"dashes\": false,\n          \"datasource\": \"$datasource\",\n          \"editable\": true,\n          \"error\": false,\n          \"fieldConfig\": {\n            \"defaults\": {\n              \"custom\": {},\n              \"links\": []\n            },\n            \"overrides\": []\n          },\n          \"fill\": 1,\n          \"fillGradient\": 0,\n          \"grid\": {},\n          \"gridPos\": {\n            \"h\": 7,\n            \"w\": 12,\n            \"x\": 0,\n            \"y\": 7\n          },\n          \"hiddenSeries\": false,\n          \"id\": 8,\n          \"legend\": {\n            \"avg\": false,\n            \"current\": false,\n            \"max\": false,\n            \"min\": false,\n            \"show\": true,\n            \"total\": false,\n            \"values\": false\n          },\n          \"lines\": true,\n          \"linewidth\": 2,\n          \"links\": [],\n          \"nullPointMode\": \"connected\",\n          \"options\": {\n            \"alertThreshold\": true\n          },\n          \"percentage\": false,\n          \"pluginVersion\": \"7.2.0\",\n          \"pointradius\": 5,\n          \"points\": false,\n          \"renderer\": \"flot\",\n          \"seriesOverrides\": [\n            {\n              \"alias\": \"total\",\n              \"yaxis\": 2\n            }\n          ],\n          \"spaceLength\": 10,\n          \"stack\": false,\n          \"steppedLine\": false,\n          \"targets\": [\n            {\n              \"expr\": \"sum(rate(coredns_dns_request_do_count_total{instance=~\\\"$instance\\\"}[5m])) or\\nsum(rate(coredns_dns_do_requests_total{instance=~\\\"$instance\\\"}[5m]))\",\n              \"interval\": \"\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"DO\",\n              \"refId\": \"A\",\n              \"step\": 40\n            },\n            {\n              \"expr\": \"sum(rate(coredns_dns_request_count_total{instance=~\\\"$instance\\\"}[5m])) or\\nsum(rate(coredns_dns_requests_total{instance=~\\\"$instance\\\"}[5m]))\",\n              \"interval\": \"\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"total\",\n              \"refId\": \"B\",\n              \"step\": 40\n            }\n          ],\n          \"thresholds\": [],\n          \"timeFrom\": null,\n          \"timeRegions\": [],\n          \"timeShift\": null,\n          \"title\": \"Requests (DO bit)\",\n          \"tooltip\": {\n            \"shared\": true,\n            \"sort\": 2,\n            \"value_type\": \"cumulative\"\n          },\n          \"type\": \"graph\",\n          \"xaxis\": {\n            \"buckets\": null,\n            \"mode\": \"time\",\n            \"name\": null,\n            \"show\": true,\n            \"values\": []\n          },\n          \"yaxes\": [\n            {\n              \"format\": \"pps\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            },\n            {\n              \"format\": \"pps\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": null,\n              \"show\": true\n            }\n          ],\n          \"yaxis\": {\n            \"align\": false,\n            \"alignLevel\": null\n          }\n        },\n        {\n          \"aliasColors\": {},\n          \"bars\": false,\n          \"dashLength\": 10,\n          \"dashes\": false,\n          \"datasource\": \"$datasource\",\n          \"editable\": true,\n          \"error\": false,\n          \"fieldConfig\": {\n            \"defaults\": {\n              \"custom\": {},\n              \"links\": []\n            },\n            \"overrides\": []\n          },\n          \"fill\": 1,\n          \"fillGradient\": 0,\n          \"grid\": {},\n          \"gridPos\": {\n            \"h\": 7,\n            \"w\": 6,\n            \"x\": 12,\n            \"y\": 7\n          },\n          \"hiddenSeries\": false,\n          \"id\": 10,\n          \"legend\": {\n            \"avg\": false,\n            \"current\": false,\n            \"max\": false,\n            \"min\": false,\n            \"show\": true,\n            \"total\": false,\n            \"values\": false\n          },\n          \"lines\": true,\n          \"linewidth\": 2,\n          \"links\": [],\n          \"nullPointMode\": \"connected\",\n          \"options\": {\n            \"alertThreshold\": true\n          },\n          \"percentage\": false,\n          \"pluginVersion\": \"7.2.0\",\n          \"pointradius\": 5,\n          \"points\": false,\n          \"renderer\": \"flot\",\n          \"seriesOverrides\": [\n            {\n              \"alias\": \"tcp:90\",\n              \"yaxis\": 2\n            },\n            {\n              \"alias\": \"tcp:99 \",\n              \"yaxis\": 2\n            },\n            {\n              \"alias\": \"tcp:50\",\n              \"yaxis\": 2\n            }\n          ],\n          \"spaceLength\": 10,\n          \"stack\": false,\n          \"steppedLine\": false,\n          \"targets\": [\n            {\n              \"expr\": \"histogram_quantile(0.99, sum(rate(coredns_dns_request_size_bytes_bucket{instance=~\\\"$instance\\\",proto=\\\"udp\\\"}[5m])) by (le,proto))\",\n              \"interval\": \"\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"{{\"{{proto}}\"}}:99 \",\n              \"refId\": \"A\",\n              \"step\": 60\n            },\n            {\n              \"expr\": \"histogram_quantile(0.90, sum(rate(coredns_dns_request_size_bytes_bucket{instance=~\\\"$instance\\\",proto=\\\"udp\\\"}[5m])) by (le,proto))\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"{{\"{{proto}}\"}}:90\",\n              \"refId\": \"B\",\n              \"step\": 60\n            },\n            {\n              \"expr\": \"histogram_quantile(0.50, sum(rate(coredns_dns_request_size_bytes_bucket{instance=~\\\"$instance\\\",proto=\\\"udp\\\"}[5m])) by (le,proto))\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"{{\"{{proto}}\"}}:50\",\n              \"refId\": \"C\",\n              \"step\": 60\n            }\n          ],\n          \"thresholds\": [],\n          \"timeFrom\": null,\n          \"timeRegions\": [],\n          \"timeShift\": null,\n          \"title\": \"Requests (size, udp)\",\n          \"tooltip\": {\n            \"shared\": true,\n            \"sort\": 0,\n            \"value_type\": \"cumulative\"\n          },\n          \"type\": \"graph\",\n          \"xaxis\": {\n            \"buckets\": null,\n            \"mode\": \"time\",\n            \"name\": null,\n            \"show\": true,\n            \"values\": []\n          },\n          \"yaxes\": [\n            {\n              \"format\": \"bytes\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            },\n            {\n              \"format\": \"short\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            }\n          ],\n          \"yaxis\": {\n            \"align\": false,\n            \"alignLevel\": null\n          }\n        },\n        {\n          \"aliasColors\": {},\n          \"bars\": false,\n          \"dashLength\": 10,\n          \"dashes\": false,\n          \"datasource\": \"$datasource\",\n          \"editable\": true,\n          \"error\": false,\n          \"fieldConfig\": {\n            \"defaults\": {\n              \"custom\": {},\n              \"links\": []\n            },\n            \"overrides\": []\n          },\n          \"fill\": 1,\n          \"fillGradient\": 0,\n          \"grid\": {},\n          \"gridPos\": {\n            \"h\": 7,\n            \"w\": 6,\n            \"x\": 18,\n            \"y\": 7\n          },\n          \"hiddenSeries\": false,\n          \"id\": 12,\n          \"legend\": {\n            \"avg\": false,\n            \"current\": false,\n            \"max\": false,\n            \"min\": false,\n            \"show\": true,\n            \"total\": false,\n            \"values\": false\n          },\n          \"lines\": true,\n          \"linewidth\": 2,\n          \"links\": [],\n          \"nullPointMode\": \"connected\",\n          \"options\": {\n            \"alertThreshold\": true\n          },\n          \"percentage\": false,\n          \"pluginVersion\": \"7.2.0\",\n          \"pointradius\": 5,\n          \"points\": false,\n          \"renderer\": \"flot\",\n          \"seriesOverrides\": [\n            {\n              \"alias\": \"tcp:90\",\n              \"yaxis\": 1\n            },\n            {\n              \"alias\": \"tcp:99 \",\n              \"yaxis\": 1\n            },\n            {\n              \"alias\": \"tcp:50\",\n              \"yaxis\": 1\n            }\n          ],\n          \"spaceLength\": 10,\n          \"stack\": false,\n          \"steppedLine\": false,\n          \"targets\": [\n            {\n              \"expr\": \"histogram_quantile(0.99, sum(rate(coredns_dns_request_size_bytes_bucket{instance=~\\\"$instance\\\",proto=\\\"tcp\\\"}[5m])) by (le,proto))\",\n              \"format\": \"time_series\",\n              \"interval\": \"\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"{{\"{{proto}}\"}}:99 \",\n              \"refId\": \"A\",\n              \"step\": 60\n            },\n            {\n              \"expr\": \"histogram_quantile(0.90, sum(rate(coredns_dns_request_size_bytes_bucket{instance=~\\\"$instance\\\",proto=\\\"tcp\\\"}[5m])) by (le,proto))\",\n              \"format\": \"time_series\",\n              \"interval\": \"\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"{{\"{{proto}}\"}}:90\",\n              \"refId\": \"B\",\n              \"step\": 60\n            },\n            {\n              \"expr\": \"histogram_quantile(0.50, sum(rate(coredns_dns_request_size_bytes_bucket{instance=~\\\"$instance\\\",proto=\\\"tcp\\\"}[5m])) by (le,proto))\",\n              \"format\": \"time_series\",\n              \"interval\": \"\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"{{\"{{proto}}\"}}:50\",\n              \"refId\": \"C\",\n              \"step\": 60\n            }\n          ],\n          \"thresholds\": [],\n          \"timeFrom\": null,\n          \"timeRegions\": [],\n          \"timeShift\": null,\n          \"title\": \"Requests (size,tcp)\",\n          \"tooltip\": {\n            \"shared\": true,\n            \"sort\": 0,\n            \"value_type\": \"cumulative\"\n          },\n          \"type\": \"graph\",\n          \"xaxis\": {\n            \"buckets\": null,\n            \"mode\": \"time\",\n            \"name\": null,\n            \"show\": true,\n            \"values\": []\n          },\n          \"yaxes\": [\n            {\n              \"format\": \"bytes\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            },\n            {\n              \"format\": \"short\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            }\n          ],\n          \"yaxis\": {\n            \"align\": false,\n            \"alignLevel\": null\n          }\n        },\n        {\n          \"aliasColors\": {},\n          \"bars\": false,\n          \"dashLength\": 10,\n          \"dashes\": false,\n          \"datasource\": \"$datasource\",\n          \"editable\": true,\n          \"error\": false,\n          \"fieldConfig\": {\n            \"defaults\": {\n              \"custom\": {},\n              \"links\": []\n            },\n            \"overrides\": []\n          },\n          \"fill\": 1,\n          \"fillGradient\": 0,\n          \"grid\": {},\n          \"gridPos\": {\n            \"h\": 7,\n            \"w\": 12,\n            \"x\": 0,\n            \"y\": 14\n          },\n          \"hiddenSeries\": false,\n          \"id\": 14,\n          \"legend\": {\n            \"avg\": false,\n            \"current\": false,\n            \"max\": false,\n            \"min\": false,\n            \"show\": true,\n            \"total\": false,\n            \"values\": false\n          },\n          \"lines\": true,\n          \"linewidth\": 2,\n          \"links\": [],\n          \"nullPointMode\": \"connected\",\n          \"options\": {\n            \"alertThreshold\": true\n          },\n          \"percentage\": false,\n          \"pluginVersion\": \"7.2.0\",\n          \"pointradius\": 5,\n          \"points\": false,\n          \"renderer\": \"flot\",\n          \"seriesOverrides\": [],\n          \"spaceLength\": 10,\n          \"stack\": true,\n          \"steppedLine\": false,\n          \"targets\": [\n            {\n              \"expr\": \"sum(rate(coredns_dns_response_rcode_count_total{instance=~\\\"$instance\\\"}[5m])) by (rcode) or\\nsum(rate(coredns_dns_responses_total{instance=~\\\"$instance\\\"}[5m])) by (rcode)\",\n              \"interval\": \"\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"{{\"{{rcode}}\"}}\",\n              \"refId\": \"A\",\n              \"step\": 40\n            }\n          ],\n          \"thresholds\": [],\n          \"timeFrom\": null,\n          \"timeRegions\": [],\n          \"timeShift\": null,\n          \"title\": \"Responses (by rcode)\",\n          \"tooltip\": {\n            \"shared\": true,\n            \"sort\": 2,\n            \"value_type\": \"individual\"\n          },\n          \"type\": \"graph\",\n          \"xaxis\": {\n            \"buckets\": null,\n            \"mode\": \"time\",\n            \"name\": null,\n            \"show\": true,\n            \"values\": []\n          },\n          \"yaxes\": [\n            {\n              \"format\": \"pps\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            },\n            {\n              \"format\": \"short\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": null,\n              \"show\": true\n            }\n          ],\n          \"yaxis\": {\n            \"align\": false,\n            \"alignLevel\": null\n          }\n        },\n        {\n          \"aliasColors\": {},\n          \"bars\": false,\n          \"dashLength\": 10,\n          \"dashes\": false,\n          \"datasource\": \"$datasource\",\n          \"editable\": true,\n          \"error\": false,\n          \"fieldConfig\": {\n            \"defaults\": {\n              \"custom\": {},\n              \"links\": []\n            },\n            \"overrides\": []\n          },\n          \"fill\": 1,\n          \"fillGradient\": 0,\n          \"grid\": {},\n          \"gridPos\": {\n            \"h\": 7,\n            \"w\": 12,\n            \"x\": 12,\n            \"y\": 14\n          },\n          \"hiddenSeries\": false,\n          \"id\": 32,\n          \"legend\": {\n            \"avg\": false,\n            \"current\": false,\n            \"max\": false,\n            \"min\": false,\n            \"show\": true,\n            \"total\": false,\n            \"values\": false\n          },\n          \"lines\": true,\n          \"linewidth\": 2,\n          \"links\": [],\n          \"nullPointMode\": \"connected\",\n          \"options\": {\n            \"alertThreshold\": true\n          },\n          \"percentage\": false,\n          \"pluginVersion\": \"7.2.0\",\n          \"pointradius\": 5,\n          \"points\": false,\n          \"renderer\": \"flot\",\n          \"seriesOverrides\": [],\n          \"spaceLength\": 10,\n          \"stack\": false,\n          \"steppedLine\": false,\n          \"targets\": [\n            {\n              \"expr\": \"histogram_quantile(0.99, sum(rate(coredns_dns_request_duration_seconds_bucket{instance=~\\\"$instance\\\"}[5m])) by (le, job))\",\n              \"format\": \"time_series\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"99%\",\n              \"refId\": \"A\",\n              \"step\": 40\n            },\n            {\n              \"expr\": \"histogram_quantile(0.90, sum(rate(coredns_dns_request_duration_seconds_bucket{instance=~\\\"$instance\\\"}[5m])) by (le))\",\n              \"format\": \"time_series\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"90%\",\n              \"refId\": \"B\",\n              \"step\": 40\n            },\n            {\n              \"expr\": \"histogram_quantile(0.50, sum(rate(coredns_dns_request_duration_seconds_bucket{instance=~\\\"$instance\\\"}[5m])) by (le))\",\n              \"format\": \"time_series\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"50%\",\n              \"refId\": \"C\",\n              \"step\": 40\n            }\n          ],\n          \"thresholds\": [],\n          \"timeFrom\": null,\n          \"timeRegions\": [],\n          \"timeShift\": null,\n          \"title\": \"Responses (duration)\",\n          \"tooltip\": {\n            \"shared\": true,\n            \"sort\": 0,\n            \"value_type\": \"cumulative\"\n          },\n          \"type\": \"graph\",\n          \"xaxis\": {\n            \"buckets\": null,\n            \"mode\": \"time\",\n            \"name\": null,\n            \"show\": true,\n            \"values\": []\n          },\n          \"yaxes\": [\n            {\n              \"format\": \"s\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            },\n            {\n              \"format\": \"short\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": null,\n              \"show\": true\n            }\n          ],\n          \"yaxis\": {\n            \"align\": false,\n            \"alignLevel\": null\n          }\n        },\n        {\n          \"aliasColors\": {},\n          \"bars\": false,\n          \"dashLength\": 10,\n          \"dashes\": false,\n          \"datasource\": \"$datasource\",\n          \"editable\": true,\n          \"error\": false,\n          \"fieldConfig\": {\n            \"defaults\": {\n              \"custom\": {},\n              \"links\": []\n            },\n            \"overrides\": []\n          },\n          \"fill\": 1,\n          \"fillGradient\": 0,\n          \"grid\": {},\n          \"gridPos\": {\n            \"h\": 7,\n            \"w\": 12,\n            \"x\": 0,\n            \"y\": 21\n          },\n          \"hiddenSeries\": false,\n          \"id\": 18,\n          \"legend\": {\n            \"avg\": false,\n            \"current\": false,\n            \"max\": false,\n            \"min\": false,\n            \"show\": true,\n            \"total\": false,\n            \"values\": false\n          },\n          \"lines\": true,\n          \"linewidth\": 2,\n          \"links\": [],\n          \"nullPointMode\": \"connected\",\n          \"options\": {\n            \"alertThreshold\": true\n          },\n          \"percentage\": false,\n          \"pluginVersion\": \"7.2.0\",\n          \"pointradius\": 5,\n          \"points\": false,\n          \"renderer\": \"flot\",\n          \"seriesOverrides\": [\n            {\n              \"alias\": \"udp:50%\",\n              \"yaxis\": 1\n            },\n            {\n              \"alias\": \"tcp:50%\",\n              \"yaxis\": 2\n            },\n            {\n              \"alias\": \"tcp:90%\",\n              \"yaxis\": 2\n            },\n            {\n              \"alias\": \"tcp:99%\",\n              \"yaxis\": 2\n            }\n          ],\n          \"spaceLength\": 10,\n          \"stack\": false,\n          \"steppedLine\": false,\n          \"targets\": [\n            {\n              \"expr\": \"histogram_quantile(0.99, sum(rate(coredns_dns_response_size_bytes_bucket{instance=~\\\"$instance\\\",proto=\\\"udp\\\"}[5m])) by (le,proto)) \",\n              \"interval\": \"\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"{{\"{{proto}}\"}}:99%\",\n              \"refId\": \"A\",\n              \"step\": 40\n            },\n            {\n              \"expr\": \"histogram_quantile(0.90, sum(rate(coredns_dns_response_size_bytes_bucket{instance=~\\\"$instance\\\",proto=\\\"udp\\\"}[5m])) by (le,proto)) \",\n              \"interval\": \"\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"{{\"{{proto}}\"}}:90%\",\n              \"refId\": \"B\",\n              \"step\": 40\n            },\n            {\n              \"expr\": \"histogram_quantile(0.50, sum(rate(coredns_dns_response_size_bytes_bucket{instance=~\\\"$instance\\\",proto=\\\"udp\\\"}[5m])) by (le,proto)) \",\n              \"hide\": false,\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"{{\"{{proto}}\"}}:50%\",\n              \"metric\": \"\",\n              \"refId\": \"C\",\n              \"step\": 40\n            }\n          ],\n          \"thresholds\": [],\n          \"timeFrom\": null,\n          \"timeRegions\": [],\n          \"timeShift\": null,\n          \"title\": \"Responses (size, udp)\",\n          \"tooltip\": {\n            \"shared\": true,\n            \"sort\": 0,\n            \"value_type\": \"cumulative\"\n          },\n          \"type\": \"graph\",\n          \"xaxis\": {\n            \"buckets\": null,\n            \"mode\": \"time\",\n            \"name\": null,\n            \"show\": true,\n            \"values\": []\n          },\n          \"yaxes\": [\n            {\n              \"format\": \"bytes\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            },\n            {\n              \"format\": \"short\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            }\n          ],\n          \"yaxis\": {\n            \"align\": false,\n            \"alignLevel\": null\n          }\n        },\n        {\n          \"aliasColors\": {},\n          \"bars\": false,\n          \"dashLength\": 10,\n          \"dashes\": false,\n          \"datasource\": \"$datasource\",\n          \"editable\": true,\n          \"error\": false,\n          \"fieldConfig\": {\n            \"defaults\": {\n              \"custom\": {},\n              \"links\": []\n            },\n            \"overrides\": []\n          },\n          \"fill\": 1,\n          \"fillGradient\": 0,\n          \"grid\": {},\n          \"gridPos\": {\n            \"h\": 7,\n            \"w\": 12,\n            \"x\": 12,\n            \"y\": 21\n          },\n          \"hiddenSeries\": false,\n          \"id\": 20,\n          \"legend\": {\n            \"avg\": false,\n            \"current\": false,\n            \"max\": false,\n            \"min\": false,\n            \"show\": true,\n            \"total\": false,\n            \"values\": false\n          },\n          \"lines\": true,\n          \"linewidth\": 2,\n          \"links\": [],\n          \"nullPointMode\": \"connected\",\n          \"options\": {\n            \"alertThreshold\": true\n          },\n          \"percentage\": false,\n          \"pluginVersion\": \"7.2.0\",\n          \"pointradius\": 5,\n          \"points\": false,\n          \"renderer\": \"flot\",\n          \"seriesOverrides\": [\n            {\n              \"alias\": \"udp:50%\",\n              \"yaxis\": 1\n            },\n            {\n              \"alias\": \"tcp:50%\",\n              \"yaxis\": 1\n            },\n            {\n              \"alias\": \"tcp:90%\",\n              \"yaxis\": 1\n            },\n            {\n              \"alias\": \"tcp:99%\",\n              \"yaxis\": 1\n            }\n          ],\n          \"spaceLength\": 10,\n          \"stack\": false,\n          \"steppedLine\": false,\n          \"targets\": [\n            {\n              \"expr\": \"histogram_quantile(0.99, sum(rate(coredns_dns_response_size_bytes_bucket{instance=~\\\"$instance\\\",proto=\\\"tcp\\\"}[5m])) by (le,proto)) \",\n              \"format\": \"time_series\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"{{\"{{proto}}\"}}:99%\",\n              \"refId\": \"A\",\n              \"step\": 40\n            },\n            {\n              \"expr\": \"histogram_quantile(0.90, sum(rate(coredns_dns_response_size_bytes_bucket{instance=~\\\"$instance\\\",proto=\\\"tcp\\\"}[5m])) by (le,proto)) \",\n              \"format\": \"time_series\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"{{\"{{proto}}\"}}:90%\",\n              \"refId\": \"B\",\n              \"step\": 40\n            },\n            {\n              \"expr\": \"histogram_quantile(0.50, sum(rate(coredns_dns_response_size_bytes_bucket{instance=~\\\"$instance\\\",proto=\\\"tcp\\\"}[5m])) by (le, proto)) \",\n              \"format\": \"time_series\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"{{\"{{proto}}\"}}:50%\",\n              \"metric\": \"\",\n              \"refId\": \"C\",\n              \"step\": 40\n            }\n          ],\n          \"thresholds\": [],\n          \"timeFrom\": null,\n          \"timeRegions\": [],\n          \"timeShift\": null,\n          \"title\": \"Responses (size, tcp)\",\n          \"tooltip\": {\n            \"shared\": true,\n            \"sort\": 0,\n            \"value_type\": \"cumulative\"\n          },\n          \"type\": \"graph\",\n          \"xaxis\": {\n            \"buckets\": null,\n            \"mode\": \"time\",\n            \"name\": null,\n            \"show\": true,\n            \"values\": []\n          },\n          \"yaxes\": [\n            {\n              \"format\": \"bytes\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            },\n            {\n              \"format\": \"short\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            }\n          ],\n          \"yaxis\": {\n            \"align\": false,\n            \"alignLevel\": null\n          }\n        },\n        {\n          \"aliasColors\": {},\n          \"bars\": false,\n          \"dashLength\": 10,\n          \"dashes\": false,\n          \"datasource\": \"$datasource\",\n          \"editable\": true,\n          \"error\": false,\n          \"fieldConfig\": {\n            \"defaults\": {\n              \"custom\": {},\n              \"links\": []\n            },\n            \"overrides\": []\n          },\n          \"fill\": 1,\n          \"fillGradient\": 0,\n          \"grid\": {},\n          \"gridPos\": {\n            \"h\": 7,\n            \"w\": 12,\n            \"x\": 0,\n            \"y\": 28\n          },\n          \"hiddenSeries\": false,\n          \"id\": 22,\n          \"legend\": {\n            \"avg\": false,\n            \"current\": false,\n            \"max\": false,\n            \"min\": false,\n            \"show\": true,\n            \"total\": false,\n            \"values\": false\n          },\n          \"lines\": true,\n          \"linewidth\": 2,\n          \"links\": [],\n          \"nullPointMode\": \"connected\",\n          \"options\": {\n            \"alertThreshold\": true\n          },\n          \"percentage\": false,\n          \"pluginVersion\": \"7.2.0\",\n          \"pointradius\": 5,\n          \"points\": false,\n          \"renderer\": \"flot\",\n          \"seriesOverrides\": [],\n          \"spaceLength\": 10,\n          \"stack\": true,\n          \"steppedLine\": false,\n          \"targets\": [\n            {\n              \"expr\": \"sum(coredns_cache_size{instance=~\\\"$instance\\\"}) by (type) or\\nsum(coredns_cache_entries{instance=~\\\"$instance\\\"}) by (type)\",\n              \"interval\": \"\",\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"{{\"{{type}}\"}}\",\n              \"refId\": \"A\",\n              \"step\": 40\n            }\n          ],\n          \"thresholds\": [],\n          \"timeFrom\": null,\n          \"timeRegions\": [],\n          \"timeShift\": null,\n          \"title\": \"Cache (size)\",\n          \"tooltip\": {\n            \"shared\": true,\n            \"sort\": 2,\n            \"value_type\": \"cumulative\"\n          },\n          \"type\": \"graph\",\n          \"xaxis\": {\n            \"buckets\": null,\n            \"mode\": \"time\",\n            \"name\": null,\n            \"show\": true,\n            \"values\": []\n          },\n          \"yaxes\": [\n            {\n              \"format\": \"decbytes\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            },\n            {\n              \"format\": \"short\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            }\n          ],\n          \"yaxis\": {\n            \"align\": false,\n            \"alignLevel\": null\n          }\n        },\n        {\n          \"aliasColors\": {},\n          \"bars\": false,\n          \"dashLength\": 10,\n          \"dashes\": false,\n          \"datasource\": \"$datasource\",\n          \"editable\": true,\n          \"error\": false,\n          \"fieldConfig\": {\n            \"defaults\": {\n              \"custom\": {},\n              \"links\": []\n            },\n            \"overrides\": []\n          },\n          \"fill\": 1,\n          \"fillGradient\": 0,\n          \"grid\": {},\n          \"gridPos\": {\n            \"h\": 7,\n            \"w\": 12,\n            \"x\": 12,\n            \"y\": 28\n          },\n          \"hiddenSeries\": false,\n          \"id\": 24,\n          \"legend\": {\n            \"avg\": false,\n            \"current\": false,\n            \"max\": false,\n            \"min\": false,\n            \"show\": true,\n            \"total\": false,\n            \"values\": false\n          },\n          \"lines\": true,\n          \"linewidth\": 2,\n          \"links\": [],\n          \"nullPointMode\": \"connected\",\n          \"options\": {\n            \"alertThreshold\": true\n          },\n          \"percentage\": false,\n          \"pluginVersion\": \"7.2.0\",\n          \"pointradius\": 5,\n          \"points\": false,\n          \"renderer\": \"flot\",\n          \"seriesOverrides\": [\n            {\n              \"alias\": \"misses\",\n              \"yaxis\": 2\n            }\n          ],\n          \"spaceLength\": 10,\n          \"stack\": true,\n          \"steppedLine\": false,\n          \"targets\": [\n            {\n              \"expr\": \"sum(rate(coredns_cache_hits_total{instance=~\\\"$instance\\\"}[5m])) by (type)\",\n              \"hide\": false,\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"hits:{{\"{{type}}\"}}\",\n              \"refId\": \"A\",\n              \"step\": 40\n            },\n            {\n              \"expr\": \"sum(rate(coredns_cache_misses_total{instance=~\\\"$instance\\\"}[5m])) by (type)\",\n              \"hide\": false,\n              \"intervalFactor\": 2,\n              \"legendFormat\": \"misses\",\n              \"refId\": \"B\",\n              \"step\": 40\n            }\n          ],\n          \"thresholds\": [],\n          \"timeFrom\": null,\n          \"timeRegions\": [],\n          \"timeShift\": null,\n          \"title\": \"Cache (hitrate)\",\n          \"tooltip\": {\n            \"shared\": true,\n            \"sort\": 2,\n            \"value_type\": \"individual\"\n          },\n          \"type\": \"graph\",\n          \"xaxis\": {\n            \"buckets\": null,\n            \"mode\": \"time\",\n            \"name\": null,\n            \"show\": true,\n            \"values\": []\n          },\n          \"yaxes\": [\n            {\n              \"format\": \"pps\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            },\n            {\n              \"format\": \"pps\",\n              \"logBase\": 1,\n              \"max\": null,\n              \"min\": 0,\n              \"show\": true\n            }\n          ],\n          \"yaxis\": {\n            \"align\": false,\n            \"alignLevel\": null\n          }\n        }\n      ],\n      \"refresh\": \"10s\",\n      \"schemaVersion\": 26,\n      \"style\": \"dark\",\n      \"tags\": [\n        \"dns\",\n        \"coredns\"\n      ],\n      \"templating\": {\n        \"list\": [\n          {\n            \"current\": {\n              \"selected\": true,\n              \"text\": \"default\",\n              \"value\": \"default\"\n            },\n            \"hide\": 0,\n            \"includeAll\": false,\n            \"label\": null,\n            \"multi\": false,\n            \"name\": \"datasource\",\n            \"options\": [],\n            \"query\": \"prometheus\",\n            \"queryValue\": \"\",\n            \"refresh\": 1,\n            \"regex\": \"\",\n            \"skipUrlSync\": false,\n            \"type\": \"datasource\"\n          },\n          {\n            \"allValue\": \".*\",\n            \"current\": {\n              \"selected\": true,\n              \"text\": \"All\",\n              \"value\": \"$__all\"\n            },\n            \"datasource\": \"$datasource\",\n            \"definition\": \"label_values(up{job=\\\"coredns\\\"}, instance)\",\n            \"hide\": 0,\n            \"includeAll\": true,\n            \"label\": \"Instance\",\n            \"multi\": false,\n            \"name\": \"instance\",\n            \"options\": [],\n            \"query\": \"label_values(up{job=\\\"coredns\\\"}, instance)\",\n            \"refresh\": 1,\n            \"regex\": \"\",\n            \"skipUrlSync\": false,\n            \"sort\": 3,\n            \"tagValuesQuery\": \"\",\n            \"tags\": [],\n            \"tagsQuery\": \"\",\n            \"type\": \"query\",\n            \"useTags\": false\n          }\n        ]\n      },\n      \"time\": {\n        \"from\": \"now-3h\",\n        \"to\": \"now\"\n      },\n      \"timepicker\": {\n        \"refresh_intervals\": [\n          \"10s\",\n          \"30s\",\n          \"1m\",\n          \"5m\",\n          \"15m\",\n          \"30m\",\n          \"1h\",\n          \"2h\",\n          \"1d\"\n        ]\n      },\n      \"timezone\": \"utc\",\n      \"title\": \"CoreDNS\",\n      \"uid\": \"vkQ0UHxik\",\n      \"version\": 2\n    }\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-cluster.yaml",
    "content": "{{- /*\nGenerated from 'k8s-resources-cluster' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"k8s-resources-cluster\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  k8s-resources-cluster.json: |-\n    {\n        \"annotations\": {\n            \"list\": [\n\n            ]\n        },\n        \"editable\": true,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"links\": [\n\n        ],\n        \"refresh\": \"10s\",\n        \"rows\": [\n            {\n                \"collapse\": false,\n                \"height\": \"100px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"format\": \"percentunit\",\n                        \"id\": 1,\n                        \"interval\": \"1m\",\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 2,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"1 - avg(rate(node_cpu_seconds_total{mode=\\\"idle\\\", cluster=\\\"$cluster\\\"}[$__rate_interval]))\",\n                                \"format\": \"time_series\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"70,80\",\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Utilisation\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"singlestat\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"format\": \"percentunit\",\n                        \"id\": 2,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 2,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(namespace_cpu:kube_pod_container_resource_requests:sum{cluster=\\\"$cluster\\\"}) / sum(kube_node_status_allocatable{resource=\\\"cpu\\\",cluster=\\\"$cluster\\\"})\",\n                                \"format\": \"time_series\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"70,80\",\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Requests Commitment\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"singlestat\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"format\": \"percentunit\",\n                        \"id\": 3,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 2,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(namespace_cpu:kube_pod_container_resource_limits:sum{cluster=\\\"$cluster\\\"}) / sum(kube_node_status_allocatable{resource=\\\"cpu\\\",cluster=\\\"$cluster\\\"})\",\n                                \"format\": \"time_series\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"70,80\",\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Limits Commitment\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"singlestat\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"format\": \"percentunit\",\n                        \"id\": 4,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 2,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"1 - sum(:node_memory_MemAvailable_bytes:sum{cluster=\\\"$cluster\\\"}) / sum(node_memory_MemTotal_bytes{cluster=\\\"$cluster\\\"})\",\n                                \"format\": \"time_series\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"70,80\",\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Utilisation\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"singlestat\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"format\": \"percentunit\",\n                        \"id\": 5,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 2,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(namespace_memory:kube_pod_container_resource_requests:sum{cluster=\\\"$cluster\\\"}) / sum(kube_node_status_allocatable{resource=\\\"memory\\\",cluster=\\\"$cluster\\\"})\",\n                                \"format\": \"time_series\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"70,80\",\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Requests Commitment\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"singlestat\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"format\": \"percentunit\",\n                        \"id\": 6,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 2,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(namespace_memory:kube_pod_container_resource_limits:sum{cluster=\\\"$cluster\\\"}) / sum(kube_node_status_allocatable{resource=\\\"memory\\\",cluster=\\\"$cluster\\\"})\",\n                                \"format\": \"time_series\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"70,80\",\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Limits Commitment\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"singlestat\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Headlines\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 7,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\"}) by (namespace)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Usage\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"CPU\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 8,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"styles\": [\n                            {\n                                \"alias\": \"Time\",\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"pattern\": \"Time\",\n                                \"type\": \"hidden\"\n                            },\n                            {\n                                \"alias\": \"Pods\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 0,\n                                \"link\": true,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down to pods\",\n                                \"linkUrl\": \"./d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1\",\n                                \"pattern\": \"Value #A\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"Workloads\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 0,\n                                \"link\": true,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down to workloads\",\n                                \"linkUrl\": \"./d/a87fb0d919ec0ea5f6543124e16c42a5/k8s-resources-workloads-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1\",\n                                \"pattern\": \"Value #B\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"CPU Usage\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #C\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"CPU Requests\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #D\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"CPU Requests %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #E\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"CPU Limits\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #F\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"CPU Limits %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #G\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"Namespace\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": true,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down to pods\",\n                                \"linkUrl\": \"./d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell\",\n                                \"pattern\": \"namespace\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"pattern\": \"/.*/\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"string\",\n                                \"unit\": \"short\"\n                            }\n                        ],\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(kube_pod_owner{cluster=\\\"$cluster\\\"}) by (namespace)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"count(avg(namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\"}) by (workload, namespace)) by (namespace)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"B\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\"}) by (namespace)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"C\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(namespace_cpu:kube_pod_container_resource_requests:sum{cluster=\\\"$cluster\\\"}) by (namespace)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"D\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\"}) by (namespace) / sum(namespace_cpu:kube_pod_container_resource_requests:sum{cluster=\\\"$cluster\\\"}) by (namespace)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"E\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(namespace_cpu:kube_pod_container_resource_limits:sum{cluster=\\\"$cluster\\\"}) by (namespace)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"F\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\"}) by (namespace) / sum(namespace_cpu:kube_pod_container_resource_limits:sum{cluster=\\\"$cluster\\\"}) by (namespace)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"G\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Quota\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"transform\": \"table\",\n                        \"type\": \"table\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"CPU Quota\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 9,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(container_memory_rss{cluster=\\\"$cluster\\\", container!=\\\"\\\"}) by (namespace)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Usage (w/o cache)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Memory\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 10,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"styles\": [\n                            {\n                                \"alias\": \"Time\",\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"pattern\": \"Time\",\n                                \"type\": \"hidden\"\n                            },\n                            {\n                                \"alias\": \"Pods\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 0,\n                                \"link\": true,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down to pods\",\n                                \"linkUrl\": \"./d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1\",\n                                \"pattern\": \"Value #A\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"Workloads\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 0,\n                                \"link\": true,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down to workloads\",\n                                \"linkUrl\": \"./d/a87fb0d919ec0ea5f6543124e16c42a5/k8s-resources-workloads-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1\",\n                                \"pattern\": \"Value #B\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"Memory Usage\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #C\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Requests\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #D\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Requests %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #E\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"Memory Limits\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #F\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Limits %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #G\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"Namespace\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": true,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down to pods\",\n                                \"linkUrl\": \"./d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell\",\n                                \"pattern\": \"namespace\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"pattern\": \"/.*/\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"string\",\n                                \"unit\": \"short\"\n                            }\n                        ],\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(kube_pod_owner{cluster=\\\"$cluster\\\"}) by (namespace)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"count(avg(namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\"}) by (workload, namespace)) by (namespace)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"B\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(container_memory_rss{cluster=\\\"$cluster\\\", container!=\\\"\\\"}) by (namespace)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"C\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(namespace_memory:kube_pod_container_resource_requests:sum{cluster=\\\"$cluster\\\"}) by (namespace)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"D\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(container_memory_rss{cluster=\\\"$cluster\\\", container!=\\\"\\\"}) by (namespace) / sum(namespace_memory:kube_pod_container_resource_requests:sum{cluster=\\\"$cluster\\\"}) by (namespace)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"E\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(namespace_memory:kube_pod_container_resource_limits:sum{cluster=\\\"$cluster\\\"}) by (namespace)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"F\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(container_memory_rss{cluster=\\\"$cluster\\\", container!=\\\"\\\"}) by (namespace) / sum(namespace_memory:kube_pod_container_resource_limits:sum{cluster=\\\"$cluster\\\"}) by (namespace)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"G\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Requests by Namespace\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"transform\": \"table\",\n                        \"type\": \"table\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Memory Requests\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 11,\n                        \"interval\": \"1m\",\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"styles\": [\n                            {\n                                \"alias\": \"Time\",\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"pattern\": \"Time\",\n                                \"type\": \"hidden\"\n                            },\n                            {\n                                \"alias\": \"Current Receive Bandwidth\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #A\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"Bps\"\n                            },\n                            {\n                                \"alias\": \"Current Transmit Bandwidth\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #B\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"Bps\"\n                            },\n                            {\n                                \"alias\": \"Rate of Received Packets\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #C\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"pps\"\n                            },\n                            {\n                                \"alias\": \"Rate of Transmitted Packets\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #D\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"pps\"\n                            },\n                            {\n                                \"alias\": \"Rate of Received Packets Dropped\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #E\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"pps\"\n                            },\n                            {\n                                \"alias\": \"Rate of Transmitted Packets Dropped\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #F\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"pps\"\n                            },\n                            {\n                                \"alias\": \"Namespace\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": true,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down to pods\",\n                                \"linkUrl\": \"./d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell\",\n                                \"pattern\": \"namespace\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"pattern\": \"/.*/\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"string\",\n                                \"unit\": \"short\"\n                            }\n                        ],\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\".+\\\"}[$__rate_interval])) by (namespace)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\".+\\\"}[$__rate_interval])) by (namespace)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"B\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(irate(container_network_receive_packets_total{cluster=\\\"$cluster\\\", namespace=~\\\".+\\\"}[$__rate_interval])) by (namespace)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"C\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(irate(container_network_transmit_packets_total{cluster=\\\"$cluster\\\", namespace=~\\\".+\\\"}[$__rate_interval])) by (namespace)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"D\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(irate(container_network_receive_packets_dropped_total{cluster=\\\"$cluster\\\", namespace=~\\\".+\\\"}[$__rate_interval])) by (namespace)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"E\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(irate(container_network_transmit_packets_dropped_total{cluster=\\\"$cluster\\\", namespace=~\\\".+\\\"}[$__rate_interval])) by (namespace)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"F\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Current Network Usage\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"transform\": \"table\",\n                        \"type\": \"table\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Current Network Usage\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 12,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\".+\\\"}[$__rate_interval])) by (namespace)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Receive Bandwidth\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 13,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\".+\\\"}[$__rate_interval])) by (namespace)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Transmit Bandwidth\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Bandwidth\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 14,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"avg(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\".+\\\"}[$__rate_interval])) by (namespace)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Average Container Bandwidth by Namespace: Received\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 15,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"avg(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\".+\\\"}[$__rate_interval])) by (namespace)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Average Container Bandwidth by Namespace: Transmitted\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Average Container Bandwidth by Namespace\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 16,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_receive_packets_total{cluster=\\\"$cluster\\\", namespace=~\\\".+\\\"}[$__rate_interval])) by (namespace)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Received Packets\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 17,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_transmit_packets_total{cluster=\\\"$cluster\\\", namespace=~\\\".+\\\"}[$__rate_interval])) by (namespace)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Transmitted Packets\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Rate of Packets\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 18,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_receive_packets_dropped_total{cluster=\\\"$cluster\\\", namespace=~\\\".+\\\"}[$__rate_interval])) by (namespace)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Received Packets Dropped\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 19,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_transmit_packets_dropped_total{cluster=\\\"$cluster\\\", namespace=~\\\".+\\\"}[$__rate_interval])) by (namespace)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Transmitted Packets Dropped\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Rate of Packets Dropped\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"decimals\": -1,\n                        \"fill\": 10,\n                        \"id\": 20,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"ceil(sum by(namespace) (rate(container_fs_reads_total{container!=\\\"\\\", cluster=\\\"$cluster\\\"}[5m]) + rate(container_fs_writes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\"}[5m])))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"IOPS(Reads+Writes)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 21,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum by(namespace) (rate(container_fs_reads_bytes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\"}[5m]) + rate(container_fs_writes_bytes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}namespace{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"ThroughPut(Read+Write)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Storage IO\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 22,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"sort\": {\n                            \"col\": 4,\n                            \"desc\": true\n                        },\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"styles\": [\n                            {\n                                \"alias\": \"Time\",\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"pattern\": \"Time\",\n                                \"type\": \"hidden\"\n                            },\n                            {\n                                \"alias\": \"IOPS(Reads)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": -1,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #A\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"IOPS(Writes)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": -1,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #B\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"IOPS(Reads + Writes)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": -1,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #C\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"Throughput(Read)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #D\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"Bps\"\n                            },\n                            {\n                                \"alias\": \"Throughput(Write)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #E\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"Bps\"\n                            },\n                            {\n                                \"alias\": \"Throughput(Read + Write)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #F\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"Bps\"\n                            },\n                            {\n                                \"alias\": \"Namespace\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": true,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down to pods\",\n                                \"linkUrl\": \"./d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell\",\n                                \"pattern\": \"namespace\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"pattern\": \"/.*/\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"string\",\n                                \"unit\": \"short\"\n                            }\n                        ],\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum by(namespace) (rate(container_fs_reads_total{container!=\\\"\\\", cluster=\\\"$cluster\\\"}[5m]))\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum by(namespace) (rate(container_fs_writes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\"}[5m]))\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"B\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum by(namespace) (rate(container_fs_reads_total{container!=\\\"\\\", cluster=\\\"$cluster\\\"}[5m]) + rate(container_fs_writes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\"}[5m]))\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"C\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum by(namespace) (rate(container_fs_reads_bytes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\"}[5m]))\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"D\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum by(namespace) (rate(container_fs_writes_bytes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\"}[5m]))\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"E\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum by(namespace) (rate(container_fs_reads_bytes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\"}[5m]) + rate(container_fs_writes_bytes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\"}[5m]))\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"F\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Current Storage IO\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"transform\": \"table\",\n                        \"type\": \"table\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Storage IO - Distribution\",\n                \"titleSize\": \"h6\"\n            }\n        ],\n        \"schemaVersion\": 14,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"kubernetes-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": \"\",\n                        \"value\": \"\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }},\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"cluster\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(node_cpu_seconds_total, cluster)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"UTC\",\n        \"title\": \"Kubernetes / Compute Resources / Cluster\",\n        \"uid\": \"efa86fd1d0c121a26444b636a3f509a8\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-namespace.yaml",
    "content": "{{- /*\nGenerated from 'k8s-resources-namespace' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"k8s-resources-namespace\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  k8s-resources-namespace.json: |-\n    {\n        \"annotations\": {\n            \"list\": [\n\n            ]\n        },\n        \"editable\": true,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"links\": [\n\n        ],\n        \"refresh\": \"10s\",\n        \"rows\": [\n            {\n                \"collapse\": false,\n                \"height\": \"100px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"format\": \"percentunit\",\n                        \"id\": 1,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 3,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}) / sum(kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", resource=\\\"cpu\\\"})\",\n                                \"format\": \"time_series\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"70,80\",\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Utilisation (from requests)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"singlestat\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"format\": \"percentunit\",\n                        \"id\": 2,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 3,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}) / sum(kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", resource=\\\"cpu\\\"})\",\n                                \"format\": \"time_series\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"70,80\",\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Utilisation (from limits)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"singlestat\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"format\": \"percentunit\",\n                        \"id\": 3,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 3,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(container_memory_working_set_bytes{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\",container!=\\\"\\\", image!=\\\"\\\"}) / sum(kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", resource=\\\"memory\\\"})\",\n                                \"format\": \"time_series\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"70,80\",\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Utilisation (from requests)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"singlestat\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"format\": \"percentunit\",\n                        \"id\": 4,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 3,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(container_memory_working_set_bytes{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\",container!=\\\"\\\", image!=\\\"\\\"}) / sum(kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", resource=\\\"memory\\\"})\",\n                                \"format\": \"time_series\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"70,80\",\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Utilisation (from limits)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"singlestat\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Headlines\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 5,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n                            {\n                                \"alias\": \"quota - requests\",\n                                \"color\": \"#F2495C\",\n                                \"dashes\": true,\n                                \"fill\": 0,\n                                \"hiddenSeries\": true,\n                                \"hideTooltip\": true,\n                                \"legend\": true,\n                                \"linewidth\": 2,\n                                \"stack\": false\n                            },\n                            {\n                                \"alias\": \"quota - limits\",\n                                \"color\": \"#FF9830\",\n                                \"dashes\": true,\n                                \"fill\": 0,\n                                \"hiddenSeries\": true,\n                                \"hideTooltip\": true,\n                                \"legend\": true,\n                                \"linewidth\": 2,\n                                \"stack\": false\n                            }\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"scalar(kube_resourcequota{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", type=\\\"hard\\\",resource=\\\"requests.cpu\\\"})\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"quota - requests\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"scalar(kube_resourcequota{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", type=\\\"hard\\\",resource=\\\"limits.cpu\\\"})\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"quota - limits\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Usage\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"CPU Usage\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 6,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"styles\": [\n                            {\n                                \"alias\": \"Time\",\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"pattern\": \"Time\",\n                                \"type\": \"hidden\"\n                            },\n                            {\n                                \"alias\": \"CPU Usage\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #A\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"CPU Requests\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #B\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"CPU Requests %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #C\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"CPU Limits\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #D\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"CPU Limits %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #E\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"Pod\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": true,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"./d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell\",\n                                \"pattern\": \"pod\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"pattern\": \"/.*/\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"string\",\n                                \"unit\": \"short\"\n                            }\n                        ],\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"B\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}) by (pod) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"C\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"D\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}) by (pod) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"E\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Quota\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"transform\": \"table\",\n                        \"type\": \"table\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"CPU Quota\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 7,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n                            {\n                                \"alias\": \"quota - requests\",\n                                \"color\": \"#F2495C\",\n                                \"dashes\": true,\n                                \"fill\": 0,\n                                \"hiddenSeries\": true,\n                                \"hideTooltip\": true,\n                                \"legend\": true,\n                                \"linewidth\": 2,\n                                \"stack\": false\n                            },\n                            {\n                                \"alias\": \"quota - limits\",\n                                \"color\": \"#FF9830\",\n                                \"dashes\": true,\n                                \"fill\": 0,\n                                \"hiddenSeries\": true,\n                                \"hideTooltip\": true,\n                                \"legend\": true,\n                                \"linewidth\": 2,\n                                \"stack\": false\n                            }\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(container_memory_working_set_bytes{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", container!=\\\"\\\", image!=\\\"\\\"}) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"scalar(kube_resourcequota{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", type=\\\"hard\\\",resource=\\\"requests.memory\\\"})\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"quota - requests\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"scalar(kube_resourcequota{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", type=\\\"hard\\\",resource=\\\"limits.memory\\\"})\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"quota - limits\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Usage (w/o cache)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Memory Usage\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 8,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"styles\": [\n                            {\n                                \"alias\": \"Time\",\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"pattern\": \"Time\",\n                                \"type\": \"hidden\"\n                            },\n                            {\n                                \"alias\": \"Memory Usage\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #A\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Requests\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #B\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Requests %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #C\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"Memory Limits\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #D\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Limits %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #E\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"Memory Usage (RSS)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #F\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Usage (Cache)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #G\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Usage (Swap)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #H\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Pod\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": true,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"./d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell\",\n                                \"pattern\": \"pod\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"pattern\": \"/.*/\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"string\",\n                                \"unit\": \"short\"\n                            }\n                        ],\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(container_memory_working_set_bytes{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\",container!=\\\"\\\", image!=\\\"\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"B\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(container_memory_working_set_bytes{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\",container!=\\\"\\\", image!=\\\"\\\"}) by (pod) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"C\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"D\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(container_memory_working_set_bytes{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\",container!=\\\"\\\", image!=\\\"\\\"}) by (pod) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"E\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(container_memory_rss{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\",container!=\\\"\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"F\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(container_memory_cache{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\",container!=\\\"\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"G\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(container_memory_swap{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\",container!=\\\"\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"H\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Quota\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"transform\": \"table\",\n                        \"type\": \"table\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Memory Quota\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 9,\n                        \"interval\": \"1m\",\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"styles\": [\n                            {\n                                \"alias\": \"Time\",\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"pattern\": \"Time\",\n                                \"type\": \"hidden\"\n                            },\n                            {\n                                \"alias\": \"Current Receive Bandwidth\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #A\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"Bps\"\n                            },\n                            {\n                                \"alias\": \"Current Transmit Bandwidth\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #B\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"Bps\"\n                            },\n                            {\n                                \"alias\": \"Rate of Received Packets\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #C\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"pps\"\n                            },\n                            {\n                                \"alias\": \"Rate of Transmitted Packets\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #D\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"pps\"\n                            },\n                            {\n                                \"alias\": \"Rate of Received Packets Dropped\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #E\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"pps\"\n                            },\n                            {\n                                \"alias\": \"Rate of Transmitted Packets Dropped\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #F\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"pps\"\n                            },\n                            {\n                                \"alias\": \"Pod\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": true,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down to pods\",\n                                \"linkUrl\": \"./d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell\",\n                                \"pattern\": \"pod\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"pattern\": \"/.*/\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"string\",\n                                \"unit\": \"short\"\n                            }\n                        ],\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"B\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(irate(container_network_receive_packets_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"C\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(irate(container_network_transmit_packets_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"D\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(irate(container_network_receive_packets_dropped_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"E\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(irate(container_network_transmit_packets_dropped_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"F\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Current Network Usage\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"transform\": \"table\",\n                        \"type\": \"table\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Current Network Usage\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 10,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Receive Bandwidth\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 11,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Transmit Bandwidth\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Bandwidth\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 12,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_receive_packets_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Received Packets\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 13,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_transmit_packets_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Transmitted Packets\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Rate of Packets\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 14,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_receive_packets_dropped_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Received Packets Dropped\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 15,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_transmit_packets_dropped_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Transmitted Packets Dropped\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Rate of Packets Dropped\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"decimals\": -1,\n                        \"fill\": 10,\n                        \"id\": 16,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"ceil(sum by(pod) (rate(container_fs_reads_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[5m]) + rate(container_fs_writes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[5m])))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"IOPS(Reads+Writes)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 17,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum by(pod) (rate(container_fs_reads_bytes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[5m]) + rate(container_fs_writes_bytes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"ThroughPut(Read+Write)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Storage IO\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 18,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"sort\": {\n                            \"col\": 4,\n                            \"desc\": true\n                        },\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"styles\": [\n                            {\n                                \"alias\": \"Time\",\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"pattern\": \"Time\",\n                                \"type\": \"hidden\"\n                            },\n                            {\n                                \"alias\": \"IOPS(Reads)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": -1,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #A\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"IOPS(Writes)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": -1,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #B\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"IOPS(Reads + Writes)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": -1,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #C\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"Throughput(Read)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #D\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"Bps\"\n                            },\n                            {\n                                \"alias\": \"Throughput(Write)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #E\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"Bps\"\n                            },\n                            {\n                                \"alias\": \"Throughput(Read + Write)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #F\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"Bps\"\n                            },\n                            {\n                                \"alias\": \"Pod\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": true,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down to pods\",\n                                \"linkUrl\": \"./d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell\",\n                                \"pattern\": \"pod\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"pattern\": \"/.*/\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"string\",\n                                \"unit\": \"short\"\n                            }\n                        ],\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum by(pod) (rate(container_fs_reads_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[5m]))\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum by(pod) (rate(container_fs_writes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[5m]))\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"B\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum by(pod) (rate(container_fs_reads_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[5m]) + rate(container_fs_writes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[5m]))\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"C\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum by(pod) (rate(container_fs_reads_bytes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[5m]))\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"D\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum by(pod) (rate(container_fs_writes_bytes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[5m]))\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"E\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum by(pod) (rate(container_fs_reads_bytes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[5m]) + rate(container_fs_writes_bytes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[5m]))\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"F\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Current Storage IO\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"transform\": \"table\",\n                        \"type\": \"table\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Storage IO - Distribution\",\n                \"titleSize\": \"h6\"\n            }\n        ],\n        \"schemaVersion\": 14,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"kubernetes-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": \"\",\n                        \"value\": \"\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }},\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"cluster\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_info, cluster)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": \"\",\n                        \"value\": \"\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"namespace\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_info{cluster=\\\"$cluster\\\"}, namespace)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"UTC\",\n        \"title\": \"Kubernetes / Compute Resources / Namespace (Pods)\",\n        \"uid\": \"85a562078cdf77779eaa1add43ccec1e\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-node.yaml",
    "content": "{{- /*\nGenerated from 'k8s-resources-node' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"k8s-resources-node\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  k8s-resources-node.json: |-\n    {\n        \"annotations\": {\n            \"list\": [\n\n            ]\n        },\n        \"editable\": true,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"links\": [\n\n        ],\n        \"refresh\": \"10s\",\n        \"rows\": [\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 1,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", node=~\\\"$node\\\"}) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Usage\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"CPU Usage\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 2,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"styles\": [\n                            {\n                                \"alias\": \"Time\",\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"pattern\": \"Time\",\n                                \"type\": \"hidden\"\n                            },\n                            {\n                                \"alias\": \"CPU Usage\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #A\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"CPU Requests\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #B\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"CPU Requests %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #C\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"CPU Limits\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #D\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"CPU Limits %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #E\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"Pod\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"pod\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"pattern\": \"/.*/\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"string\",\n                                \"unit\": \"short\"\n                            }\n                        ],\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", node=~\\\"$node\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", node=~\\\"$node\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"B\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", node=~\\\"$node\\\"}) by (pod) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", node=~\\\"$node\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"C\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", node=~\\\"$node\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"D\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", node=~\\\"$node\\\"}) by (pod) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", node=~\\\"$node\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"E\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Quota\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"transform\": \"table\",\n                        \"type\": \"table\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"CPU Quota\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 3,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_memory_working_set_bytes{cluster=\\\"$cluster\\\", node=~\\\"$node\\\", container!=\\\"\\\"}) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Usage (w/o cache)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Memory Usage\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 4,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"styles\": [\n                            {\n                                \"alias\": \"Time\",\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"pattern\": \"Time\",\n                                \"type\": \"hidden\"\n                            },\n                            {\n                                \"alias\": \"Memory Usage\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #A\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Requests\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #B\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Requests %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #C\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"Memory Limits\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #D\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Limits %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #E\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"Memory Usage (RSS)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #F\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Usage (Cache)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #G\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Usage (Swap)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #H\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Pod\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"pod\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"pattern\": \"/.*/\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"string\",\n                                \"unit\": \"short\"\n                            }\n                        ],\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_memory_working_set_bytes{cluster=\\\"$cluster\\\", node=~\\\"$node\\\",container!=\\\"\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", node=~\\\"$node\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"B\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_memory_working_set_bytes{cluster=\\\"$cluster\\\", node=~\\\"$node\\\",container!=\\\"\\\"}) by (pod) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", node=~\\\"$node\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"C\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", node=~\\\"$node\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"D\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_memory_working_set_bytes{cluster=\\\"$cluster\\\", node=~\\\"$node\\\",container!=\\\"\\\"}) by (pod) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", node=~\\\"$node\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"E\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_memory_rss{cluster=\\\"$cluster\\\", node=~\\\"$node\\\",container!=\\\"\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"F\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_memory_cache{cluster=\\\"$cluster\\\", node=~\\\"$node\\\",container!=\\\"\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"G\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_memory_swap{cluster=\\\"$cluster\\\", node=~\\\"$node\\\",container!=\\\"\\\"}) by (pod)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"H\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Quota\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"transform\": \"table\",\n                        \"type\": \"table\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Memory Quota\",\n                \"titleSize\": \"h6\"\n            }\n        ],\n        \"schemaVersion\": 14,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"kubernetes-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": \"\",\n                        \"value\": \"\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }},\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"cluster\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_info, cluster)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": \"\",\n                        \"value\": \"\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": true,\n                    \"name\": \"node\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_info{cluster=\\\"$cluster\\\"}, node)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"UTC\",\n        \"title\": \"Kubernetes / Compute Resources / Node (Pods)\",\n        \"uid\": \"200ac8fdbfbb74b39aff88118e4d1c2c\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-pod.yaml",
    "content": "{{- /*\nGenerated from 'k8s-resources-pod' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"k8s-resources-pod\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  k8s-resources-pod.json: |-\n    {\n        \"annotations\": {\n            \"list\": [\n\n            ]\n        },\n        \"editable\": true,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"links\": [\n\n        ],\n        \"refresh\": \"10s\",\n        \"rows\": [\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 1,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n                            {\n                                \"alias\": \"requests\",\n                                \"color\": \"#F2495C\",\n                                \"fill\": 0,\n                                \"hideTooltip\": true,\n                                \"legend\": true,\n                                \"linewidth\": 2,\n                                \"stack\": false\n                            },\n                            {\n                                \"alias\": \"limits\",\n                                \"color\": \"#FF9830\",\n                                \"fill\": 0,\n                                \"hideTooltip\": true,\n                                \"legend\": true,\n                                \"linewidth\": 2,\n                                \"stack\": false\n                            }\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\\\"$namespace\\\", pod=\\\"$pod\\\", cluster=\\\"$cluster\\\"}) by (container)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}container{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n    kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\", resource=\\\"cpu\\\"}\\n)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"requests\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n    kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\", resource=\\\"cpu\\\"}\\n)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"limits\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Usage\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"CPU Usage\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 2,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": true,\n                            \"max\": true,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(increase(container_cpu_cfs_throttled_periods_total{namespace=\\\"$namespace\\\", pod=\\\"$pod\\\", container!=\\\"\\\", cluster=\\\"$cluster\\\"}[5m])) by (container) /sum(increase(container_cpu_cfs_periods_total{namespace=\\\"$namespace\\\", pod=\\\"$pod\\\", container!=\\\"\\\", cluster=\\\"$cluster\\\"}[5m])) by (container)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}container{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n                            {\n                                \"colorMode\": \"critical\",\n                                \"fill\": true,\n                                \"line\": true,\n                                \"op\": \"gt\",\n                                \"value\": 0.25,\n                                \"yaxis\": \"left\"\n                            }\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Throttling\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": 1,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"CPU Throttling\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 3,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"styles\": [\n                            {\n                                \"alias\": \"Time\",\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"pattern\": \"Time\",\n                                \"type\": \"hidden\"\n                            },\n                            {\n                                \"alias\": \"CPU Usage\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #A\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"CPU Requests\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #B\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"CPU Requests %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #C\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"CPU Limits\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #D\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"CPU Limits %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #E\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"Container\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"container\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"pattern\": \"/.*/\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"string\",\n                                \"unit\": \"short\"\n                            }\n                        ],\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\"}) by (container)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\"}) by (container)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"B\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\"}) by (container) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\"}) by (container)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"C\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\"}) by (container)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"D\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\"}) by (container) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\"}) by (container)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"E\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Quota\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"transform\": \"table\",\n                        \"type\": \"table\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"CPU Quota\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 4,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n                            {\n                                \"alias\": \"requests\",\n                                \"color\": \"#F2495C\",\n                                \"dashes\": true,\n                                \"fill\": 0,\n                                \"hideTooltip\": true,\n                                \"legend\": true,\n                                \"linewidth\": 2,\n                                \"stack\": false\n                            },\n                            {\n                                \"alias\": \"limits\",\n                                \"color\": \"#FF9830\",\n                                \"dashes\": true,\n                                \"fill\": 0,\n                                \"hideTooltip\": true,\n                                \"legend\": true,\n                                \"linewidth\": 2,\n                                \"stack\": false\n                            }\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(container_memory_working_set_bytes{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\", container!=\\\"\\\", image!=\\\"\\\"}) by (container)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}container{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n    kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\", resource=\\\"memory\\\"}\\n)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"requests\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n    kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\", resource=\\\"memory\\\"}\\n)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"limits\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Usage (WSS)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Memory Usage\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 5,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"styles\": [\n                            {\n                                \"alias\": \"Time\",\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"pattern\": \"Time\",\n                                \"type\": \"hidden\"\n                            },\n                            {\n                                \"alias\": \"Memory Usage (WSS)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #A\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Requests\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #B\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Requests %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #C\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"Memory Limits\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #D\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Limits %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #E\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"Memory Usage (RSS)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #F\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Usage (Cache)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #G\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Usage (Swap)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #H\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Container\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"container\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"pattern\": \"/.*/\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"string\",\n                                \"unit\": \"short\"\n                            }\n                        ],\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(container_memory_working_set_bytes{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\", container!=\\\"\\\", image!=\\\"\\\"}) by (container)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\"}) by (container)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"B\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(container_memory_working_set_bytes{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\", image!=\\\"\\\"}) by (container) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\"}) by (container)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"C\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\"}) by (container)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"D\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(container_memory_working_set_bytes{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\", container!=\\\"\\\", image!=\\\"\\\"}) by (container) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\"}) by (container)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"E\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(container_memory_rss{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\", container != \\\"\\\", container != \\\"POD\\\"}) by (container)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"F\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(container_memory_cache{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\", container != \\\"\\\", container != \\\"POD\\\"}) by (container)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"G\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(container_memory_swap{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=\\\"$pod\\\", container != \\\"\\\", container != \\\"POD\\\"}) by (container)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"H\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Quota\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"transform\": \"table\",\n                        \"type\": \"table\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Memory Quota\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 6,\n                        \"interval\": \"1m\",\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", pod=~\\\"$pod\\\"}[$__rate_interval])) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Receive Bandwidth\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 7,\n                        \"interval\": \"1m\",\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", pod=~\\\"$pod\\\"}[$__rate_interval])) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Transmit Bandwidth\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Bandwidth\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 8,\n                        \"interval\": \"1m\",\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_receive_packets_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", pod=~\\\"$pod\\\"}[$__rate_interval])) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Received Packets\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 9,\n                        \"interval\": \"1m\",\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_transmit_packets_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", pod=~\\\"$pod\\\"}[$__rate_interval])) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Transmitted Packets\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Rate of Packets\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 10,\n                        \"interval\": \"1m\",\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_receive_packets_dropped_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", pod=~\\\"$pod\\\"}[$__rate_interval])) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Received Packets Dropped\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 11,\n                        \"interval\": \"1m\",\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_transmit_packets_dropped_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", pod=~\\\"$pod\\\"}[$__rate_interval])) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Transmitted Packets Dropped\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Rate of Packets Dropped\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"decimals\": -1,\n                        \"fill\": 10,\n                        \"id\": 12,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"ceil(sum by(pod) (rate(container_fs_reads_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=~\\\"$pod\\\"}[5m])))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"Reads\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"ceil(sum by(pod) (rate(container_fs_writes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=~\\\"$pod\\\"}[5m])))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"Writes\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"IOPS\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 13,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum by(pod) (rate(container_fs_reads_bytes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=~\\\"$pod\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"Reads\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum by(pod) (rate(container_fs_writes_bytes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=~\\\"$pod\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"Writes\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"ThroughPut\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Storage IO - Distribution(Pod - Read & Writes)\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"decimals\": -1,\n                        \"fill\": 10,\n                        \"id\": 14,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"ceil(sum by(container) (rate(container_fs_reads_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=\\\"$pod\\\"}[5m]) + rate(container_fs_writes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=\\\"$pod\\\"}[5m])))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}container{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"IOPS(Reads+Writes)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 15,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum by(container) (rate(container_fs_reads_bytes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=\\\"$pod\\\"}[5m]) + rate(container_fs_writes_bytes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=\\\"$pod\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}container{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"ThroughPut(Read+Write)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Storage IO - Distribution(Containers)\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 16,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"sort\": {\n                            \"col\": 4,\n                            \"desc\": true\n                        },\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"styles\": [\n                            {\n                                \"alias\": \"Time\",\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"pattern\": \"Time\",\n                                \"type\": \"hidden\"\n                            },\n                            {\n                                \"alias\": \"IOPS(Reads)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": -1,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #A\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"IOPS(Writes)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": -1,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #B\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"IOPS(Reads + Writes)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": -1,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #C\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"Throughput(Read)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #D\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"Bps\"\n                            },\n                            {\n                                \"alias\": \"Throughput(Write)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #E\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"Bps\"\n                            },\n                            {\n                                \"alias\": \"Throughput(Read + Write)\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #F\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"Bps\"\n                            },\n                            {\n                                \"alias\": \"Container\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"container\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"pattern\": \"/.*/\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"string\",\n                                \"unit\": \"short\"\n                            }\n                        ],\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum by(container) (rate(container_fs_reads_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=\\\"$pod\\\"}[5m]))\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum by(container) (rate(container_fs_writes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=\\\"$pod\\\"}[5m]))\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"B\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum by(container) (rate(container_fs_reads_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=\\\"$pod\\\"}[5m]) + rate(container_fs_writes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=\\\"$pod\\\"}[5m]))\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"C\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum by(container) (rate(container_fs_reads_bytes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=\\\"$pod\\\"}[5m]))\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"D\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum by(container) (rate(container_fs_writes_bytes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=\\\"$pod\\\"}[5m]))\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"E\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum by(container) (rate(container_fs_reads_bytes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=\\\"$pod\\\"}[5m]) + rate(container_fs_writes_bytes_total{container!=\\\"\\\", cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=\\\"$pod\\\"}[5m]))\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"F\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Current Storage IO\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"transform\": \"table\",\n                        \"type\": \"table\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Storage IO - Distribution\",\n                \"titleSize\": \"h6\"\n            }\n        ],\n        \"schemaVersion\": 14,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"kubernetes-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": \"\",\n                        \"value\": \"\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }},\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"cluster\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_info, cluster)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": \"\",\n                        \"value\": \"\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"namespace\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_info{cluster=\\\"$cluster\\\"}, namespace)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": \"\",\n                        \"value\": \"\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"pod\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_info{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}, pod)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"UTC\",\n        \"title\": \"Kubernetes / Compute Resources / Pod\",\n        \"uid\": \"6581e46e4e5c7ba40a07646395ef7b23\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-workload.yaml",
    "content": "{{- /*\nGenerated from 'k8s-resources-workload' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"k8s-resources-workload\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  k8s-resources-workload.json: |-\n    {\n        \"annotations\": {\n            \"list\": [\n\n            ]\n        },\n        \"editable\": true,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"links\": [\n\n        ],\n        \"refresh\": \"10s\",\n        \"rows\": [\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 1,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(\\n    node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}\\n  * on(namespace,pod)\\n    group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload=\\\"$workload\\\", workload_type=\\\"$type\\\"}\\n) by (pod)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Usage\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"CPU Usage\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 2,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"styles\": [\n                            {\n                                \"alias\": \"Time\",\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"pattern\": \"Time\",\n                                \"type\": \"hidden\"\n                            },\n                            {\n                                \"alias\": \"CPU Usage\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #A\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"CPU Requests\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #B\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"CPU Requests %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #C\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"CPU Limits\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #D\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"CPU Limits %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #E\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"Pod\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": true,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"./d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell\",\n                                \"pattern\": \"pod\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"pattern\": \"/.*/\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"string\",\n                                \"unit\": \"short\"\n                            }\n                        ],\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(\\n    node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}\\n  * on(namespace,pod)\\n    group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload=\\\"$workload\\\", workload_type=\\\"$type\\\"}\\n) by (pod)\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n    kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", resource=\\\"cpu\\\"}\\n  * on(namespace,pod)\\n    group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload=\\\"$workload\\\", workload_type=\\\"$type\\\"}\\n) by (pod)\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"B\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n    node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}\\n  * on(namespace,pod)\\n    group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload=\\\"$workload\\\", workload_type=\\\"$type\\\"}\\n) by (pod)\\n/sum(\\n    kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", resource=\\\"cpu\\\"}\\n  * on(namespace,pod)\\n    group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload=\\\"$workload\\\", workload_type=\\\"$type\\\"}\\n) by (pod)\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"C\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n    kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", resource=\\\"cpu\\\"}\\n  * on(namespace,pod)\\n    group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload=\\\"$workload\\\", workload_type=\\\"$type\\\"}\\n) by (pod)\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"D\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n    node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}\\n  * on(namespace,pod)\\n    group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload=\\\"$workload\\\", workload_type=\\\"$type\\\"}\\n) by (pod)\\n/sum(\\n    kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", resource=\\\"cpu\\\"}\\n  * on(namespace,pod)\\n    group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload=\\\"$workload\\\", workload_type=\\\"$type\\\"}\\n) by (pod)\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"E\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Quota\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"transform\": \"table\",\n                        \"type\": \"table\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"CPU Quota\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 3,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(\\n    container_memory_working_set_bytes{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", container!=\\\"\\\", image!=\\\"\\\"}\\n  * on(namespace,pod)\\n    group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload=\\\"$workload\\\", workload_type=\\\"$type\\\"}\\n) by (pod)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Usage\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Memory Usage\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 4,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"styles\": [\n                            {\n                                \"alias\": \"Time\",\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"pattern\": \"Time\",\n                                \"type\": \"hidden\"\n                            },\n                            {\n                                \"alias\": \"Memory Usage\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #A\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Requests\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #B\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Requests %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #C\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"Memory Limits\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #D\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Limits %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #E\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"Pod\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": true,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"./d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell\",\n                                \"pattern\": \"pod\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"pattern\": \"/.*/\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"string\",\n                                \"unit\": \"short\"\n                            }\n                        ],\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(\\n    container_memory_working_set_bytes{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", container!=\\\"\\\", image!=\\\"\\\"}\\n  * on(namespace,pod)\\n    group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload=\\\"$workload\\\", workload_type=\\\"$type\\\"}\\n) by (pod)\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n    kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", resource=\\\"memory\\\"}\\n  * on(namespace,pod)\\n    group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload=\\\"$workload\\\", workload_type=\\\"$type\\\"}\\n) by (pod)\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"B\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n    container_memory_working_set_bytes{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", container!=\\\"\\\", image!=\\\"\\\"}\\n  * on(namespace,pod)\\n    group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload=\\\"$workload\\\", workload_type=\\\"$type\\\"}\\n) by (pod)\\n/sum(\\n    kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", resource=\\\"memory\\\"}\\n  * on(namespace,pod)\\n    group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload=\\\"$workload\\\", workload_type=\\\"$type\\\"}\\n) by (pod)\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"C\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n    kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", resource=\\\"memory\\\"}\\n  * on(namespace,pod)\\n    group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload=\\\"$workload\\\", workload_type=\\\"$type\\\"}\\n) by (pod)\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"D\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n    container_memory_working_set_bytes{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", container!=\\\"\\\", image!=\\\"\\\"}\\n  * on(namespace,pod)\\n    group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload=\\\"$workload\\\", workload_type=\\\"$type\\\"}\\n) by (pod)\\n/sum(\\n    kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", resource=\\\"memory\\\"}\\n  * on(namespace,pod)\\n    group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload=\\\"$workload\\\", workload_type=\\\"$type\\\"}\\n) by (pod)\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"E\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Quota\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"transform\": \"table\",\n                        \"type\": \"table\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Memory Quota\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 5,\n                        \"interval\": \"1m\",\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"styles\": [\n                            {\n                                \"alias\": \"Time\",\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"pattern\": \"Time\",\n                                \"type\": \"hidden\"\n                            },\n                            {\n                                \"alias\": \"Current Receive Bandwidth\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #A\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"Bps\"\n                            },\n                            {\n                                \"alias\": \"Current Transmit Bandwidth\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #B\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"Bps\"\n                            },\n                            {\n                                \"alias\": \"Rate of Received Packets\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #C\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"pps\"\n                            },\n                            {\n                                \"alias\": \"Rate of Transmitted Packets\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #D\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"pps\"\n                            },\n                            {\n                                \"alias\": \"Rate of Received Packets Dropped\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #E\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"pps\"\n                            },\n                            {\n                                \"alias\": \"Rate of Transmitted Packets Dropped\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #F\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"pps\"\n                            },\n                            {\n                                \"alias\": \"Pod\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": true,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"./d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell\",\n                                \"pattern\": \"pod\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"pattern\": \"/.*/\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"string\",\n                                \"unit\": \"short\"\n                            }\n                        ],\n                        \"targets\": [\n                            {\n                                \"expr\": \"(sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"(sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"B\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"(sum(irate(container_network_receive_packets_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"C\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"(sum(irate(container_network_transmit_packets_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"D\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"(sum(irate(container_network_receive_packets_dropped_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"E\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"(sum(irate(container_network_transmit_packets_dropped_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"F\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Current Network Usage\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"transform\": \"table\",\n                        \"type\": \"table\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Current Network Usage\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 6,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Receive Bandwidth\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 7,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Transmit Bandwidth\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Bandwidth\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 8,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(avg(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Average Container Bandwidth by Pod: Received\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 9,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(avg(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Average Container Bandwidth by Pod: Transmitted\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Average Container Bandwidth by Pod\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 10,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(sum(irate(container_network_receive_packets_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Received Packets\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 11,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(sum(irate(container_network_transmit_packets_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Transmitted Packets\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Rate of Packets\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 12,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(sum(irate(container_network_receive_packets_dropped_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Received Packets Dropped\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 13,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(sum(irate(container_network_transmit_packets_dropped_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Transmitted Packets Dropped\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Rate of Packets Dropped\",\n                \"titleSize\": \"h6\"\n            }\n        ],\n        \"schemaVersion\": 14,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"kubernetes-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": \"\",\n                        \"value\": \"\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }},\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"cluster\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_info, cluster)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": \"\",\n                        \"value\": \"\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"namespace\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_info{cluster=\\\"$cluster\\\"}, namespace)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": \"\",\n                        \"value\": \"\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"workload\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}, workload)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": \"\",\n                        \"value\": \"\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"type\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload=\\\"$workload\\\"}, workload_type)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"UTC\",\n        \"title\": \"Kubernetes / Compute Resources / Workload\",\n        \"uid\": \"a164a7f0339f99e89cea5cb47e9be617\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml",
    "content": "{{- /*\nGenerated from 'k8s-resources-workloads-namespace' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"k8s-resources-workloads-namespace\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  k8s-resources-workloads-namespace.json: |-\n    {\n        \"annotations\": {\n            \"list\": [\n\n            ]\n        },\n        \"editable\": true,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"links\": [\n\n        ],\n        \"refresh\": \"10s\",\n        \"rows\": [\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 1,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n                            {\n                                \"alias\": \"quota - requests\",\n                                \"color\": \"#F2495C\",\n                                \"dashes\": true,\n                                \"fill\": 0,\n                                \"hiddenSeries\": true,\n                                \"hideTooltip\": true,\n                                \"legend\": true,\n                                \"linewidth\": 2,\n                                \"stack\": false\n                            },\n                            {\n                                \"alias\": \"quota - limits\",\n                                \"color\": \"#FF9830\",\n                                \"dashes\": true,\n                                \"fill\": 0,\n                                \"hiddenSeries\": true,\n                                \"hideTooltip\": true,\n                                \"legend\": true,\n                                \"linewidth\": 2,\n                                \"stack\": false\n                            }\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(\\n  node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}\\n* on(namespace,pod)\\n  group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload_type=\\\"$type\\\"}\\n) by (workload, workload_type)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}workload{{`}}`}} - {{`{{`}}workload_type{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"scalar(kube_resourcequota{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", type=\\\"hard\\\",resource=\\\"requests.cpu\\\"})\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"quota - requests\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"scalar(kube_resourcequota{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", type=\\\"hard\\\",resource=\\\"limits.cpu\\\"})\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"quota - limits\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Usage\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"CPU Usage\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 2,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"styles\": [\n                            {\n                                \"alias\": \"Time\",\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"pattern\": \"Time\",\n                                \"type\": \"hidden\"\n                            },\n                            {\n                                \"alias\": \"Running Pods\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 0,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #A\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"CPU Usage\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #B\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"CPU Requests\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #C\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"CPU Requests %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #D\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"CPU Limits\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #E\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"CPU Limits %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #F\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"Workload\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": true,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"./d/a164a7f0339f99e89cea5cb47e9be617/k8s-resources-workload?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-workload=$__cell&var-type=$__cell_2\",\n                                \"pattern\": \"workload\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"Workload Type\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"workload_type\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"pattern\": \"/.*/\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"string\",\n                                \"unit\": \"short\"\n                            }\n                        ],\n                        \"targets\": [\n                            {\n                                \"expr\": \"count(namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload_type=\\\"$type\\\"}) by (workload, workload_type)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n  node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}\\n* on(namespace,pod)\\n  group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload_type=\\\"$type\\\"}\\n) by (workload, workload_type)\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"B\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n  kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", resource=\\\"cpu\\\"}\\n* on(namespace,pod)\\n  group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload_type=\\\"$type\\\"}\\n) by (workload, workload_type)\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"C\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n  node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}\\n* on(namespace,pod)\\n  group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload_type=\\\"$type\\\"}\\n) by (workload, workload_type)\\n/sum(\\n  kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", resource=\\\"cpu\\\"}\\n* on(namespace,pod)\\n  group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload_type=\\\"$type\\\"}\\n) by (workload, workload_type)\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"D\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n  kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", resource=\\\"cpu\\\"}\\n* on(namespace,pod)\\n  group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload_type=\\\"$type\\\"}\\n) by (workload, workload_type)\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"E\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n  node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}\\n* on(namespace,pod)\\n  group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload_type=\\\"$type\\\"}\\n) by (workload, workload_type)\\n/sum(\\n  kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", resource=\\\"cpu\\\"}\\n* on(namespace,pod)\\n  group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload_type=\\\"$type\\\"}\\n) by (workload, workload_type)\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"F\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Quota\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"transform\": \"table\",\n                        \"type\": \"table\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"CPU Quota\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 3,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n                            {\n                                \"alias\": \"quota - requests\",\n                                \"color\": \"#F2495C\",\n                                \"dashes\": true,\n                                \"fill\": 0,\n                                \"hiddenSeries\": true,\n                                \"hideTooltip\": true,\n                                \"legend\": true,\n                                \"linewidth\": 2,\n                                \"stack\": false\n                            },\n                            {\n                                \"alias\": \"quota - limits\",\n                                \"color\": \"#FF9830\",\n                                \"dashes\": true,\n                                \"fill\": 0,\n                                \"hiddenSeries\": true,\n                                \"hideTooltip\": true,\n                                \"legend\": true,\n                                \"linewidth\": 2,\n                                \"stack\": false\n                            }\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(\\n    container_memory_working_set_bytes{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", container!=\\\"\\\", image!=\\\"\\\"}\\n  * on(namespace,pod)\\n    group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload_type=\\\"$type\\\"}\\n) by (workload, workload_type)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}workload{{`}}`}} - {{`{{`}}workload_type{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"scalar(kube_resourcequota{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", type=\\\"hard\\\",resource=\\\"requests.memory\\\"})\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"quota - requests\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"scalar(kube_resourcequota{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", type=\\\"hard\\\",resource=\\\"limits.memory\\\"})\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"quota - limits\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Usage\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Memory Usage\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 4,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"styles\": [\n                            {\n                                \"alias\": \"Time\",\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"pattern\": \"Time\",\n                                \"type\": \"hidden\"\n                            },\n                            {\n                                \"alias\": \"Running Pods\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 0,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #A\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"Memory Usage\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #B\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Requests\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #C\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Requests %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #D\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"Memory Limits\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #E\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"bytes\"\n                            },\n                            {\n                                \"alias\": \"Memory Limits %\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #F\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"percentunit\"\n                            },\n                            {\n                                \"alias\": \"Workload\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": true,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"./d/a164a7f0339f99e89cea5cb47e9be617/k8s-resources-workload?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-workload=$__cell&var-type=$__cell_2\",\n                                \"pattern\": \"workload\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"Workload Type\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"workload_type\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"pattern\": \"/.*/\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"string\",\n                                \"unit\": \"short\"\n                            }\n                        ],\n                        \"targets\": [\n                            {\n                                \"expr\": \"count(namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload_type=\\\"$type\\\"}) by (workload, workload_type)\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n    container_memory_working_set_bytes{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", container!=\\\"\\\", image!=\\\"\\\"}\\n  * on(namespace,pod)\\n    group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload_type=\\\"$type\\\"}\\n) by (workload, workload_type)\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"B\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n  kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", resource=\\\"memory\\\"}\\n* on(namespace,pod)\\n  group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload_type=\\\"$type\\\"}\\n) by (workload, workload_type)\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"C\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n    container_memory_working_set_bytes{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", container!=\\\"\\\", image!=\\\"\\\"}\\n  * on(namespace,pod)\\n    group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload_type=\\\"$type\\\"}\\n) by (workload, workload_type)\\n/sum(\\n  kube_pod_container_resource_requests{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", resource=\\\"memory\\\"}\\n* on(namespace,pod)\\n  group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload_type=\\\"$type\\\"}\\n) by (workload, workload_type)\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"D\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n  kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", resource=\\\"memory\\\"}\\n* on(namespace,pod)\\n  group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload_type=\\\"$type\\\"}\\n) by (workload, workload_type)\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"E\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum(\\n    container_memory_working_set_bytes{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", container!=\\\"\\\", image!=\\\"\\\"}\\n  * on(namespace,pod)\\n    group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload_type=\\\"$type\\\"}\\n) by (workload, workload_type)\\n/sum(\\n  kube_pod_container_resource_limits{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", resource=\\\"memory\\\"}\\n* on(namespace,pod)\\n  group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", workload_type=\\\"$type\\\"}\\n) by (workload, workload_type)\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"F\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Quota\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"transform\": \"table\",\n                        \"type\": \"table\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Memory Quota\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 5,\n                        \"interval\": \"1m\",\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"styles\": [\n                            {\n                                \"alias\": \"Time\",\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"pattern\": \"Time\",\n                                \"type\": \"hidden\"\n                            },\n                            {\n                                \"alias\": \"Current Receive Bandwidth\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #A\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"Bps\"\n                            },\n                            {\n                                \"alias\": \"Current Transmit Bandwidth\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #B\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"Bps\"\n                            },\n                            {\n                                \"alias\": \"Rate of Received Packets\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #C\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"pps\"\n                            },\n                            {\n                                \"alias\": \"Rate of Transmitted Packets\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #D\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"pps\"\n                            },\n                            {\n                                \"alias\": \"Rate of Received Packets Dropped\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #E\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"pps\"\n                            },\n                            {\n                                \"alias\": \"Rate of Transmitted Packets Dropped\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #F\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"pps\"\n                            },\n                            {\n                                \"alias\": \"Workload\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": true,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down to pods\",\n                                \"linkUrl\": \"./d/a164a7f0339f99e89cea5cb47e9be617/k8s-resources-workload?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-workload=$__cell&var-type=$type\",\n                                \"pattern\": \"workload\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"Workload Type\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"workload_type\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"pattern\": \"/.*/\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"string\",\n                                \"unit\": \"short\"\n                            }\n                        ],\n                        \"targets\": [\n                            {\n                                \"expr\": \"(sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"(sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"B\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"(sum(irate(container_network_receive_packets_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"C\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"(sum(irate(container_network_transmit_packets_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"D\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"(sum(irate(container_network_receive_packets_dropped_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"E\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"(sum(irate(container_network_transmit_packets_dropped_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"F\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Current Network Usage\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"transform\": \"table\",\n                        \"type\": \"table\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Current Network Usage\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 6,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}workload{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Receive Bandwidth\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 7,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}workload{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Transmit Bandwidth\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Bandwidth\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 8,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(avg(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}workload{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Average Container Bandwidth by Workload: Received\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 9,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(avg(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}workload{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Average Container Bandwidth by Workload: Transmitted\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Average Container Bandwidth by Workload\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 10,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(sum(irate(container_network_receive_packets_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}workload{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Received Packets\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 11,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(sum(irate(container_network_transmit_packets_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}workload{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Transmitted Packets\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Rate of Packets\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 12,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(sum(irate(container_network_receive_packets_dropped_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}workload{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Received Packets Dropped\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 13,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(sum(irate(container_network_transmit_packets_dropped_total{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\"}[$__rate_interval])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}workload{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Transmitted Packets Dropped\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Rate of Packets Dropped\",\n                \"titleSize\": \"h6\"\n            }\n        ],\n        \"schemaVersion\": 14,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"kubernetes-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": \"\",\n                        \"value\": \"\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }},\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"cluster\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_info, cluster)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"auto\": false,\n                    \"auto_count\": 30,\n                    \"auto_min\": \"10s\",\n                    \"current\": {\n                        \"text\": \"deployment\",\n                        \"value\": \"deployment\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"definition\": \"label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\".+\\\"}, workload_type)\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"type\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\", namespace=~\\\"$namespace\\\", workload=~\\\".+\\\"}, workload_type)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"skipUrlSync\": false,\n                    \"sort\": 0,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": \"\",\n                        \"value\": \"\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"namespace\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_info{cluster=\\\"$cluster\\\"}, namespace)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"UTC\",\n        \"title\": \"Kubernetes / Compute Resources / Namespace (Workloads)\",\n        \"uid\": \"a87fb0d919ec0ea5f6543124e16c42a5\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/kubelet.yaml",
    "content": "{{- /*\nGenerated from 'kubelet' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled .Values.kubelet.enabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"kubelet\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  kubelet.json: |-\n    {\n        \"__inputs\": [\n\n        ],\n        \"__requires\": [\n\n        ],\n        \"annotations\": {\n            \"list\": [\n\n            ]\n        },\n        \"editable\": false,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"id\": null,\n        \"links\": [\n\n        ],\n        \"panels\": [\n            {\n                \"datasource\": \"$datasource\",\n                \"fieldConfig\": {\n                    \"defaults\": {\n                        \"links\": [\n\n                        ],\n                        \"mappings\": [\n\n                        ],\n                        \"thresholds\": {\n                            \"mode\": \"absolute\",\n                            \"steps\": [\n\n                            ]\n                        },\n                        \"unit\": \"none\"\n                    }\n                },\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 4,\n                    \"x\": 0,\n                    \"y\": 0\n                },\n                \"id\": 2,\n                \"links\": [\n\n                ],\n                \"options\": {\n                    \"colorMode\": \"value\",\n                    \"graphMode\": \"area\",\n                    \"justifyMode\": \"auto\",\n                    \"orientation\": \"auto\",\n                    \"reduceOptions\": {\n                        \"calcs\": [\n                            \"lastNotNull\"\n                        ],\n                        \"fields\": \"\",\n                        \"values\": false\n                    }\n                },\n                \"pluginVersion\": \"7\",\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(kubelet_node_name{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\"})\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"title\": \"Running Kubelets\",\n                \"transparent\": false,\n                \"type\": \"stat\"\n            },\n            {\n                \"datasource\": \"$datasource\",\n                \"fieldConfig\": {\n                    \"defaults\": {\n                        \"links\": [\n\n                        ],\n                        \"mappings\": [\n\n                        ],\n                        \"thresholds\": {\n                            \"mode\": \"absolute\",\n                            \"steps\": [\n\n                            ]\n                        },\n                        \"unit\": \"none\"\n                    }\n                },\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 4,\n                    \"x\": 4,\n                    \"y\": 0\n                },\n                \"id\": 3,\n                \"links\": [\n\n                ],\n                \"options\": {\n                    \"colorMode\": \"value\",\n                    \"graphMode\": \"area\",\n                    \"justifyMode\": \"auto\",\n                    \"orientation\": \"auto\",\n                    \"reduceOptions\": {\n                        \"calcs\": [\n                            \"lastNotNull\"\n                        ],\n                        \"fields\": \"\",\n                        \"values\": false\n                    }\n                },\n                \"pluginVersion\": \"7\",\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(kubelet_running_pods{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", instance=~\\\"$instance\\\"}) OR sum(kubelet_running_pod_count{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", instance=~\\\"$instance\\\"})\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"title\": \"Running Pods\",\n                \"transparent\": false,\n                \"type\": \"stat\"\n            },\n            {\n                \"datasource\": \"$datasource\",\n                \"fieldConfig\": {\n                    \"defaults\": {\n                        \"links\": [\n\n                        ],\n                        \"mappings\": [\n\n                        ],\n                        \"thresholds\": {\n                            \"mode\": \"absolute\",\n                            \"steps\": [\n\n                            ]\n                        },\n                        \"unit\": \"none\"\n                    }\n                },\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 4,\n                    \"x\": 8,\n                    \"y\": 0\n                },\n                \"id\": 4,\n                \"links\": [\n\n                ],\n                \"options\": {\n                    \"colorMode\": \"value\",\n                    \"graphMode\": \"area\",\n                    \"justifyMode\": \"auto\",\n                    \"orientation\": \"auto\",\n                    \"reduceOptions\": {\n                        \"calcs\": [\n                            \"lastNotNull\"\n                        ],\n                        \"fields\": \"\",\n                        \"values\": false\n                    }\n                },\n                \"pluginVersion\": \"7\",\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(kubelet_running_containers{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", instance=~\\\"$instance\\\"}) OR sum(kubelet_running_container_count{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", instance=~\\\"$instance\\\"})\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"title\": \"Running Container\",\n                \"transparent\": false,\n                \"type\": \"stat\"\n            },\n            {\n                \"datasource\": \"$datasource\",\n                \"fieldConfig\": {\n                    \"defaults\": {\n                        \"links\": [\n\n                        ],\n                        \"mappings\": [\n\n                        ],\n                        \"thresholds\": {\n                            \"mode\": \"absolute\",\n                            \"steps\": [\n\n                            ]\n                        },\n                        \"unit\": \"none\"\n                    }\n                },\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 4,\n                    \"x\": 12,\n                    \"y\": 0\n                },\n                \"id\": 5,\n                \"links\": [\n\n                ],\n                \"options\": {\n                    \"colorMode\": \"value\",\n                    \"graphMode\": \"area\",\n                    \"justifyMode\": \"auto\",\n                    \"orientation\": \"auto\",\n                    \"reduceOptions\": {\n                        \"calcs\": [\n                            \"lastNotNull\"\n                        ],\n                        \"fields\": \"\",\n                        \"values\": false\n                    }\n                },\n                \"pluginVersion\": \"7\",\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(volume_manager_total_volumes{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", instance=~\\\"$instance\\\", state=\\\"actual_state_of_world\\\"})\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"title\": \"Actual Volume Count\",\n                \"transparent\": false,\n                \"type\": \"stat\"\n            },\n            {\n                \"datasource\": \"$datasource\",\n                \"fieldConfig\": {\n                    \"defaults\": {\n                        \"links\": [\n\n                        ],\n                        \"mappings\": [\n\n                        ],\n                        \"thresholds\": {\n                            \"mode\": \"absolute\",\n                            \"steps\": [\n\n                            ]\n                        },\n                        \"unit\": \"none\"\n                    }\n                },\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 4,\n                    \"x\": 16,\n                    \"y\": 0\n                },\n                \"id\": 6,\n                \"links\": [\n\n                ],\n                \"options\": {\n                    \"colorMode\": \"value\",\n                    \"graphMode\": \"area\",\n                    \"justifyMode\": \"auto\",\n                    \"orientation\": \"auto\",\n                    \"reduceOptions\": {\n                        \"calcs\": [\n                            \"lastNotNull\"\n                        ],\n                        \"fields\": \"\",\n                        \"values\": false\n                    }\n                },\n                \"pluginVersion\": \"7\",\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(volume_manager_total_volumes{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", instance=~\\\"$instance\\\",state=\\\"desired_state_of_world\\\"})\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"title\": \"Desired Volume Count\",\n                \"transparent\": false,\n                \"type\": \"stat\"\n            },\n            {\n                \"datasource\": \"$datasource\",\n                \"fieldConfig\": {\n                    \"defaults\": {\n                        \"links\": [\n\n                        ],\n                        \"mappings\": [\n\n                        ],\n                        \"thresholds\": {\n                            \"mode\": \"absolute\",\n                            \"steps\": [\n\n                            ]\n                        },\n                        \"unit\": \"none\"\n                    }\n                },\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 4,\n                    \"x\": 20,\n                    \"y\": 0\n                },\n                \"id\": 7,\n                \"links\": [\n\n                ],\n                \"options\": {\n                    \"colorMode\": \"value\",\n                    \"graphMode\": \"area\",\n                    \"justifyMode\": \"auto\",\n                    \"orientation\": \"auto\",\n                    \"reduceOptions\": {\n                        \"calcs\": [\n                            \"lastNotNull\"\n                        ],\n                        \"fields\": \"\",\n                        \"values\": false\n                    }\n                },\n                \"pluginVersion\": \"7\",\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(rate(kubelet_node_config_error{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", instance=~\\\"$instance\\\"}[5m]))\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"title\": \"Config Error Count\",\n                \"transparent\": false,\n                \"type\": \"stat\"\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 1,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 12,\n                    \"x\": 0,\n                    \"y\": 7\n                },\n                \"id\": 8,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": false,\n                    \"current\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"nullPointMode\": \"null\",\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(rate(kubelet_runtime_operations_total{cluster=\\\"$cluster\\\",job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\",instance=~\\\"$instance\\\"}[5m])) by (operation_type, instance)\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}} {{`{{`}}operation_type{{`}}`}}\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Operation Rate\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 0,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"ops\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"ops\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 1,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 12,\n                    \"x\": 12,\n                    \"y\": 7\n                },\n                \"id\": 9,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": false,\n                    \"current\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"nullPointMode\": \"null\",\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(rate(kubelet_runtime_operations_errors_total{cluster=\\\"$cluster\\\",job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\",instance=~\\\"$instance\\\"}[5m])) by (instance, operation_type)\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}} {{`{{`}}operation_type{{`}}`}}\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Operation Error Rate\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 0,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"ops\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"ops\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 1,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 14\n                },\n                \"id\": 10,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": false,\n                    \"current\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"nullPointMode\": \"null\",\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"histogram_quantile(0.99, sum(rate(kubelet_runtime_operations_duration_seconds_bucket{cluster=\\\"$cluster\\\",job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\",instance=~\\\"$instance\\\"}[5m])) by (instance, operation_type, le))\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}} {{`{{`}}operation_type{{`}}`}}\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Operation duration 99th quantile\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 0,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"s\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"s\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 1,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 12,\n                    \"x\": 0,\n                    \"y\": 21\n                },\n                \"id\": 11,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": false,\n                    \"current\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"nullPointMode\": \"null\",\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(rate(kubelet_pod_start_duration_seconds_count{cluster=\\\"$cluster\\\",job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\",instance=~\\\"$instance\\\"}[5m])) by (instance)\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}} pod\",\n                        \"refId\": \"A\"\n                    },\n                    {\n                        \"expr\": \"sum(rate(kubelet_pod_worker_duration_seconds_count{cluster=\\\"$cluster\\\",job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\",instance=~\\\"$instance\\\"}[5m])) by (instance)\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}} worker\",\n                        \"refId\": \"B\"\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Pod Start Rate\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 0,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"ops\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"ops\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 1,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 12,\n                    \"x\": 12,\n                    \"y\": 21\n                },\n                \"id\": 12,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": false,\n                    \"current\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"nullPointMode\": \"null\",\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"histogram_quantile(0.99, sum(rate(kubelet_pod_start_duration_seconds_count{cluster=\\\"$cluster\\\",job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\",instance=~\\\"$instance\\\"}[5m])) by (instance, le))\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}} pod\",\n                        \"refId\": \"A\"\n                    },\n                    {\n                        \"expr\": \"histogram_quantile(0.99, sum(rate(kubelet_pod_worker_duration_seconds_bucket{cluster=\\\"$cluster\\\",job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\",instance=~\\\"$instance\\\"}[5m])) by (instance, le))\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}} worker\",\n                        \"refId\": \"B\"\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Pod Start Duration\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 0,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"s\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"s\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 1,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 12,\n                    \"x\": 0,\n                    \"y\": 28\n                },\n                \"id\": 13,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": false,\n                    \"current\": true,\n                    \"hideEmpty\": true,\n                    \"hideZero\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"nullPointMode\": \"null\",\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(rate(storage_operation_duration_seconds_count{cluster=\\\"$cluster\\\",job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\",instance=~\\\"$instance\\\"}[5m])) by (instance, operation_name, volume_plugin)\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}} {{`{{`}}operation_name{{`}}`}} {{`{{`}}volume_plugin{{`}}`}}\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Storage Operation Rate\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 0,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"ops\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"ops\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 1,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 12,\n                    \"x\": 12,\n                    \"y\": 28\n                },\n                \"id\": 14,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": false,\n                    \"current\": true,\n                    \"hideEmpty\": true,\n                    \"hideZero\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"nullPointMode\": \"null\",\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(rate(storage_operation_errors_total{cluster=\\\"$cluster\\\",job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\",instance=~\\\"$instance\\\"}[5m])) by (instance, operation_name, volume_plugin)\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}} {{`{{`}}operation_name{{`}}`}} {{`{{`}}volume_plugin{{`}}`}}\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Storage Operation Error Rate\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 0,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"ops\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"ops\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 1,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 35\n                },\n                \"id\": 15,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": false,\n                    \"current\": true,\n                    \"hideEmpty\": true,\n                    \"hideZero\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"nullPointMode\": \"null\",\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"histogram_quantile(0.99, sum(rate(storage_operation_duration_seconds_bucket{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", instance=~\\\"$instance\\\"}[5m])) by (instance, operation_name, volume_plugin, le))\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}} {{`{{`}}operation_name{{`}}`}} {{`{{`}}volume_plugin{{`}}`}}\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Storage Operation Duration 99th quantile\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 0,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"s\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"s\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 1,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 12,\n                    \"x\": 0,\n                    \"y\": 42\n                },\n                \"id\": 16,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": false,\n                    \"current\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"nullPointMode\": \"null\",\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(rate(kubelet_cgroup_manager_duration_seconds_count{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", instance=~\\\"$instance\\\"}[5m])) by (instance, operation_type)\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}operation_type{{`}}`}}\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Cgroup manager operation rate\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 0,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"ops\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"ops\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 1,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 12,\n                    \"x\": 12,\n                    \"y\": 42\n                },\n                \"id\": 17,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": false,\n                    \"current\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"nullPointMode\": \"null\",\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"histogram_quantile(0.99, sum(rate(kubelet_cgroup_manager_duration_seconds_bucket{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", instance=~\\\"$instance\\\"}[5m])) by (instance, operation_type, le))\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}} {{`{{`}}operation_type{{`}}`}}\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Cgroup manager 99th quantile\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 0,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"s\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"s\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"description\": \"Pod lifecycle event generator\",\n                \"fill\": 1,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 12,\n                    \"x\": 0,\n                    \"y\": 49\n                },\n                \"id\": 18,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": false,\n                    \"current\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"nullPointMode\": \"null\",\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(rate(kubelet_pleg_relist_duration_seconds_count{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", instance=~\\\"$instance\\\"}[5m])) by (instance)\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"PLEG relist rate\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 0,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"ops\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"ops\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 1,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 12,\n                    \"x\": 12,\n                    \"y\": 49\n                },\n                \"id\": 19,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": false,\n                    \"current\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"nullPointMode\": \"null\",\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"histogram_quantile(0.99, sum(rate(kubelet_pleg_relist_interval_seconds_bucket{cluster=\\\"$cluster\\\",job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\",instance=~\\\"$instance\\\"}[5m])) by (instance, le))\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"PLEG relist interval\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 0,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"s\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"s\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 1,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 56\n                },\n                \"id\": 20,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": false,\n                    \"current\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"nullPointMode\": \"null\",\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"histogram_quantile(0.99, sum(rate(kubelet_pleg_relist_duration_seconds_bucket{cluster=\\\"$cluster\\\",job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\",instance=~\\\"$instance\\\"}[5m])) by (instance, le))\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"PLEG relist duration\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 0,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"s\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"s\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 1,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 63\n                },\n                \"id\": 21,\n                \"legend\": {\n                    \"alignAsTable\": false,\n                    \"avg\": false,\n                    \"current\": false,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": false,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": false\n                },\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"nullPointMode\": \"null\",\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(rate(rest_client_requests_total{cluster=\\\"$cluster\\\",job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", instance=~\\\"$instance\\\",code=~\\\"2..\\\"}[5m]))\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"2xx\",\n                        \"refId\": \"A\"\n                    },\n                    {\n                        \"expr\": \"sum(rate(rest_client_requests_total{cluster=\\\"$cluster\\\",job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", instance=~\\\"$instance\\\",code=~\\\"3..\\\"}[5m]))\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"3xx\",\n                        \"refId\": \"B\"\n                    },\n                    {\n                        \"expr\": \"sum(rate(rest_client_requests_total{cluster=\\\"$cluster\\\",job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", instance=~\\\"$instance\\\",code=~\\\"4..\\\"}[5m]))\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"4xx\",\n                        \"refId\": \"C\"\n                    },\n                    {\n                        \"expr\": \"sum(rate(rest_client_requests_total{cluster=\\\"$cluster\\\",job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", instance=~\\\"$instance\\\",code=~\\\"5..\\\"}[5m]))\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"5xx\",\n                        \"refId\": \"D\"\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"RPC Rate\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 0,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"ops\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"ops\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 1,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 70\n                },\n                \"id\": 22,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": false,\n                    \"current\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"nullPointMode\": \"null\",\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{cluster=\\\"$cluster\\\",job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", instance=~\\\"$instance\\\"}[5m])) by (instance, verb, url, le))\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}} {{`{{`}}verb{{`}}`}} {{`{{`}}url{{`}}`}}\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Request duration 99th quantile\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 0,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"s\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"s\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 1,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 8,\n                    \"x\": 0,\n                    \"y\": 77\n                },\n                \"id\": 23,\n                \"legend\": {\n                    \"alignAsTable\": false,\n                    \"avg\": false,\n                    \"current\": false,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": false,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": false\n                },\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"nullPointMode\": \"null\",\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"process_resident_memory_bytes{cluster=\\\"$cluster\\\",job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\",instance=~\\\"$instance\\\"}\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Memory\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 0,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"bytes\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"bytes\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 1,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 8,\n                    \"x\": 8,\n                    \"y\": 77\n                },\n                \"id\": 24,\n                \"legend\": {\n                    \"alignAsTable\": false,\n                    \"avg\": false,\n                    \"current\": false,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": false,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": false\n                },\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"nullPointMode\": \"null\",\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"rate(process_cpu_seconds_total{cluster=\\\"$cluster\\\",job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\",instance=~\\\"$instance\\\"}[5m])\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"CPU usage\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 0,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"short\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"short\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 1,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 7,\n                    \"w\": 8,\n                    \"x\": 16,\n                    \"y\": 77\n                },\n                \"id\": 25,\n                \"legend\": {\n                    \"alignAsTable\": false,\n                    \"avg\": false,\n                    \"current\": false,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": false,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": false\n                },\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"nullPointMode\": \"null\",\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"go_goroutines{cluster=\\\"$cluster\\\",job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\",instance=~\\\"$instance\\\"}\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Goroutines\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 0,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"short\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"short\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": null,\n                        \"show\": true\n                    }\n                ]\n            }\n        ],\n        \"refresh\": \"10s\",\n        \"rows\": [\n\n        ],\n        \"schemaVersion\": 14,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"kubernetes-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }},\n                    \"includeAll\": false,\n                    \"label\": \"cluster\",\n                    \"multi\": false,\n                    \"name\": \"cluster\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_info, cluster)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": true,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"instance\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kubelet_runtime_operations_total{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\"}, instance)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"UTC\",\n        \"title\": \"Kubernetes / Kubelet\",\n        \"uid\": \"3138fa155d5915769fbded898ac09fd9\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/namespace-by-pod.yaml",
    "content": "{{- /*\nGenerated from 'namespace-by-pod' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"namespace-by-pod\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  namespace-by-pod.json: |-\n    {\n        \"__inputs\": [\n\n        ],\n        \"__requires\": [\n\n        ],\n        \"annotations\": {\n            \"list\": [\n                {\n                    \"builtIn\": 1,\n                    \"datasource\": \"-- Grafana --\",\n                    \"enable\": true,\n                    \"hide\": true,\n                    \"iconColor\": \"rgba(0, 211, 255, 1)\",\n                    \"name\": \"Annotations & Alerts\",\n                    \"type\": \"dashboard\"\n                }\n            ]\n        },\n        \"editable\": true,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"id\": null,\n        \"links\": [\n\n        ],\n        \"panels\": [\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 0\n                },\n                \"id\": 2,\n                \"panels\": [\n\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Current Bandwidth\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"cacheTimeout\": null,\n                \"colorBackground\": false,\n                \"colorValue\": false,\n                \"colors\": [\n                    \"#299c46\",\n                    \"rgba(237, 129, 40, 0.89)\",\n                    \"#d44a3a\"\n                ],\n                \"datasource\": \"$datasource\",\n                \"decimals\": 0,\n                \"format\": \"time_series\",\n                \"gauge\": {\n                    \"maxValue\": 100,\n                    \"minValue\": 0,\n                    \"show\": false,\n                    \"thresholdLabels\": false,\n                    \"thresholdMarkers\": true\n                },\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 12,\n                    \"x\": 0,\n                    \"y\": 1\n                },\n                \"height\": 9,\n                \"id\": 3,\n                \"interval\": null,\n                \"links\": [\n\n                ],\n                \"mappingType\": 1,\n                \"mappingTypes\": [\n                    {\n                        \"name\": \"value to text\",\n                        \"value\": 1\n                    },\n                    {\n                        \"name\": \"range to text\",\n                        \"value\": 2\n                    }\n                ],\n                \"maxDataPoints\": 100,\n                \"minSpan\": 12,\n                \"nullPointMode\": \"connected\",\n                \"nullText\": null,\n                \"options\": {\n                    \"fieldOptions\": {\n                        \"calcs\": [\n                            \"last\"\n                        ],\n                        \"defaults\": {\n                            \"max\": 10000000000,\n                            \"min\": 0,\n                            \"title\": \"$namespace\",\n                            \"unit\": \"Bps\"\n                        },\n                        \"mappings\": [\n\n                        ],\n                        \"override\": {\n\n                        },\n                        \"thresholds\": [\n                            {\n                                \"color\": \"dark-green\",\n                                \"index\": 0,\n                                \"value\": null\n                            },\n                            {\n                                \"color\": \"dark-yellow\",\n                                \"index\": 1,\n                                \"value\": 5000000000\n                            },\n                            {\n                                \"color\": \"dark-red\",\n                                \"index\": 2,\n                                \"value\": 7000000000\n                            }\n                        ],\n                        \"values\": false\n                    }\n                },\n                \"postfix\": \"\",\n                \"postfixFontSize\": \"50%\",\n                \"prefix\": \"\",\n                \"prefixFontSize\": \"50%\",\n                \"rangeMaps\": [\n                    {\n                        \"from\": \"null\",\n                        \"text\": \"N/A\",\n                        \"to\": \"null\"\n                    }\n                ],\n                \"span\": 12,\n                \"sparkline\": {\n                    \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                    \"full\": false,\n                    \"lineColor\": \"rgb(31, 120, 193)\",\n                    \"show\": false\n                },\n                \"tableColumn\": \"\",\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution]))\",\n                        \"format\": \"time_series\",\n                        \"instant\": null,\n                        \"intervalFactor\": 1,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"thresholds\": \"\",\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Current Rate of Bytes Received\",\n                \"type\": \"gauge\",\n                \"valueFontSize\": \"80%\",\n                \"valueMaps\": [\n                    {\n                        \"op\": \"=\",\n                        \"text\": \"N/A\",\n                        \"value\": \"null\"\n                    }\n                ],\n                \"valueName\": \"current\"\n            },\n            {\n                \"cacheTimeout\": null,\n                \"colorBackground\": false,\n                \"colorValue\": false,\n                \"colors\": [\n                    \"#299c46\",\n                    \"rgba(237, 129, 40, 0.89)\",\n                    \"#d44a3a\"\n                ],\n                \"datasource\": \"$datasource\",\n                \"decimals\": 0,\n                \"format\": \"time_series\",\n                \"gauge\": {\n                    \"maxValue\": 100,\n                    \"minValue\": 0,\n                    \"show\": false,\n                    \"thresholdLabels\": false,\n                    \"thresholdMarkers\": true\n                },\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 12,\n                    \"x\": 12,\n                    \"y\": 1\n                },\n                \"height\": 9,\n                \"id\": 4,\n                \"interval\": null,\n                \"links\": [\n\n                ],\n                \"mappingType\": 1,\n                \"mappingTypes\": [\n                    {\n                        \"name\": \"value to text\",\n                        \"value\": 1\n                    },\n                    {\n                        \"name\": \"range to text\",\n                        \"value\": 2\n                    }\n                ],\n                \"maxDataPoints\": 100,\n                \"minSpan\": 12,\n                \"nullPointMode\": \"connected\",\n                \"nullText\": null,\n                \"options\": {\n                    \"fieldOptions\": {\n                        \"calcs\": [\n                            \"last\"\n                        ],\n                        \"defaults\": {\n                            \"max\": 10000000000,\n                            \"min\": 0,\n                            \"title\": \"$namespace\",\n                            \"unit\": \"Bps\"\n                        },\n                        \"mappings\": [\n\n                        ],\n                        \"override\": {\n\n                        },\n                        \"thresholds\": [\n                            {\n                                \"color\": \"dark-green\",\n                                \"index\": 0,\n                                \"value\": null\n                            },\n                            {\n                                \"color\": \"dark-yellow\",\n                                \"index\": 1,\n                                \"value\": 5000000000\n                            },\n                            {\n                                \"color\": \"dark-red\",\n                                \"index\": 2,\n                                \"value\": 7000000000\n                            }\n                        ],\n                        \"values\": false\n                    }\n                },\n                \"postfix\": \"\",\n                \"postfixFontSize\": \"50%\",\n                \"prefix\": \"\",\n                \"prefixFontSize\": \"50%\",\n                \"rangeMaps\": [\n                    {\n                        \"from\": \"null\",\n                        \"text\": \"N/A\",\n                        \"to\": \"null\"\n                    }\n                ],\n                \"span\": 12,\n                \"sparkline\": {\n                    \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                    \"full\": false,\n                    \"lineColor\": \"rgb(31, 120, 193)\",\n                    \"show\": false\n                },\n                \"tableColumn\": \"\",\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution]))\",\n                        \"format\": \"time_series\",\n                        \"instant\": null,\n                        \"intervalFactor\": 1,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"thresholds\": \"\",\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Current Rate of Bytes Transmitted\",\n                \"type\": \"gauge\",\n                \"valueFontSize\": \"80%\",\n                \"valueMaps\": [\n                    {\n                        \"op\": \"=\",\n                        \"text\": \"N/A\",\n                        \"value\": \"null\"\n                    }\n                ],\n                \"valueName\": \"current\"\n            },\n            {\n                \"columns\": [\n                    {\n                        \"text\": \"Time\",\n                        \"value\": \"Time\"\n                    },\n                    {\n                        \"text\": \"Value #A\",\n                        \"value\": \"Value #A\"\n                    },\n                    {\n                        \"text\": \"Value #B\",\n                        \"value\": \"Value #B\"\n                    },\n                    {\n                        \"text\": \"Value #C\",\n                        \"value\": \"Value #C\"\n                    },\n                    {\n                        \"text\": \"Value #D\",\n                        \"value\": \"Value #D\"\n                    },\n                    {\n                        \"text\": \"Value #E\",\n                        \"value\": \"Value #E\"\n                    },\n                    {\n                        \"text\": \"Value #F\",\n                        \"value\": \"Value #F\"\n                    },\n                    {\n                        \"text\": \"pod\",\n                        \"value\": \"pod\"\n                    }\n                ],\n                \"datasource\": \"$datasource\",\n                \"fill\": 1,\n                \"fontSize\": \"100%\",\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 10\n                },\n                \"id\": 5,\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"minSpan\": 24,\n                \"nullPointMode\": \"null as zero\",\n                \"renderer\": \"flot\",\n                \"scroll\": true,\n                \"showHeader\": true,\n                \"sort\": {\n                    \"col\": 0,\n                    \"desc\": false\n                },\n                \"spaceLength\": 10,\n                \"span\": 24,\n                \"styles\": [\n                    {\n                        \"alias\": \"Time\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Time\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"hidden\",\n                        \"unit\": \"short\"\n                    },\n                    {\n                        \"alias\": \"Bandwidth Received\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #A\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"Bps\"\n                    },\n                    {\n                        \"alias\": \"Bandwidth Transmitted\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #B\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"Bps\"\n                    },\n                    {\n                        \"alias\": \"Rate of Received Packets\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #C\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"pps\"\n                    },\n                    {\n                        \"alias\": \"Rate of Transmitted Packets\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #D\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"pps\"\n                    },\n                    {\n                        \"alias\": \"Rate of Received Packets Dropped\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #E\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"pps\"\n                    },\n                    {\n                        \"alias\": \"Rate of Transmitted Packets Dropped\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #F\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"pps\"\n                    },\n                    {\n                        \"alias\": \"Pod\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": true,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"d/7a18067ce943a40ae25454675c19ff5c/kubernetes-networking-pod?orgId=1&refresh=30s&var-namespace=$namespace&var-pod=$__cell\",\n                        \"pattern\": \"pod\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"short\"\n                    }\n                ],\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])) by (pod)\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"A\",\n                        \"step\": 10\n                    },\n                    {\n                        \"expr\": \"sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])) by (pod)\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"B\",\n                        \"step\": 10\n                    },\n                    {\n                        \"expr\": \"sum(irate(container_network_receive_packets_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])) by (pod)\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"C\",\n                        \"step\": 10\n                    },\n                    {\n                        \"expr\": \"sum(irate(container_network_transmit_packets_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])) by (pod)\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"D\",\n                        \"step\": 10\n                    },\n                    {\n                        \"expr\": \"sum(irate(container_network_receive_packets_dropped_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])) by (pod)\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"E\",\n                        \"step\": 10\n                    },\n                    {\n                        \"expr\": \"sum(irate(container_network_transmit_packets_dropped_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])) by (pod)\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"F\",\n                        \"step\": 10\n                    }\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Current Status\",\n                \"type\": \"table\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 19\n                },\n                \"id\": 6,\n                \"panels\": [\n\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Bandwidth\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 2,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 12,\n                    \"x\": 0,\n                    \"y\": 20\n                },\n                \"id\": 7,\n                \"legend\": {\n                    \"alignAsTable\": false,\n                    \"avg\": false,\n                    \"current\": false,\n                    \"hideEmpty\": true,\n                    \"hideZero\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": false,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": false\n                },\n                \"lines\": true,\n                \"linewidth\": 2,\n                \"links\": [\n\n                ],\n                \"minSpan\": 12,\n                \"nullPointMode\": \"connected\",\n                \"paceLength\": 10,\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"span\": 12,\n                \"stack\": true,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])) by (pod)\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 1,\n                        \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                        \"refId\": \"A\",\n                        \"step\": 10\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Receive Bandwidth\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 2,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 2,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 12,\n                    \"x\": 12,\n                    \"y\": 20\n                },\n                \"id\": 8,\n                \"legend\": {\n                    \"alignAsTable\": false,\n                    \"avg\": false,\n                    \"current\": false,\n                    \"hideEmpty\": true,\n                    \"hideZero\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": false,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": false\n                },\n                \"lines\": true,\n                \"linewidth\": 2,\n                \"links\": [\n\n                ],\n                \"minSpan\": 12,\n                \"nullPointMode\": \"connected\",\n                \"paceLength\": 10,\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"span\": 12,\n                \"stack\": true,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])) by (pod)\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 1,\n                        \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                        \"refId\": \"A\",\n                        \"step\": 10\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Transmit Bandwidth\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 2,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"collapse\": true,\n                \"collapsed\": true,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 29\n                },\n                \"id\": 9,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 10,\n                            \"w\": 12,\n                            \"x\": 0,\n                            \"y\": 30\n                        },\n                        \"id\": 10,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 12,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_receive_packets_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Received Packets\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 10,\n                            \"w\": 12,\n                            \"x\": 12,\n                            \"y\": 30\n                        },\n                        \"id\": 11,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 12,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_transmit_packets_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Transmitted Packets\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Packets\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": true,\n                \"collapsed\": true,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 30\n                },\n                \"id\": 12,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 10,\n                            \"w\": 12,\n                            \"x\": 0,\n                            \"y\": 40\n                        },\n                        \"id\": 13,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 12,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_receive_packets_dropped_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Received Packets Dropped\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 10,\n                            \"w\": 12,\n                            \"x\": 12,\n                            \"y\": 40\n                        },\n                        \"id\": 14,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 12,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_transmit_packets_dropped_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Transmitted Packets Dropped\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Errors\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            }\n        ],\n        \"refresh\": \"10s\",\n        \"rows\": [\n\n        ],\n        \"schemaVersion\": 18,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"kubernetes-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }},\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"cluster\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_info, cluster)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 0,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": \".+\",\n                    \"auto\": false,\n                    \"auto_count\": 30,\n                    \"auto_min\": \"10s\",\n                    \"current\": {\n                        \"text\": \"kube-system\",\n                        \"value\": \"kube-system\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"definition\": \"label_values(container_network_receive_packets_total{cluster=\\\"$cluster\\\"}, namespace)\",\n                    \"hide\": 0,\n                    \"includeAll\": true,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"namespace\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(container_network_receive_packets_total{cluster=\\\"$cluster\\\"}, namespace)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"skipUrlSync\": false,\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"auto\": false,\n                    \"auto_count\": 30,\n                    \"auto_min\": \"10s\",\n                    \"current\": {\n                        \"text\": \"5m\",\n                        \"value\": \"5m\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"resolution\",\n                    \"options\": [\n                        {\n                            \"selected\": false,\n                            \"text\": \"30s\",\n                            \"value\": \"30s\"\n                        },\n                        {\n                            \"selected\": true,\n                            \"text\": \"5m\",\n                            \"value\": \"5m\"\n                        },\n                        {\n                            \"selected\": false,\n                            \"text\": \"1h\",\n                            \"value\": \"1h\"\n                        }\n                    ],\n                    \"query\": \"30s,5m,1h\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"skipUrlSync\": false,\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"interval\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"auto\": false,\n                    \"auto_count\": 30,\n                    \"auto_min\": \"10s\",\n                    \"current\": {\n                        \"text\": \"5m\",\n                        \"value\": \"5m\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 2,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"interval\",\n                    \"options\": [\n                        {\n                            \"selected\": true,\n                            \"text\": \"4h\",\n                            \"value\": \"4h\"\n                        }\n                    ],\n                    \"query\": \"4h\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"skipUrlSync\": false,\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"interval\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"UTC\",\n        \"title\": \"Kubernetes / Networking / Namespace (Pods)\",\n        \"uid\": \"8b7a8b326d7a6f1f04244066368c67af\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/namespace-by-workload.yaml",
    "content": "{{- /*\nGenerated from 'namespace-by-workload' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"namespace-by-workload\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  namespace-by-workload.json: |-\n    {\n        \"__inputs\": [\n\n        ],\n        \"__requires\": [\n\n        ],\n        \"annotations\": {\n            \"list\": [\n                {\n                    \"builtIn\": 1,\n                    \"datasource\": \"-- Grafana --\",\n                    \"enable\": true,\n                    \"hide\": true,\n                    \"iconColor\": \"rgba(0, 211, 255, 1)\",\n                    \"name\": \"Annotations & Alerts\",\n                    \"type\": \"dashboard\"\n                }\n            ]\n        },\n        \"editable\": true,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"id\": null,\n        \"links\": [\n\n        ],\n        \"panels\": [\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 0\n                },\n                \"id\": 2,\n                \"panels\": [\n\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Current Bandwidth\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": true,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 2,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 12,\n                    \"x\": 0,\n                    \"y\": 1\n                },\n                \"id\": 3,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": false,\n                    \"current\": true,\n                    \"hideEmpty\": true,\n                    \"hideZero\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"sort\": \"current\",\n                    \"sortDesc\": true,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": false,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"minSpan\": 24,\n                \"nullPointMode\": \"null\",\n                \"paceLength\": 10,\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"span\": 24,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 1,\n                        \"legendFormat\": \"{{`{{`}} workload {{`}}`}}\",\n                        \"refId\": \"A\",\n                        \"step\": 10\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Current Rate of Bytes Received\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 2,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"series\",\n                    \"name\": null,\n                    \"show\": false,\n                    \"values\": [\n                        \"current\"\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": true,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 2,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 12,\n                    \"x\": 12,\n                    \"y\": 1\n                },\n                \"id\": 4,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": false,\n                    \"current\": true,\n                    \"hideEmpty\": true,\n                    \"hideZero\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"sort\": \"current\",\n                    \"sortDesc\": true,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": false,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"minSpan\": 24,\n                \"nullPointMode\": \"null\",\n                \"paceLength\": 10,\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"span\": 24,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 1,\n                        \"legendFormat\": \"{{`{{`}} workload {{`}}`}}\",\n                        \"refId\": \"A\",\n                        \"step\": 10\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Current Rate of Bytes Transmitted\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 2,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"series\",\n                    \"name\": null,\n                    \"show\": false,\n                    \"values\": [\n                        \"current\"\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"columns\": [\n                    {\n                        \"text\": \"Time\",\n                        \"value\": \"Time\"\n                    },\n                    {\n                        \"text\": \"Value #A\",\n                        \"value\": \"Value #A\"\n                    },\n                    {\n                        \"text\": \"Value #B\",\n                        \"value\": \"Value #B\"\n                    },\n                    {\n                        \"text\": \"Value #C\",\n                        \"value\": \"Value #C\"\n                    },\n                    {\n                        \"text\": \"Value #D\",\n                        \"value\": \"Value #D\"\n                    },\n                    {\n                        \"text\": \"Value #E\",\n                        \"value\": \"Value #E\"\n                    },\n                    {\n                        \"text\": \"Value #F\",\n                        \"value\": \"Value #F\"\n                    },\n                    {\n                        \"text\": \"Value #G\",\n                        \"value\": \"Value #G\"\n                    },\n                    {\n                        \"text\": \"Value #H\",\n                        \"value\": \"Value #H\"\n                    },\n                    {\n                        \"text\": \"workload\",\n                        \"value\": \"workload\"\n                    }\n                ],\n                \"datasource\": \"$datasource\",\n                \"fill\": 1,\n                \"fontSize\": \"90%\",\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 10\n                },\n                \"id\": 5,\n                \"lines\": true,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"minSpan\": 24,\n                \"nullPointMode\": \"null as zero\",\n                \"renderer\": \"flot\",\n                \"scroll\": true,\n                \"showHeader\": true,\n                \"sort\": {\n                    \"col\": 0,\n                    \"desc\": false\n                },\n                \"spaceLength\": 10,\n                \"span\": 24,\n                \"styles\": [\n                    {\n                        \"alias\": \"Time\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Time\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"hidden\",\n                        \"unit\": \"short\"\n                    },\n                    {\n                        \"alias\": \"Current Bandwidth Received\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #A\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"Bps\"\n                    },\n                    {\n                        \"alias\": \"Current Bandwidth Transmitted\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #B\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"Bps\"\n                    },\n                    {\n                        \"alias\": \"Average Bandwidth Received\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #C\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"Bps\"\n                    },\n                    {\n                        \"alias\": \"Average Bandwidth Transmitted\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #D\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"Bps\"\n                    },\n                    {\n                        \"alias\": \"Rate of Received Packets\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #E\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"pps\"\n                    },\n                    {\n                        \"alias\": \"Rate of Transmitted Packets\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #F\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"pps\"\n                    },\n                    {\n                        \"alias\": \"Rate of Received Packets Dropped\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #G\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"pps\"\n                    },\n                    {\n                        \"alias\": \"Rate of Transmitted Packets Dropped\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": false,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"\",\n                        \"pattern\": \"Value #H\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"pps\"\n                    },\n                    {\n                        \"alias\": \"Workload\",\n                        \"colorMode\": null,\n                        \"colors\": [\n\n                        ],\n                        \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                        \"decimals\": 2,\n                        \"link\": true,\n                        \"linkTooltip\": \"Drill down\",\n                        \"linkUrl\": \"d/728bf77cc1166d2f3133bf25846876cc/kubernetes-networking-workload?orgId=1&refresh=30s&var-namespace=$namespace&var-type=$type&var-workload=$__cell\",\n                        \"pattern\": \"workload\",\n                        \"thresholds\": [\n\n                        ],\n                        \"type\": \"number\",\n                        \"unit\": \"short\"\n                    }\n                ],\n                \"targets\": [\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"A\",\n                        \"step\": 10\n                    },\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"B\",\n                        \"step\": 10\n                    },\n                    {\n                        \"expr\": \"sort_desc(avg(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"C\",\n                        \"step\": 10\n                    },\n                    {\n                        \"expr\": \"sort_desc(avg(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"D\",\n                        \"step\": 10\n                    },\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_receive_packets_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"E\",\n                        \"step\": 10\n                    },\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_transmit_packets_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"F\",\n                        \"step\": 10\n                    },\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_receive_packets_dropped_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"G\",\n                        \"step\": 10\n                    },\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_transmit_packets_dropped_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                        \"format\": \"table\",\n                        \"instant\": true,\n                        \"intervalFactor\": 2,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"H\",\n                        \"step\": 10\n                    }\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Current Status\",\n                \"type\": \"table\"\n            },\n            {\n                \"collapse\": true,\n                \"collapsed\": true,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 19\n                },\n                \"id\": 6,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": true,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 9,\n                            \"w\": 12,\n                            \"x\": 0,\n                            \"y\": 20\n                        },\n                        \"id\": 7,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": false,\n                            \"current\": true,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"sort\": \"current\",\n                            \"sortDesc\": true,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": false,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 24,\n                        \"nullPointMode\": \"null\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 24,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sort_desc(avg(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}} workload {{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Average Rate of Bytes Received\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"series\",\n                            \"name\": null,\n                            \"show\": false,\n                            \"values\": [\n                                \"current\"\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": true,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 9,\n                            \"w\": 12,\n                            \"x\": 12,\n                            \"y\": 20\n                        },\n                        \"id\": 8,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": false,\n                            \"current\": true,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"sort\": \"current\",\n                            \"sortDesc\": true,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": false,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 24,\n                        \"nullPointMode\": \"null\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 24,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sort_desc(avg(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}} workload {{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Average Rate of Bytes Transmitted\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"series\",\n                            \"name\": null,\n                            \"show\": false,\n                            \"values\": [\n                                \"current\"\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Average Bandwidth\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 29\n                },\n                \"id\": 9,\n                \"panels\": [\n\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Bandwidth HIstory\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 2,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 12,\n                    \"x\": 0,\n                    \"y\": 38\n                },\n                \"id\": 10,\n                \"legend\": {\n                    \"alignAsTable\": false,\n                    \"avg\": false,\n                    \"current\": false,\n                    \"hideEmpty\": true,\n                    \"hideZero\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": false,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": false\n                },\n                \"lines\": true,\n                \"linewidth\": 2,\n                \"links\": [\n\n                ],\n                \"minSpan\": 12,\n                \"nullPointMode\": \"connected\",\n                \"paceLength\": 10,\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"span\": 12,\n                \"stack\": true,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 1,\n                        \"legendFormat\": \"{{`{{`}}workload{{`}}`}}\",\n                        \"refId\": \"A\",\n                        \"step\": 10\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Receive Bandwidth\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 2,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 2,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 12,\n                    \"x\": 12,\n                    \"y\": 38\n                },\n                \"id\": 11,\n                \"legend\": {\n                    \"alignAsTable\": false,\n                    \"avg\": false,\n                    \"current\": false,\n                    \"hideEmpty\": true,\n                    \"hideZero\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": false,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": false\n                },\n                \"lines\": true,\n                \"linewidth\": 2,\n                \"links\": [\n\n                ],\n                \"minSpan\": 12,\n                \"nullPointMode\": \"connected\",\n                \"paceLength\": 10,\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"span\": 12,\n                \"stack\": true,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 1,\n                        \"legendFormat\": \"{{`{{`}}workload{{`}}`}}\",\n                        \"refId\": \"A\",\n                        \"step\": 10\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Transmit Bandwidth\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 2,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"collapse\": true,\n                \"collapsed\": true,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 39\n                },\n                \"id\": 12,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 9,\n                            \"w\": 12,\n                            \"x\": 0,\n                            \"y\": 40\n                        },\n                        \"id\": 13,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 12,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sort_desc(sum(irate(container_network_receive_packets_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}workload{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Received Packets\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 9,\n                            \"w\": 12,\n                            \"x\": 12,\n                            \"y\": 40\n                        },\n                        \"id\": 14,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 12,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sort_desc(sum(irate(container_network_transmit_packets_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}workload{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Transmitted Packets\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Packets\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": true,\n                \"collapsed\": true,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 40\n                },\n                \"id\": 15,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 9,\n                            \"w\": 12,\n                            \"x\": 0,\n                            \"y\": 41\n                        },\n                        \"id\": 16,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 12,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sort_desc(sum(irate(container_network_receive_packets_dropped_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}workload{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Received Packets Dropped\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 9,\n                            \"w\": 12,\n                            \"x\": 12,\n                            \"y\": 41\n                        },\n                        \"id\": 17,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 12,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sort_desc(sum(irate(container_network_transmit_packets_dropped_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\".+\\\", workload_type=\\\"$type\\\"}) by (workload))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}workload{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Transmitted Packets Dropped\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Errors\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            }\n        ],\n        \"refresh\": \"10s\",\n        \"rows\": [\n\n        ],\n        \"schemaVersion\": 18,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"kubernetes-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }},\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"cluster\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_info, cluster)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 0,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"auto\": false,\n                    \"auto_count\": 30,\n                    \"auto_min\": \"10s\",\n                    \"current\": {\n                        \"text\": \"kube-system\",\n                        \"value\": \"kube-system\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"definition\": \"label_values(container_network_receive_packets_total{cluster=\\\"$cluster\\\"}, namespace)\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"namespace\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(container_network_receive_packets_total{cluster=\\\"$cluster\\\"}, namespace)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"skipUrlSync\": false,\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"auto\": false,\n                    \"auto_count\": 30,\n                    \"auto_min\": \"10s\",\n                    \"current\": {\n                        \"text\": \"deployment\",\n                        \"value\": \"deployment\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"definition\": \"label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\".+\\\"}, workload_type)\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"type\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\".+\\\"}, workload_type)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"skipUrlSync\": false,\n                    \"sort\": 0,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"auto\": false,\n                    \"auto_count\": 30,\n                    \"auto_min\": \"10s\",\n                    \"current\": {\n                        \"text\": \"5m\",\n                        \"value\": \"5m\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"resolution\",\n                    \"options\": [\n                        {\n                            \"selected\": false,\n                            \"text\": \"30s\",\n                            \"value\": \"30s\"\n                        },\n                        {\n                            \"selected\": true,\n                            \"text\": \"5m\",\n                            \"value\": \"5m\"\n                        },\n                        {\n                            \"selected\": false,\n                            \"text\": \"1h\",\n                            \"value\": \"1h\"\n                        }\n                    ],\n                    \"query\": \"30s,5m,1h\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"skipUrlSync\": false,\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"interval\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"auto\": false,\n                    \"auto_count\": 30,\n                    \"auto_min\": \"10s\",\n                    \"current\": {\n                        \"text\": \"5m\",\n                        \"value\": \"5m\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 2,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"interval\",\n                    \"options\": [\n                        {\n                            \"selected\": true,\n                            \"text\": \"4h\",\n                            \"value\": \"4h\"\n                        }\n                    ],\n                    \"query\": \"4h\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"skipUrlSync\": false,\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"interval\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"UTC\",\n        \"title\": \"Kubernetes / Networking / Namespace (Workload)\",\n        \"uid\": \"bbb2a765a623ae38130206c7d94a160f\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/node-cluster-rsrc-use.yaml",
    "content": "{{- /*\nGenerated from 'node-cluster-rsrc-use' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled .Values.nodeExporter.enabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"node-cluster-rsrc-use\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  node-cluster-rsrc-use.json: |-\n    {\n        \"annotations\": {\n            \"list\": [\n\n            ]\n        },\n        \"editable\": true,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"links\": [\n\n        ],\n        \"refresh\": \"10s\",\n        \"rows\": [\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 1,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(\\n  instance:node_cpu_utilisation:rate5m{job=\\\"node-exporter\\\"}\\n*\\n  instance:node_num_cpu:sum{job=\\\"node-exporter\\\"}\\n)\\n/ scalar(sum(instance:node_num_cpu:sum{job=\\\"node-exporter\\\"}))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"legendLink\": \"/dashboard/file/node-rsrc-use.json\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Utilisation\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": 1,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 2,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"instance:node_load1_per_cpu:ratio{job=\\\"node-exporter\\\"}\\n/ scalar(count(instance:node_load1_per_cpu:ratio{job=\\\"node-exporter\\\"}))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"legendLink\": \"/dashboard/file/node-rsrc-use.json\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Saturation (load1 per CPU)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": 1,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"CPU\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 3,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"instance:node_memory_utilisation:ratio{job=\\\"node-exporter\\\"}\\n/ scalar(count(instance:node_memory_utilisation:ratio{job=\\\"node-exporter\\\"}))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"legendLink\": \"/dashboard/file/node-rsrc-use.json\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Utilisation\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": 1,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 4,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"instance:node_vmstat_pgmajfault:rate5m{job=\\\"node-exporter\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"legendLink\": \"/dashboard/file/node-rsrc-use.json\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Saturation (Major Page Faults)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"rps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Memory\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 5,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n                            {\n                                \"alias\": \"/ Receive/\",\n                                \"stack\": \"A\"\n                            },\n                            {\n                                \"alias\": \"/ Transmit/\",\n                                \"stack\": \"B\",\n                                \"transform\": \"negative-Y\"\n                            }\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"instance:node_network_receive_bytes_excluding_lo:rate5m{job=\\\"node-exporter\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} Receive\",\n                                \"legendLink\": \"/dashboard/file/node-rsrc-use.json\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"instance:node_network_transmit_bytes_excluding_lo:rate5m{job=\\\"node-exporter\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} Transmit\",\n                                \"legendLink\": \"/dashboard/file/node-rsrc-use.json\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Net Utilisation (Bytes Receive/Transmit)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 6,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n                            {\n                                \"alias\": \"/ Receive/\",\n                                \"stack\": \"A\"\n                            },\n                            {\n                                \"alias\": \"/ Transmit/\",\n                                \"stack\": \"B\",\n                                \"transform\": \"negative-Y\"\n                            }\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"instance:node_network_receive_drop_excluding_lo:rate5m{job=\\\"node-exporter\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} Receive\",\n                                \"legendLink\": \"/dashboard/file/node-rsrc-use.json\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"instance:node_network_transmit_drop_excluding_lo:rate5m{job=\\\"node-exporter\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} Transmit\",\n                                \"legendLink\": \"/dashboard/file/node-rsrc-use.json\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Net Saturation (Drops Receive/Transmit)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"rps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Network\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 7,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"instance_device:node_disk_io_time_seconds:rate5m{job=\\\"node-exporter\\\"}\\n/ scalar(count(instance_device:node_disk_io_time_seconds:rate5m{job=\\\"node-exporter\\\"}))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} {{`{{`}}device{{`}}`}}\",\n                                \"legendLink\": \"/dashboard/file/node-rsrc-use.json\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Disk IO Utilisation\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": 1,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 8,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"instance_device:node_disk_io_time_weighted_seconds:rate5m{job=\\\"node-exporter\\\"}\\n/ scalar(count(instance_device:node_disk_io_time_weighted_seconds:rate5m{job=\\\"node-exporter\\\"}))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}} {{`{{`}}device{{`}}`}}\",\n                                \"legendLink\": \"/dashboard/file/node-rsrc-use.json\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Disk IO Saturation\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": 1,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Disk IO\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 9,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum without (device) (\\n  max without (fstype, mountpoint) (\\n    node_filesystem_size_bytes{job=\\\"node-exporter\\\", fstype!=\\\"\\\"} - node_filesystem_avail_bytes{job=\\\"node-exporter\\\", fstype!=\\\"\\\"}\\n  )\\n) \\n/ scalar(sum(max without (fstype, mountpoint) (node_filesystem_size_bytes{job=\\\"node-exporter\\\", fstype!=\\\"\\\"})))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"legendLink\": \"/dashboard/file/node-rsrc-use.json\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Disk Space Utilisation\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": 1,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Disk Space\",\n                \"titleSize\": \"h6\"\n            }\n        ],\n        \"schemaVersion\": 14,\n        \"style\": \"dark\",\n        \"tags\": [\n\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"utc\",\n        \"title\": \"USE Method / Cluster\",\n        \"uid\": \"\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/node-rsrc-use.yaml",
    "content": "{{- /*\nGenerated from 'node-rsrc-use' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled .Values.nodeExporter.enabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"node-rsrc-use\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  node-rsrc-use.json: |-\n    {\n        \"annotations\": {\n            \"list\": [\n\n            ]\n        },\n        \"editable\": true,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"links\": [\n\n        ],\n        \"refresh\": \"10s\",\n        \"rows\": [\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 1,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": false,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"instance:node_cpu_utilisation:rate5m{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"Utilisation\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Utilisation\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 2,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": false,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"instance:node_load1_per_cpu:ratio{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"Saturation\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Saturation (Load1 per CPU)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"CPU\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 3,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"instance:node_memory_utilisation:ratio{job=\\\"node-exporter\\\", job=\\\"node-exporter\\\", instance=\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"Memory\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Utilisation\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 4,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": false,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"instance:node_vmstat_pgmajfault:rate5m{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"Major page faults\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Saturation (Major Page Faults)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Memory\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 5,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n                            {\n                                \"alias\": \"/Receive/\",\n                                \"stack\": \"A\"\n                            },\n                            {\n                                \"alias\": \"/Transmit/\",\n                                \"stack\": \"B\",\n                                \"transform\": \"negative-Y\"\n                            }\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"instance:node_network_receive_bytes_excluding_lo:rate5m{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"Receive\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"instance:node_network_transmit_bytes_excluding_lo:rate5m{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"Transmit\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Net Utilisation (Bytes Receive/Transmit)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 6,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n                            {\n                                \"alias\": \"/Receive/\",\n                                \"stack\": \"A\"\n                            },\n                            {\n                                \"alias\": \"/Transmit/\",\n                                \"stack\": \"B\",\n                                \"transform\": \"negative-Y\"\n                            }\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"instance:node_network_receive_drop_excluding_lo:rate5m{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"Receive drops\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"instance:node_network_transmit_drop_excluding_lo:rate5m{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"Transmit drops\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Net Saturation (Drops Receive/Transmit)\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"rps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Net\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 7,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"instance_device:node_disk_io_time_seconds:rate5m{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}device{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Disk IO Utilisation\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 8,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"instance_device:node_disk_io_time_weighted_seconds:rate5m{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}device{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Disk IO Saturation\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Disk IO\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 9,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": false,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"1 -\\n(\\n  max without (mountpoint, fstype) (node_filesystem_avail_bytes{job=\\\"node-exporter\\\", fstype!=\\\"\\\", instance=\\\"$instance\\\"})\\n/\\n  max without (mountpoint, fstype) (node_filesystem_size_bytes{job=\\\"node-exporter\\\", fstype!=\\\"\\\", instance=\\\"$instance\\\"})\\n)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}device{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Disk Space Utilisation\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Disk Space\",\n                \"titleSize\": \"h6\"\n            }\n        ],\n        \"schemaVersion\": 14,\n        \"style\": \"dark\",\n        \"tags\": [\n\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": \"prod\",\n                        \"value\": \"prod\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": \"instance\",\n                    \"multi\": false,\n                    \"name\": \"instance\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(up{job=\\\"node-exporter\\\"}, instance)\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"sort\": 2,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"utc\",\n        \"title\": \"USE Method / Node\",\n        \"uid\": \"\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/nodes.yaml",
    "content": "{{- /*\nGenerated from 'nodes' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"nodes\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  nodes.json: |-\n    {\n        \"__inputs\": [\n\n        ],\n        \"__requires\": [\n\n        ],\n        \"annotations\": {\n            \"list\": [\n\n            ]\n        },\n        \"editable\": false,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"id\": null,\n        \"links\": [\n\n        ],\n        \"refresh\": \"\",\n        \"rows\": [\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 2,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(\\n  (1 - rate(node_cpu_seconds_total{job=\\\"node-exporter\\\", mode=\\\"idle\\\", instance=\\\"$instance\\\"}[$__rate_interval]))\\n/ ignoring(cpu) group_left\\n  count without (cpu)( node_cpu_seconds_total{job=\\\"node-exporter\\\", mode=\\\"idle\\\", instance=\\\"$instance\\\"})\\n)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 5,\n                                \"legendFormat\": \"{{`{{`}}cpu{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU Usage\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": 1,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"percentunit\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": 1,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 0,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 3,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"node_load1{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"1m load average\",\n                                \"refId\": \"A\"\n                            },\n                            {\n                                \"expr\": \"node_load5{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"5m load average\",\n                                \"refId\": \"B\"\n                            },\n                            {\n                                \"expr\": \"node_load15{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"15m load average\",\n                                \"refId\": \"C\"\n                            },\n                            {\n                                \"expr\": \"count(node_cpu_seconds_total{job=\\\"node-exporter\\\", instance=\\\"$instance\\\", mode=\\\"idle\\\"})\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"logical cores\",\n                                \"refId\": \"D\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Load Average\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 4,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 9,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(\\n  node_memory_MemTotal_bytes{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"}\\n-\\n  node_memory_MemFree_bytes{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"}\\n-\\n  node_memory_Buffers_bytes{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"}\\n-\\n  node_memory_Cached_bytes{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"}\\n)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"memory used\",\n                                \"refId\": \"A\"\n                            },\n                            {\n                                \"expr\": \"node_memory_Buffers_bytes{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"memory buffers\",\n                                \"refId\": \"B\"\n                            },\n                            {\n                                \"expr\": \"node_memory_Cached_bytes{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"memory cached\",\n                                \"refId\": \"C\"\n                            },\n                            {\n                                \"expr\": \"node_memory_MemFree_bytes{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"memory free\",\n                                \"refId\": \"D\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory Usage\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"cacheTimeout\": null,\n                        \"colorBackground\": false,\n                        \"colorValue\": false,\n                        \"colors\": [\n                            \"rgba(50, 172, 45, 0.97)\",\n                            \"rgba(237, 129, 40, 0.89)\",\n                            \"rgba(245, 54, 54, 0.9)\"\n                        ],\n                        \"datasource\": \"$datasource\",\n                        \"format\": \"percent\",\n                        \"gauge\": {\n                            \"maxValue\": 100,\n                            \"minValue\": 0,\n                            \"show\": true,\n                            \"thresholdLabels\": false,\n                            \"thresholdMarkers\": true\n                        },\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 5,\n                        \"interval\": null,\n                        \"links\": [\n\n                        ],\n                        \"mappingType\": 1,\n                        \"mappingTypes\": [\n                            {\n                                \"name\": \"value to text\",\n                                \"value\": 1\n                            },\n                            {\n                                \"name\": \"range to text\",\n                                \"value\": 2\n                            }\n                        ],\n                        \"maxDataPoints\": 100,\n                        \"nullPointMode\": \"connected\",\n                        \"nullText\": null,\n                        \"postfix\": \"\",\n                        \"postfixFontSize\": \"50%\",\n                        \"prefix\": \"\",\n                        \"prefixFontSize\": \"50%\",\n                        \"rangeMaps\": [\n                            {\n                                \"from\": \"null\",\n                                \"text\": \"N/A\",\n                                \"to\": \"null\"\n                            }\n                        ],\n                        \"span\": 3,\n                        \"sparkline\": {\n                            \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                            \"full\": false,\n                            \"lineColor\": \"rgb(31, 120, 193)\",\n                            \"show\": false\n                        },\n                        \"tableColumn\": \"\",\n                        \"targets\": [\n                            {\n                                \"expr\": \"100 -\\n(\\n  avg(node_memory_MemAvailable_bytes{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"})\\n/\\n  avg(node_memory_MemTotal_bytes{job=\\\"node-exporter\\\", instance=\\\"$instance\\\"})\\n* 100\\n)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"80, 90\",\n                        \"title\": \"Memory Usage\",\n                        \"type\": \"singlestat\",\n                        \"valueFontSize\": \"80%\",\n                        \"valueMaps\": [\n                            {\n                                \"op\": \"=\",\n                                \"text\": \"N/A\",\n                                \"value\": \"null\"\n                            }\n                        ],\n                        \"valueName\": \"current\"\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 0,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 6,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n                            {\n                                \"alias\": \"/ read| written/\",\n                                \"yaxis\": 1\n                            },\n                            {\n                                \"alias\": \"/ io time/\",\n                                \"yaxis\": 2\n                            }\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"rate(node_disk_read_bytes_total{job=\\\"node-exporter\\\", instance=\\\"$instance\\\", device=~\\\"mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+\\\"}[$__rate_interval])\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}device{{`}}`}} read\",\n                                \"refId\": \"A\"\n                            },\n                            {\n                                \"expr\": \"rate(node_disk_written_bytes_total{job=\\\"node-exporter\\\", instance=\\\"$instance\\\", device=~\\\"mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+\\\"}[$__rate_interval])\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}device{{`}}`}} written\",\n                                \"refId\": \"B\"\n                            },\n                            {\n                                \"expr\": \"rate(node_disk_io_time_seconds_total{job=\\\"node-exporter\\\", instance=\\\"$instance\\\", device=~\\\"mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+\\\"}[$__rate_interval])\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}device{{`}}`}} io time\",\n                                \"refId\": \"C\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Disk I/O\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 7,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n                            {\n                                \"alias\": \"used\",\n                                \"color\": \"#E0B400\"\n                            },\n                            {\n                                \"alias\": \"available\",\n                                \"color\": \"#73BF69\"\n                            }\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(\\n  max by (device) (\\n    node_filesystem_size_bytes{job=\\\"node-exporter\\\", instance=\\\"$instance\\\", fstype!=\\\"\\\"}\\n  -\\n    node_filesystem_avail_bytes{job=\\\"node-exporter\\\", instance=\\\"$instance\\\", fstype!=\\\"\\\"}\\n  )\\n)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"used\",\n                                \"refId\": \"A\"\n                            },\n                            {\n                                \"expr\": \"sum(\\n  max by (device) (\\n    node_filesystem_avail_bytes{job=\\\"node-exporter\\\", instance=\\\"$instance\\\", fstype!=\\\"\\\"}\\n  )\\n)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"available\",\n                                \"refId\": \"B\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Disk Space Usage\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 0,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 8,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"rate(node_network_receive_bytes_total{job=\\\"node-exporter\\\", instance=\\\"$instance\\\", device!=\\\"lo\\\"}[$__rate_interval])\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}device{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Network Received\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 0,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 9,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"rate(node_network_transmit_bytes_total{job=\\\"node-exporter\\\", instance=\\\"$instance\\\", device!=\\\"lo\\\"}[$__rate_interval])\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}device{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Network Transmitted\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            }\n        ],\n        \"schemaVersion\": 14,\n        \"style\": \"dark\",\n        \"tags\": [\n\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"Prometheus\",\n                        \"value\": \"Prometheus\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"instance\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(node_exporter_build_info{job=\\\"node-exporter\\\"}, instance)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 0,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"browser\",\n        \"title\": \"Nodes\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/persistentvolumesusage.yaml",
    "content": "{{- /*\nGenerated from 'persistentvolumesusage' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"persistentvolumesusage\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  persistentvolumesusage.json: |-\n    {\n        \"__inputs\": [\n\n        ],\n        \"__requires\": [\n\n        ],\n        \"annotations\": {\n            \"list\": [\n\n            ]\n        },\n        \"editable\": false,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"id\": null,\n        \"links\": [\n\n        ],\n        \"refresh\": \"10s\",\n        \"rows\": [\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 2,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": true,\n                            \"current\": true,\n                            \"max\": true,\n                            \"min\": true,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 9,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(\\n  sum without(instance, node) (topk(1, (kubelet_volume_stats_capacity_bytes{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", namespace=\\\"$namespace\\\", persistentvolumeclaim=\\\"$volume\\\"})))\\n  -\\n  sum without(instance, node) (topk(1, (kubelet_volume_stats_available_bytes{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", namespace=\\\"$namespace\\\", persistentvolumeclaim=\\\"$volume\\\"})))\\n)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"Used Space\",\n                                \"refId\": \"A\"\n                            },\n                            {\n                                \"expr\": \"sum without(instance, node) (topk(1, (kubelet_volume_stats_available_bytes{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", namespace=\\\"$namespace\\\", persistentvolumeclaim=\\\"$volume\\\"})))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"Free Space\",\n                                \"refId\": \"B\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Volume Space Usage\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"cacheTimeout\": null,\n                        \"colorBackground\": false,\n                        \"colorValue\": false,\n                        \"colors\": [\n                            \"rgba(50, 172, 45, 0.97)\",\n                            \"rgba(237, 129, 40, 0.89)\",\n                            \"rgba(245, 54, 54, 0.9)\"\n                        ],\n                        \"datasource\": \"$datasource\",\n                        \"format\": \"percent\",\n                        \"gauge\": {\n                            \"maxValue\": 100,\n                            \"minValue\": 0,\n                            \"show\": true,\n                            \"thresholdLabels\": false,\n                            \"thresholdMarkers\": true\n                        },\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 3,\n                        \"interval\": null,\n                        \"links\": [\n\n                        ],\n                        \"mappingType\": 1,\n                        \"mappingTypes\": [\n                            {\n                                \"name\": \"value to text\",\n                                \"value\": 1\n                            },\n                            {\n                                \"name\": \"range to text\",\n                                \"value\": 2\n                            }\n                        ],\n                        \"maxDataPoints\": 100,\n                        \"nullPointMode\": \"connected\",\n                        \"nullText\": null,\n                        \"postfix\": \"\",\n                        \"postfixFontSize\": \"50%\",\n                        \"prefix\": \"\",\n                        \"prefixFontSize\": \"50%\",\n                        \"rangeMaps\": [\n                            {\n                                \"from\": \"null\",\n                                \"text\": \"N/A\",\n                                \"to\": \"null\"\n                            }\n                        ],\n                        \"span\": 3,\n                        \"sparkline\": {\n                            \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                            \"full\": false,\n                            \"lineColor\": \"rgb(31, 120, 193)\",\n                            \"show\": false\n                        },\n                        \"tableColumn\": \"\",\n                        \"targets\": [\n                            {\n                                \"expr\": \"max without(instance,node) (\\n(\\n  topk(1, kubelet_volume_stats_capacity_bytes{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", namespace=\\\"$namespace\\\", persistentvolumeclaim=\\\"$volume\\\"})\\n  -\\n  topk(1, kubelet_volume_stats_available_bytes{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", namespace=\\\"$namespace\\\", persistentvolumeclaim=\\\"$volume\\\"})\\n)\\n/\\ntopk(1, kubelet_volume_stats_capacity_bytes{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", namespace=\\\"$namespace\\\", persistentvolumeclaim=\\\"$volume\\\"})\\n* 100)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"80, 90\",\n                        \"title\": \"Volume Space Usage\",\n                        \"tooltip\": {\n                            \"shared\": false\n                        },\n                        \"type\": \"singlestat\",\n                        \"valueFontSize\": \"80%\",\n                        \"valueMaps\": [\n                            {\n                                \"op\": \"=\",\n                                \"text\": \"N/A\",\n                                \"value\": \"null\"\n                            }\n                        ],\n                        \"valueName\": \"current\"\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 4,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": true,\n                            \"current\": true,\n                            \"max\": true,\n                            \"min\": true,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 9,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes_used{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", namespace=\\\"$namespace\\\", persistentvolumeclaim=\\\"$volume\\\"})))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"Used inodes\",\n                                \"refId\": \"A\"\n                            },\n                            {\n                                \"expr\": \"(\\n  sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", namespace=\\\"$namespace\\\", persistentvolumeclaim=\\\"$volume\\\"})))\\n  -\\n  sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes_used{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", namespace=\\\"$namespace\\\", persistentvolumeclaim=\\\"$volume\\\"})))\\n)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \" Free inodes\",\n                                \"refId\": \"B\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Volume inodes Usage\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"none\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"none\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"cacheTimeout\": null,\n                        \"colorBackground\": false,\n                        \"colorValue\": false,\n                        \"colors\": [\n                            \"rgba(50, 172, 45, 0.97)\",\n                            \"rgba(237, 129, 40, 0.89)\",\n                            \"rgba(245, 54, 54, 0.9)\"\n                        ],\n                        \"datasource\": \"$datasource\",\n                        \"format\": \"percent\",\n                        \"gauge\": {\n                            \"maxValue\": 100,\n                            \"minValue\": 0,\n                            \"show\": true,\n                            \"thresholdLabels\": false,\n                            \"thresholdMarkers\": true\n                        },\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 5,\n                        \"interval\": null,\n                        \"links\": [\n\n                        ],\n                        \"mappingType\": 1,\n                        \"mappingTypes\": [\n                            {\n                                \"name\": \"value to text\",\n                                \"value\": 1\n                            },\n                            {\n                                \"name\": \"range to text\",\n                                \"value\": 2\n                            }\n                        ],\n                        \"maxDataPoints\": 100,\n                        \"nullPointMode\": \"connected\",\n                        \"nullText\": null,\n                        \"postfix\": \"\",\n                        \"postfixFontSize\": \"50%\",\n                        \"prefix\": \"\",\n                        \"prefixFontSize\": \"50%\",\n                        \"rangeMaps\": [\n                            {\n                                \"from\": \"null\",\n                                \"text\": \"N/A\",\n                                \"to\": \"null\"\n                            }\n                        ],\n                        \"span\": 3,\n                        \"sparkline\": {\n                            \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                            \"full\": false,\n                            \"lineColor\": \"rgb(31, 120, 193)\",\n                            \"show\": false\n                        },\n                        \"tableColumn\": \"\",\n                        \"targets\": [\n                            {\n                                \"expr\": \"max without(instance,node) (\\ntopk(1, kubelet_volume_stats_inodes_used{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", namespace=\\\"$namespace\\\", persistentvolumeclaim=\\\"$volume\\\"})\\n/\\ntopk(1, kubelet_volume_stats_inodes{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", namespace=\\\"$namespace\\\", persistentvolumeclaim=\\\"$volume\\\"})\\n* 100)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"80, 90\",\n                        \"title\": \"Volume inodes Usage\",\n                        \"tooltip\": {\n                            \"shared\": false\n                        },\n                        \"type\": \"singlestat\",\n                        \"valueFontSize\": \"80%\",\n                        \"valueMaps\": [\n                            {\n                                \"op\": \"=\",\n                                \"text\": \"N/A\",\n                                \"value\": \"null\"\n                            }\n                        ],\n                        \"valueName\": \"current\"\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            }\n        ],\n        \"schemaVersion\": 14,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"kubernetes-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }},\n                    \"includeAll\": false,\n                    \"label\": \"cluster\",\n                    \"multi\": false,\n                    \"name\": \"cluster\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kubelet_volume_stats_capacity_bytes, cluster)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": \"Namespace\",\n                    \"multi\": false,\n                    \"name\": \"namespace\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kubelet_volume_stats_capacity_bytes{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\"}, namespace)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": \"PersistentVolumeClaim\",\n                    \"multi\": false,\n                    \"name\": \"volume\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kubelet_volume_stats_capacity_bytes{cluster=\\\"$cluster\\\", job=\\\"kubelet\\\", metrics_path=\\\"/metrics\\\", namespace=\\\"$namespace\\\"}, persistentvolumeclaim)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-7d\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"UTC\",\n        \"title\": \"Kubernetes / Persistent Volumes\",\n        \"uid\": \"919b92a8e8041bd567af9edab12c840c\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/pod-total.yaml",
    "content": "{{- /*\nGenerated from 'pod-total' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"pod-total\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  pod-total.json: |-\n    {\n        \"__inputs\": [\n\n        ],\n        \"__requires\": [\n\n        ],\n        \"annotations\": {\n            \"list\": [\n                {\n                    \"builtIn\": 1,\n                    \"datasource\": \"-- Grafana --\",\n                    \"enable\": true,\n                    \"hide\": true,\n                    \"iconColor\": \"rgba(0, 211, 255, 1)\",\n                    \"name\": \"Annotations & Alerts\",\n                    \"type\": \"dashboard\"\n                }\n            ]\n        },\n        \"editable\": true,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"id\": null,\n        \"links\": [\n\n        ],\n        \"panels\": [\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 0\n                },\n                \"id\": 2,\n                \"panels\": [\n\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Current Bandwidth\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"cacheTimeout\": null,\n                \"colorBackground\": false,\n                \"colorValue\": false,\n                \"colors\": [\n                    \"#299c46\",\n                    \"rgba(237, 129, 40, 0.89)\",\n                    \"#d44a3a\"\n                ],\n                \"datasource\": \"$datasource\",\n                \"decimals\": 0,\n                \"format\": \"time_series\",\n                \"gauge\": {\n                    \"maxValue\": 100,\n                    \"minValue\": 0,\n                    \"show\": false,\n                    \"thresholdLabels\": false,\n                    \"thresholdMarkers\": true\n                },\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 12,\n                    \"x\": 0,\n                    \"y\": 1\n                },\n                \"height\": 9,\n                \"id\": 3,\n                \"interval\": null,\n                \"links\": [\n\n                ],\n                \"mappingType\": 1,\n                \"mappingTypes\": [\n                    {\n                        \"name\": \"value to text\",\n                        \"value\": 1\n                    },\n                    {\n                        \"name\": \"range to text\",\n                        \"value\": 2\n                    }\n                ],\n                \"maxDataPoints\": 100,\n                \"minSpan\": 12,\n                \"nullPointMode\": \"connected\",\n                \"nullText\": null,\n                \"options\": {\n                    \"fieldOptions\": {\n                        \"calcs\": [\n                            \"last\"\n                        ],\n                        \"defaults\": {\n                            \"max\": 10000000000,\n                            \"min\": 0,\n                            \"title\": \"$namespace: $pod\",\n                            \"unit\": \"Bps\"\n                        },\n                        \"mappings\": [\n\n                        ],\n                        \"override\": {\n\n                        },\n                        \"thresholds\": [\n                            {\n                                \"color\": \"dark-green\",\n                                \"index\": 0,\n                                \"value\": null\n                            },\n                            {\n                                \"color\": \"dark-yellow\",\n                                \"index\": 1,\n                                \"value\": 5000000000\n                            },\n                            {\n                                \"color\": \"dark-red\",\n                                \"index\": 2,\n                                \"value\": 7000000000\n                            }\n                        ],\n                        \"values\": false\n                    }\n                },\n                \"postfix\": \"\",\n                \"postfixFontSize\": \"50%\",\n                \"prefix\": \"\",\n                \"prefixFontSize\": \"50%\",\n                \"rangeMaps\": [\n                    {\n                        \"from\": \"null\",\n                        \"text\": \"N/A\",\n                        \"to\": \"null\"\n                    }\n                ],\n                \"span\": 12,\n                \"sparkline\": {\n                    \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                    \"full\": false,\n                    \"lineColor\": \"rgb(31, 120, 193)\",\n                    \"show\": false\n                },\n                \"tableColumn\": \"\",\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=~\\\"$pod\\\"}[$interval:$resolution]))\",\n                        \"format\": \"time_series\",\n                        \"instant\": null,\n                        \"intervalFactor\": 1,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"thresholds\": \"\",\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Current Rate of Bytes Received\",\n                \"type\": \"gauge\",\n                \"valueFontSize\": \"80%\",\n                \"valueMaps\": [\n                    {\n                        \"op\": \"=\",\n                        \"text\": \"N/A\",\n                        \"value\": \"null\"\n                    }\n                ],\n                \"valueName\": \"current\"\n            },\n            {\n                \"cacheTimeout\": null,\n                \"colorBackground\": false,\n                \"colorValue\": false,\n                \"colors\": [\n                    \"#299c46\",\n                    \"rgba(237, 129, 40, 0.89)\",\n                    \"#d44a3a\"\n                ],\n                \"datasource\": \"$datasource\",\n                \"decimals\": 0,\n                \"format\": \"time_series\",\n                \"gauge\": {\n                    \"maxValue\": 100,\n                    \"minValue\": 0,\n                    \"show\": false,\n                    \"thresholdLabels\": false,\n                    \"thresholdMarkers\": true\n                },\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 12,\n                    \"x\": 12,\n                    \"y\": 1\n                },\n                \"height\": 9,\n                \"id\": 4,\n                \"interval\": null,\n                \"links\": [\n\n                ],\n                \"mappingType\": 1,\n                \"mappingTypes\": [\n                    {\n                        \"name\": \"value to text\",\n                        \"value\": 1\n                    },\n                    {\n                        \"name\": \"range to text\",\n                        \"value\": 2\n                    }\n                ],\n                \"maxDataPoints\": 100,\n                \"minSpan\": 12,\n                \"nullPointMode\": \"connected\",\n                \"nullText\": null,\n                \"options\": {\n                    \"fieldOptions\": {\n                        \"calcs\": [\n                            \"last\"\n                        ],\n                        \"defaults\": {\n                            \"max\": 10000000000,\n                            \"min\": 0,\n                            \"title\": \"$namespace: $pod\",\n                            \"unit\": \"Bps\"\n                        },\n                        \"mappings\": [\n\n                        ],\n                        \"override\": {\n\n                        },\n                        \"thresholds\": [\n                            {\n                                \"color\": \"dark-green\",\n                                \"index\": 0,\n                                \"value\": null\n                            },\n                            {\n                                \"color\": \"dark-yellow\",\n                                \"index\": 1,\n                                \"value\": 5000000000\n                            },\n                            {\n                                \"color\": \"dark-red\",\n                                \"index\": 2,\n                                \"value\": 7000000000\n                            }\n                        ],\n                        \"values\": false\n                    }\n                },\n                \"postfix\": \"\",\n                \"postfixFontSize\": \"50%\",\n                \"prefix\": \"\",\n                \"prefixFontSize\": \"50%\",\n                \"rangeMaps\": [\n                    {\n                        \"from\": \"null\",\n                        \"text\": \"N/A\",\n                        \"to\": \"null\"\n                    }\n                ],\n                \"span\": 12,\n                \"sparkline\": {\n                    \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                    \"full\": false,\n                    \"lineColor\": \"rgb(31, 120, 193)\",\n                    \"show\": false\n                },\n                \"tableColumn\": \"\",\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=~\\\"$pod\\\"}[$interval:$resolution]))\",\n                        \"format\": \"time_series\",\n                        \"instant\": null,\n                        \"intervalFactor\": 1,\n                        \"legendFormat\": \"\",\n                        \"refId\": \"A\"\n                    }\n                ],\n                \"thresholds\": \"\",\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Current Rate of Bytes Transmitted\",\n                \"type\": \"gauge\",\n                \"valueFontSize\": \"80%\",\n                \"valueMaps\": [\n                    {\n                        \"op\": \"=\",\n                        \"text\": \"N/A\",\n                        \"value\": \"null\"\n                    }\n                ],\n                \"valueName\": \"current\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 10\n                },\n                \"id\": 5,\n                \"panels\": [\n\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Bandwidth\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 2,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 12,\n                    \"x\": 0,\n                    \"y\": 11\n                },\n                \"id\": 6,\n                \"legend\": {\n                    \"alignAsTable\": false,\n                    \"avg\": false,\n                    \"current\": false,\n                    \"hideEmpty\": true,\n                    \"hideZero\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": false,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": false\n                },\n                \"lines\": true,\n                \"linewidth\": 2,\n                \"links\": [\n\n                ],\n                \"minSpan\": 12,\n                \"nullPointMode\": \"connected\",\n                \"paceLength\": 10,\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"span\": 12,\n                \"stack\": true,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=~\\\"$pod\\\"}[$interval:$resolution])) by (pod)\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 1,\n                        \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                        \"refId\": \"A\",\n                        \"step\": 10\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Receive Bandwidth\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 2,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 2,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 12,\n                    \"x\": 12,\n                    \"y\": 11\n                },\n                \"id\": 7,\n                \"legend\": {\n                    \"alignAsTable\": false,\n                    \"avg\": false,\n                    \"current\": false,\n                    \"hideEmpty\": true,\n                    \"hideZero\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": false,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": false\n                },\n                \"lines\": true,\n                \"linewidth\": 2,\n                \"links\": [\n\n                ],\n                \"minSpan\": 12,\n                \"nullPointMode\": \"connected\",\n                \"paceLength\": 10,\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"span\": 12,\n                \"stack\": true,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=~\\\"$pod\\\"}[$interval:$resolution])) by (pod)\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 1,\n                        \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                        \"refId\": \"A\",\n                        \"step\": 10\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Transmit Bandwidth\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 2,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"collapse\": true,\n                \"collapsed\": true,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 20\n                },\n                \"id\": 8,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 10,\n                            \"w\": 12,\n                            \"x\": 0,\n                            \"y\": 21\n                        },\n                        \"id\": 9,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 12,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_receive_packets_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=~\\\"$pod\\\"}[$interval:$resolution])) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Received Packets\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 10,\n                            \"w\": 12,\n                            \"x\": 12,\n                            \"y\": 21\n                        },\n                        \"id\": 10,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 12,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_transmit_packets_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=~\\\"$pod\\\"}[$interval:$resolution])) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Transmitted Packets\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Packets\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": true,\n                \"collapsed\": true,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 21\n                },\n                \"id\": 11,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 10,\n                            \"w\": 12,\n                            \"x\": 0,\n                            \"y\": 32\n                        },\n                        \"id\": 12,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 12,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_receive_packets_dropped_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=~\\\"$pod\\\"}[$interval:$resolution])) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Received Packets Dropped\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 10,\n                            \"w\": 12,\n                            \"x\": 12,\n                            \"y\": 32\n                        },\n                        \"id\": 13,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 12,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(irate(container_network_transmit_packets_dropped_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", pod=~\\\"$pod\\\"}[$interval:$resolution])) by (pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Transmitted Packets Dropped\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Errors\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            }\n        ],\n        \"refresh\": \"10s\",\n        \"rows\": [\n\n        ],\n        \"schemaVersion\": 18,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"kubernetes-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }},\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"cluster\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_info, cluster)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 0,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": \".+\",\n                    \"auto\": false,\n                    \"auto_count\": 30,\n                    \"auto_min\": \"10s\",\n                    \"current\": {\n                        \"text\": \"kube-system\",\n                        \"value\": \"kube-system\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"definition\": \"label_values(container_network_receive_packets_total{cluster=\\\"$cluster\\\"}, namespace)\",\n                    \"hide\": 0,\n                    \"includeAll\": true,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"namespace\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(container_network_receive_packets_total{cluster=\\\"$cluster\\\"}, namespace)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"skipUrlSync\": false,\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": \".+\",\n                    \"auto\": false,\n                    \"auto_count\": 30,\n                    \"auto_min\": \"10s\",\n                    \"current\": {\n                        \"text\": \"\",\n                        \"value\": \"\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"definition\": \"label_values(container_network_receive_packets_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}, pod)\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"pod\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(container_network_receive_packets_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}, pod)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"skipUrlSync\": false,\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"auto\": false,\n                    \"auto_count\": 30,\n                    \"auto_min\": \"10s\",\n                    \"current\": {\n                        \"text\": \"5m\",\n                        \"value\": \"5m\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"resolution\",\n                    \"options\": [\n                        {\n                            \"selected\": false,\n                            \"text\": \"30s\",\n                            \"value\": \"30s\"\n                        },\n                        {\n                            \"selected\": true,\n                            \"text\": \"5m\",\n                            \"value\": \"5m\"\n                        },\n                        {\n                            \"selected\": false,\n                            \"text\": \"1h\",\n                            \"value\": \"1h\"\n                        }\n                    ],\n                    \"query\": \"30s,5m,1h\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"skipUrlSync\": false,\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"interval\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"auto\": false,\n                    \"auto_count\": 30,\n                    \"auto_min\": \"10s\",\n                    \"current\": {\n                        \"text\": \"5m\",\n                        \"value\": \"5m\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 2,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"interval\",\n                    \"options\": [\n                        {\n                            \"selected\": true,\n                            \"text\": \"4h\",\n                            \"value\": \"4h\"\n                        }\n                    ],\n                    \"query\": \"4h\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"skipUrlSync\": false,\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"interval\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"UTC\",\n        \"title\": \"Kubernetes / Networking / Pod\",\n        \"uid\": \"7a18067ce943a40ae25454675c19ff5c\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml",
    "content": "{{- /*\nGenerated from 'prometheus-remote-write' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled .Values.prometheus.prometheusSpec.remoteWriteDashboards }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"prometheus-remote-write\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  prometheus-remote-write.json: |-\n    {\n        \"__inputs\": [\n\n        ],\n        \"__requires\": [\n\n        ],\n        \"annotations\": {\n            \"list\": [\n\n            ]\n        },\n        \"editable\": true,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"id\": null,\n        \"links\": [\n\n        ],\n        \"refresh\": \"60s\",\n        \"rows\": [\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 2,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"(\\n  prometheus_remote_storage_highest_timestamp_in_seconds{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"} \\n-  \\n  ignoring(remote_name, url) group_right(instance) (prometheus_remote_storage_queue_highest_sent_timestamp_seconds{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"} != 0)\\n)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Highest Timestamp In vs. Highest Timestamp Sent\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 3,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"clamp_min(\\n  rate(prometheus_remote_storage_highest_timestamp_in_seconds{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}[5m])  \\n- \\n  ignoring (remote_name, url) group_right(instance) rate(prometheus_remote_storage_queue_highest_sent_timestamp_seconds{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}[5m])\\n, 0)\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate[5m]\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Timestamps\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 4,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"rate(\\n  prometheus_remote_storage_samples_in_total{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}[5m])\\n- \\n  ignoring(remote_name, url) group_right(instance) (rate(prometheus_remote_storage_succeeded_samples_total{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}[5m]) or rate(prometheus_remote_storage_samples_total{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}[5m]))\\n- \\n  (rate(prometheus_remote_storage_dropped_samples_total{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}[5m]) or rate(prometheus_remote_storage_samples_dropped_total{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}[5m]))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate, in vs. succeeded or dropped [5m]\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Samples\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 5,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 6,\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"prometheus_remote_storage_shards{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Current Shards\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 6,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"prometheus_remote_storage_shards_max{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Max Shards\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 7,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"prometheus_remote_storage_shards_min{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Min Shards\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 8,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"prometheus_remote_storage_shards_desired{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Desired Shards\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Shards\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 9,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"prometheus_remote_storage_shard_capacity{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Shard Capacity\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 10,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"prometheus_remote_storage_pending_samples{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"} or prometheus_remote_storage_samples_pending{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Pending Samples\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Shard Details\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 11,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"prometheus_tsdb_wal_segment_current{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"TSDB Current Segment\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"none\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 12,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"prometheus_wal_watcher_current_segment{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}consumer{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Remote Write Current Segment\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"none\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Segments\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 13,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 3,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"rate(prometheus_remote_storage_dropped_samples_total{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}[5m]) or rate(prometheus_remote_storage_samples_dropped_total{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}[5m])\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Dropped Samples\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 14,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 3,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"rate(prometheus_remote_storage_failed_samples_total{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}[5m]) or rate(prometheus_remote_storage_samples_failed_total{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}[5m])\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Failed Samples\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 15,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 3,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"rate(prometheus_remote_storage_retried_samples_total{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}[5m]) or rate(prometheus_remote_storage_samples_retried_total{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}[5m])\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Retried Samples\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 16,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 3,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"rate(prometheus_remote_storage_enqueue_retries_total{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}[5m])\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Enqueue Retries\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Misc. Rates\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            }\n        ],\n        \"schemaVersion\": 14,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"prometheus-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": {\n                            \"selected\": true,\n                            \"text\": \"All\",\n                            \"value\": \"$__all\"\n                        },\n                        \"value\": {\n                            \"selected\": true,\n                            \"text\": \"All\",\n                            \"value\": \"$__all\"\n                        }\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": true,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"instance\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(prometheus_build_info, instance)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 0,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n                        \"text\": {\n                            \"selected\": true,\n                            \"text\": \"All\",\n                            \"value\": \"$__all\"\n                        },\n                        \"value\": {\n                            \"selected\": true,\n                            \"text\": \"All\",\n                            \"value\": \"$__all\"\n                        }\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }},\n                    \"includeAll\": true,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"cluster\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_container_info{image=~\\\".*prometheus.*\\\"}, cluster)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 0,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": true,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"url\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(prometheus_remote_storage_shards{cluster=~\\\"$cluster\\\", instance=~\\\"$instance\\\"}, url)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 0,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-6h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"browser\",\n        \"title\": \"Prometheus / Remote Write\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/prometheus.yaml",
    "content": "{{- /*\nGenerated from 'prometheus' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"prometheus\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  prometheus.json: |-\n    {\n        \"annotations\": {\n            \"list\": [\n\n            ]\n        },\n        \"editable\": true,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"links\": [\n\n        ],\n        \"refresh\": \"60s\",\n        \"rows\": [\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 1,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"styles\": [\n                            {\n                                \"alias\": \"Time\",\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"pattern\": \"Time\",\n                                \"type\": \"hidden\"\n                            },\n                            {\n                                \"alias\": \"Count\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #A\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"hidden\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"Uptime\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"Value #B\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"Instance\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"instance\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"Job\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"job\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"Version\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"link\": false,\n                                \"linkTargetBlank\": false,\n                                \"linkTooltip\": \"Drill down\",\n                                \"linkUrl\": \"\",\n                                \"pattern\": \"version\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"number\",\n                                \"unit\": \"short\"\n                            },\n                            {\n                                \"alias\": \"\",\n                                \"colorMode\": null,\n                                \"colors\": [\n\n                                ],\n                                \"dateFormat\": \"YYYY-MM-DD HH:mm:ss\",\n                                \"decimals\": 2,\n                                \"pattern\": \"/.*/\",\n                                \"thresholds\": [\n\n                                ],\n                                \"type\": \"string\",\n                                \"unit\": \"short\"\n                            }\n                        ],\n                        \"targets\": [\n                            {\n                                \"expr\": \"count by (job, instance, version) (prometheus_build_info{job=~\\\"$job\\\", instance=~\\\"$instance\\\"})\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"max by (job, instance) (time() - process_start_time_seconds{job=~\\\"$job\\\", instance=~\\\"$instance\\\"})\",\n                                \"format\": \"table\",\n                                \"instant\": true,\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"B\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Prometheus Stats\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"transform\": \"table\",\n                        \"type\": \"table\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Prometheus Stats\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 2,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(rate(prometheus_target_sync_length_seconds_sum{job=~\\\"$job\\\",instance=~\\\"$instance\\\"}[5m])) by (scrape_job) * 1e3\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}scrape_job{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Target Sync\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"ms\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 3,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(prometheus_sd_discovered_targets{job=~\\\"$job\\\",instance=~\\\"$instance\\\"})\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"Targets\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Targets\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Discovery\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"id\": 4,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"rate(prometheus_target_interval_length_seconds_sum{job=~\\\"$job\\\",instance=~\\\"$instance\\\"}[5m]) / rate(prometheus_target_interval_length_seconds_count{job=~\\\"$job\\\",instance=~\\\"$instance\\\"}[5m]) * 1e3\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}interval{{`}}`}} configured\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Average Scrape Interval Duration\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"ms\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 5,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum by (job) (rate(prometheus_target_scrapes_exceeded_body_size_limit_total[1m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"exceeded body size limit: {{`{{`}}job{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum by (job) (rate(prometheus_target_scrapes_exceeded_sample_limit_total[1m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"exceeded sample limit: {{`{{`}}job{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum by (job) (rate(prometheus_target_scrapes_sample_duplicate_timestamp_total[1m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"duplicate timestamp: {{`{{`}}job{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum by (job) (rate(prometheus_target_scrapes_sample_out_of_bounds_total[1m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"out of bounds: {{`{{`}}job{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            },\n                            {\n                                \"expr\": \"sum by (job) (rate(prometheus_target_scrapes_sample_out_of_order_total[1m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"out of order: {{`{{`}}job{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Scrape failures\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 6,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"rate(prometheus_tsdb_head_samples_appended_total{job=~\\\"$job\\\",instance=~\\\"$instance\\\"}[5m])\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}job{{`}}`}} {{`{{`}}instance{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Appended Samples\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Retrieval\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 7,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"prometheus_tsdb_head_series{job=~\\\"$job\\\",instance=~\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}job{{`}}`}} {{`{{`}}instance{{`}}`}} head series\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Head Series\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 8,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"prometheus_tsdb_head_chunks{job=~\\\"$job\\\",instance=~\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}job{{`}}`}} {{`{{`}}instance{{`}}`}} head chunks\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Head Chunks\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Storage\",\n                \"titleSize\": \"h6\"\n            },\n            {\n                \"collapse\": false,\n                \"height\": \"250px\",\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 9,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"rate(prometheus_engine_query_duration_seconds_count{job=~\\\"$job\\\",instance=~\\\"$instance\\\",slice=\\\"inner_eval\\\"}[5m])\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}job{{`}}`}} {{`{{`}}instance{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Query Rate\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 10,\n                        \"id\": 10,\n                        \"legend\": {\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"show\": true,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 0,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null as zero\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"max by (slice) (prometheus_engine_query_duration_seconds{quantile=\\\"0.9\\\",job=~\\\"$job\\\",instance=~\\\"$instance\\\"}) * 1e3\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}slice{{`}}`}}\",\n                                \"legendLink\": null,\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Stage Duration\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"ms\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": false\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Query\",\n                \"titleSize\": \"h6\"\n            }\n        ],\n        \"schemaVersion\": 14,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"prometheus-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": \".+\",\n                    \"current\": {\n                        \"selected\": true,\n                        \"text\": \"All\",\n                        \"value\": \"$__all\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": true,\n                    \"label\": \"job\",\n                    \"multi\": true,\n                    \"name\": \"job\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(prometheus_build_info, job)\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"sort\": 2,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": \".+\",\n                    \"current\": {\n                        \"selected\": true,\n                        \"text\": \"All\",\n                        \"value\": \"$__all\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": true,\n                    \"label\": \"instance\",\n                    \"multi\": true,\n                    \"name\": \"instance\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(prometheus_build_info, instance)\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"sort\": 2,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"utc\",\n        \"title\": \"Prometheus / Overview\",\n        \"uid\": \"\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/proxy.yaml",
    "content": "{{- /*\nGenerated from 'proxy' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled .Values.kubeProxy.enabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"proxy\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  proxy.json: |-\n    {\n        \"__inputs\": [\n\n        ],\n        \"__requires\": [\n\n        ],\n        \"annotations\": {\n            \"list\": [\n\n            ]\n        },\n        \"editable\": false,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"id\": null,\n        \"links\": [\n\n        ],\n        \"refresh\": \"10s\",\n        \"rows\": [\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"cacheTimeout\": null,\n                        \"colorBackground\": false,\n                        \"colorValue\": false,\n                        \"colors\": [\n                            \"#299c46\",\n                            \"rgba(237, 129, 40, 0.89)\",\n                            \"#d44a3a\"\n                        ],\n                        \"datasource\": \"$datasource\",\n                        \"format\": \"none\",\n                        \"gauge\": {\n                            \"maxValue\": 100,\n                            \"minValue\": 0,\n                            \"show\": false,\n                            \"thresholdLabels\": false,\n                            \"thresholdMarkers\": true\n                        },\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 2,\n                        \"interval\": null,\n                        \"links\": [\n\n                        ],\n                        \"mappingType\": 1,\n                        \"mappingTypes\": [\n                            {\n                                \"name\": \"value to text\",\n                                \"value\": 1\n                            },\n                            {\n                                \"name\": \"range to text\",\n                                \"value\": 2\n                            }\n                        ],\n                        \"maxDataPoints\": 100,\n                        \"nullPointMode\": \"connected\",\n                        \"nullText\": null,\n                        \"postfix\": \"\",\n                        \"postfixFontSize\": \"50%\",\n                        \"prefix\": \"\",\n                        \"prefixFontSize\": \"50%\",\n                        \"rangeMaps\": [\n                            {\n                                \"from\": \"null\",\n                                \"text\": \"N/A\",\n                                \"to\": \"null\"\n                            }\n                        ],\n                        \"span\": 2,\n                        \"sparkline\": {\n                            \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                            \"full\": false,\n                            \"lineColor\": \"rgb(31, 120, 193)\",\n                            \"show\": false\n                        },\n                        \"tableColumn\": \"\",\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(up{cluster=\\\"$cluster\\\", job=\\\"kube-proxy\\\"})\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"\",\n                        \"title\": \"Up\",\n                        \"tooltip\": {\n                            \"shared\": false\n                        },\n                        \"type\": \"singlestat\",\n                        \"valueFontSize\": \"80%\",\n                        \"valueMaps\": [\n                            {\n                                \"op\": \"=\",\n                                \"text\": \"N/A\",\n                                \"value\": \"null\"\n                            }\n                        ],\n                        \"valueName\": \"min\"\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 3,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 5,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(rate(kubeproxy_sync_proxy_rules_duration_seconds_count{cluster=\\\"$cluster\\\", job=\\\"kube-proxy\\\", instance=~\\\"$instance\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"rate\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rules Sync Rate\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 4,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": false,\n                            \"current\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 5,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"histogram_quantile(0.99,rate(kubeproxy_sync_proxy_rules_duration_seconds_bucket{cluster=\\\"$cluster\\\", job=\\\"kube-proxy\\\", instance=~\\\"$instance\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rule Sync Latency 99th Quantile\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 5,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(rate(kubeproxy_network_programming_duration_seconds_count{cluster=\\\"$cluster\\\", job=\\\"kube-proxy\\\", instance=~\\\"$instance\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"rate\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Network Programming Rate\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 6,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": false,\n                            \"current\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 6,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"histogram_quantile(0.99, sum(rate(kubeproxy_network_programming_duration_seconds_bucket{cluster=\\\"$cluster\\\", job=\\\"kube-proxy\\\", instance=~\\\"$instance\\\"}[5m])) by (instance, le))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Network Programming Latency 99th Quantile\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 7,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(rate(rest_client_requests_total{cluster=\\\"$cluster\\\", job=\\\"kube-proxy\\\", instance=~\\\"$instance\\\",code=~\\\"2..\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"2xx\",\n                                \"refId\": \"A\"\n                            },\n                            {\n                                \"expr\": \"sum(rate(rest_client_requests_total{cluster=\\\"$cluster\\\", job=\\\"kube-proxy\\\", instance=~\\\"$instance\\\",code=~\\\"3..\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"3xx\",\n                                \"refId\": \"B\"\n                            },\n                            {\n                                \"expr\": \"sum(rate(rest_client_requests_total{cluster=\\\"$cluster\\\", job=\\\"kube-proxy\\\", instance=~\\\"$instance\\\",code=~\\\"4..\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"4xx\",\n                                \"refId\": \"C\"\n                            },\n                            {\n                                \"expr\": \"sum(rate(rest_client_requests_total{cluster=\\\"$cluster\\\", job=\\\"kube-proxy\\\", instance=~\\\"$instance\\\",code=~\\\"5..\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"5xx\",\n                                \"refId\": \"D\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Kube API Request Rate\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 8,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 8,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{cluster=\\\"$cluster\\\", job=\\\"kube-proxy\\\",instance=~\\\"$instance\\\",verb=\\\"POST\\\"}[5m])) by (verb, url, le))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}verb{{`}}`}} {{`{{`}}url{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Post Request Latency 99th Quantile\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 9,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": false,\n                            \"current\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{cluster=\\\"$cluster\\\", job=\\\"kube-proxy\\\", instance=~\\\"$instance\\\", verb=\\\"GET\\\"}[5m])) by (verb, url, le))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}verb{{`}}`}} {{`{{`}}url{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Get Request Latency 99th Quantile\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 10,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"process_resident_memory_bytes{cluster=\\\"$cluster\\\", job=\\\"kube-proxy\\\",instance=~\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 11,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"rate(process_cpu_seconds_total{cluster=\\\"$cluster\\\", job=\\\"kube-proxy\\\",instance=~\\\"$instance\\\"}[5m])\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU usage\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 12,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"go_goroutines{cluster=\\\"$cluster\\\", job=\\\"kube-proxy\\\",instance=~\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Goroutines\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            }\n        ],\n        \"schemaVersion\": 14,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"kubernetes-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }},\n                    \"includeAll\": false,\n                    \"label\": \"cluster\",\n                    \"multi\": false,\n                    \"name\": \"cluster\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_info, cluster)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": true,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"instance\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kubeproxy_network_programming_duration_seconds_bucket{cluster=\\\"$cluster\\\", job=\\\"kube-proxy\\\"}, instance)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"UTC\",\n        \"title\": \"Kubernetes / Proxy\",\n        \"uid\": \"632e265de029684c40b21cb76bca4f94\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/scheduler.yaml",
    "content": "{{- /*\nGenerated from 'scheduler' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled .Values.kubeScheduler.enabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"scheduler\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  scheduler.json: |-\n    {\n        \"__inputs\": [\n\n        ],\n        \"__requires\": [\n\n        ],\n        \"annotations\": {\n            \"list\": [\n\n            ]\n        },\n        \"editable\": false,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"id\": null,\n        \"links\": [\n\n        ],\n        \"refresh\": \"10s\",\n        \"rows\": [\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"cacheTimeout\": null,\n                        \"colorBackground\": false,\n                        \"colorValue\": false,\n                        \"colors\": [\n                            \"#299c46\",\n                            \"rgba(237, 129, 40, 0.89)\",\n                            \"#d44a3a\"\n                        ],\n                        \"datasource\": \"$datasource\",\n                        \"format\": \"none\",\n                        \"gauge\": {\n                            \"maxValue\": 100,\n                            \"minValue\": 0,\n                            \"show\": false,\n                            \"thresholdLabels\": false,\n                            \"thresholdMarkers\": true\n                        },\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 2,\n                        \"interval\": null,\n                        \"links\": [\n\n                        ],\n                        \"mappingType\": 1,\n                        \"mappingTypes\": [\n                            {\n                                \"name\": \"value to text\",\n                                \"value\": 1\n                            },\n                            {\n                                \"name\": \"range to text\",\n                                \"value\": 2\n                            }\n                        ],\n                        \"maxDataPoints\": 100,\n                        \"nullPointMode\": \"connected\",\n                        \"nullText\": null,\n                        \"postfix\": \"\",\n                        \"postfixFontSize\": \"50%\",\n                        \"prefix\": \"\",\n                        \"prefixFontSize\": \"50%\",\n                        \"rangeMaps\": [\n                            {\n                                \"from\": \"null\",\n                                \"text\": \"N/A\",\n                                \"to\": \"null\"\n                            }\n                        ],\n                        \"span\": 2,\n                        \"sparkline\": {\n                            \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                            \"full\": false,\n                            \"lineColor\": \"rgb(31, 120, 193)\",\n                            \"show\": false\n                        },\n                        \"tableColumn\": \"\",\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(up{cluster=\\\"$cluster\\\", job=\\\"kube-scheduler\\\"})\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"\",\n                        \"title\": \"Up\",\n                        \"tooltip\": {\n                            \"shared\": false\n                        },\n                        \"type\": \"singlestat\",\n                        \"valueFontSize\": \"80%\",\n                        \"valueMaps\": [\n                            {\n                                \"op\": \"=\",\n                                \"text\": \"N/A\",\n                                \"value\": \"null\"\n                            }\n                        ],\n                        \"valueName\": \"min\"\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 3,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": false,\n                            \"current\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 5,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(rate(scheduler_e2e_scheduling_duration_seconds_count{cluster=\\\"$cluster\\\", job=\\\"kube-scheduler\\\", instance=~\\\"$instance\\\"}[5m])) by (cluster, instance)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}} {{`{{`}}instance{{`}}`}} e2e\",\n                                \"refId\": \"A\"\n                            },\n                            {\n                                \"expr\": \"sum(rate(scheduler_binding_duration_seconds_count{cluster=\\\"$cluster\\\", job=\\\"kube-scheduler\\\", instance=~\\\"$instance\\\"}[5m])) by (cluster, instance)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}} {{`{{`}}instance{{`}}`}} binding\",\n                                \"refId\": \"B\"\n                            },\n                            {\n                                \"expr\": \"sum(rate(scheduler_scheduling_algorithm_duration_seconds_count{cluster=\\\"$cluster\\\", job=\\\"kube-scheduler\\\", instance=~\\\"$instance\\\"}[5m])) by (cluster, instance)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}} {{`{{`}}instance{{`}}`}} scheduling algorithm\",\n                                \"refId\": \"C\"\n                            },\n                            {\n                                \"expr\": \"sum(rate(scheduler_volume_scheduling_duration_seconds_count{cluster=\\\"$cluster\\\", job=\\\"kube-scheduler\\\", instance=~\\\"$instance\\\"}[5m])) by (cluster, instance)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}} {{`{{`}}instance{{`}}`}} volume\",\n                                \"refId\": \"D\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Scheduling Rate\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 4,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": false,\n                            \"current\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 5,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"histogram_quantile(0.99, sum(rate(scheduler_e2e_scheduling_duration_seconds_bucket{cluster=\\\"$cluster\\\", job=\\\"kube-scheduler\\\",instance=~\\\"$instance\\\"}[5m])) by (cluster, instance, le))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}} {{`{{`}}instance{{`}}`}} e2e\",\n                                \"refId\": \"A\"\n                            },\n                            {\n                                \"expr\": \"histogram_quantile(0.99, sum(rate(scheduler_binding_duration_seconds_bucket{cluster=\\\"$cluster\\\", job=\\\"kube-scheduler\\\",instance=~\\\"$instance\\\"}[5m])) by (cluster, instance, le))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}} {{`{{`}}instance{{`}}`}} binding\",\n                                \"refId\": \"B\"\n                            },\n                            {\n                                \"expr\": \"histogram_quantile(0.99, sum(rate(scheduler_scheduling_algorithm_duration_seconds_bucket{cluster=\\\"$cluster\\\", job=\\\"kube-scheduler\\\",instance=~\\\"$instance\\\"}[5m])) by (cluster, instance, le))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}} {{`{{`}}instance{{`}}`}} scheduling algorithm\",\n                                \"refId\": \"C\"\n                            },\n                            {\n                                \"expr\": \"histogram_quantile(0.99, sum(rate(scheduler_volume_scheduling_duration_seconds_bucket{cluster=\\\"$cluster\\\", job=\\\"kube-scheduler\\\",instance=~\\\"$instance\\\"}[5m])) by (cluster, instance, le))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}cluster{{`}}`}} {{`{{`}}instance{{`}}`}} volume\",\n                                \"refId\": \"D\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Scheduling latency 99th Quantile\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 5,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(rate(rest_client_requests_total{cluster=\\\"$cluster\\\", job=\\\"kube-scheduler\\\", instance=~\\\"$instance\\\",code=~\\\"2..\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"2xx\",\n                                \"refId\": \"A\"\n                            },\n                            {\n                                \"expr\": \"sum(rate(rest_client_requests_total{cluster=\\\"$cluster\\\", job=\\\"kube-scheduler\\\", instance=~\\\"$instance\\\",code=~\\\"3..\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"3xx\",\n                                \"refId\": \"B\"\n                            },\n                            {\n                                \"expr\": \"sum(rate(rest_client_requests_total{cluster=\\\"$cluster\\\", job=\\\"kube-scheduler\\\", instance=~\\\"$instance\\\",code=~\\\"4..\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"4xx\",\n                                \"refId\": \"C\"\n                            },\n                            {\n                                \"expr\": \"sum(rate(rest_client_requests_total{cluster=\\\"$cluster\\\", job=\\\"kube-scheduler\\\", instance=~\\\"$instance\\\",code=~\\\"5..\\\"}[5m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"5xx\",\n                                \"refId\": \"D\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Kube API Request Rate\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"ops\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 6,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 8,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{cluster=\\\"$cluster\\\", job=\\\"kube-scheduler\\\", instance=~\\\"$instance\\\", verb=\\\"POST\\\"}[5m])) by (verb, url, le))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}verb{{`}}`}} {{`{{`}}url{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Post Request Latency 99th Quantile\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 7,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": false,\n                            \"current\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{cluster=\\\"$cluster\\\", job=\\\"kube-scheduler\\\", instance=~\\\"$instance\\\", verb=\\\"GET\\\"}[5m])) by (verb, url, le))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}verb{{`}}`}} {{`{{`}}url{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Get Request Latency 99th Quantile\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"s\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 8,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"process_resident_memory_bytes{cluster=\\\"$cluster\\\", job=\\\"kube-scheduler\\\", instance=~\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Memory\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 9,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"rate(process_cpu_seconds_total{cluster=\\\"$cluster\\\", job=\\\"kube-scheduler\\\", instance=~\\\"$instance\\\"}[5m])\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"CPU usage\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"bytes\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 10,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 4,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"go_goroutines{cluster=\\\"$cluster\\\", job=\\\"kube-scheduler\\\",instance=~\\\"$instance\\\"}\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"{{`{{`}}instance{{`}}`}}\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Goroutines\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            }\n        ],\n        \"schemaVersion\": 14,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"kubernetes-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }},\n                    \"includeAll\": false,\n                    \"label\": \"cluster\",\n                    \"multi\": false,\n                    \"name\": \"cluster\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_info, cluster)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": true,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"instance\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(process_cpu_seconds_total{cluster=\\\"$cluster\\\", job=\\\"kube-scheduler\\\"}, instance)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"UTC\",\n        \"title\": \"Kubernetes / Scheduler\",\n        \"uid\": \"2e6b6a3b4bddf1427b3a55aa1311c656\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/statefulset.yaml",
    "content": "{{- /*\nGenerated from 'statefulset' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"statefulset\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  statefulset.json: |-\n    {\n        \"__inputs\": [\n\n        ],\n        \"__requires\": [\n\n        ],\n        \"annotations\": {\n            \"list\": [\n\n            ]\n        },\n        \"editable\": false,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"id\": null,\n        \"links\": [\n\n        ],\n        \"refresh\": \"\",\n        \"rows\": [\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"cacheTimeout\": null,\n                        \"colorBackground\": false,\n                        \"colorValue\": false,\n                        \"colors\": [\n                            \"#299c46\",\n                            \"rgba(237, 129, 40, 0.89)\",\n                            \"#d44a3a\"\n                        ],\n                        \"datasource\": \"$datasource\",\n                        \"format\": \"none\",\n                        \"gauge\": {\n                            \"maxValue\": 100,\n                            \"minValue\": 0,\n                            \"show\": false,\n                            \"thresholdLabels\": false,\n                            \"thresholdMarkers\": true\n                        },\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 2,\n                        \"interval\": null,\n                        \"links\": [\n\n                        ],\n                        \"mappingType\": 1,\n                        \"mappingTypes\": [\n                            {\n                                \"name\": \"value to text\",\n                                \"value\": 1\n                            },\n                            {\n                                \"name\": \"range to text\",\n                                \"value\": 2\n                            }\n                        ],\n                        \"maxDataPoints\": 100,\n                        \"nullPointMode\": \"connected\",\n                        \"nullText\": null,\n                        \"postfix\": \"cores\",\n                        \"postfixFontSize\": \"50%\",\n                        \"prefix\": \"\",\n                        \"prefixFontSize\": \"50%\",\n                        \"rangeMaps\": [\n                            {\n                                \"from\": \"null\",\n                                \"text\": \"N/A\",\n                                \"to\": \"null\"\n                            }\n                        ],\n                        \"span\": 4,\n                        \"sparkline\": {\n                            \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                            \"lineColor\": \"rgb(31, 120, 193)\",\n                            \"show\": true\n                        },\n                        \"tableColumn\": \"\",\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(rate(container_cpu_usage_seconds_total{job=\\\"kubelet\\\", metrics_path=\\\"/metrics/cadvisor\\\", cluster=\\\"$cluster\\\", container!=\\\"\\\", namespace=\\\"$namespace\\\", pod=~\\\"$statefulset.*\\\"}[3m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"\",\n                        \"title\": \"CPU\",\n                        \"tooltip\": {\n                            \"shared\": false\n                        },\n                        \"type\": \"singlestat\",\n                        \"valueFontSize\": \"80%\",\n                        \"valueMaps\": [\n                            {\n                                \"op\": \"=\",\n                                \"text\": \"0\",\n                                \"value\": \"null\"\n                            }\n                        ],\n                        \"valueName\": \"current\"\n                    },\n                    {\n                        \"cacheTimeout\": null,\n                        \"colorBackground\": false,\n                        \"colorValue\": false,\n                        \"colors\": [\n                            \"#299c46\",\n                            \"rgba(237, 129, 40, 0.89)\",\n                            \"#d44a3a\"\n                        ],\n                        \"datasource\": \"$datasource\",\n                        \"format\": \"none\",\n                        \"gauge\": {\n                            \"maxValue\": 100,\n                            \"minValue\": 0,\n                            \"show\": false,\n                            \"thresholdLabels\": false,\n                            \"thresholdMarkers\": true\n                        },\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 3,\n                        \"interval\": null,\n                        \"links\": [\n\n                        ],\n                        \"mappingType\": 1,\n                        \"mappingTypes\": [\n                            {\n                                \"name\": \"value to text\",\n                                \"value\": 1\n                            },\n                            {\n                                \"name\": \"range to text\",\n                                \"value\": 2\n                            }\n                        ],\n                        \"maxDataPoints\": 100,\n                        \"nullPointMode\": \"connected\",\n                        \"nullText\": null,\n                        \"postfix\": \"GB\",\n                        \"postfixFontSize\": \"50%\",\n                        \"prefix\": \"\",\n                        \"prefixFontSize\": \"50%\",\n                        \"rangeMaps\": [\n                            {\n                                \"from\": \"null\",\n                                \"text\": \"N/A\",\n                                \"to\": \"null\"\n                            }\n                        ],\n                        \"span\": 4,\n                        \"sparkline\": {\n                            \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                            \"lineColor\": \"rgb(31, 120, 193)\",\n                            \"show\": true\n                        },\n                        \"tableColumn\": \"\",\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(container_memory_usage_bytes{job=\\\"kubelet\\\", metrics_path=\\\"/metrics/cadvisor\\\", cluster=\\\"$cluster\\\", container!=\\\"\\\", namespace=\\\"$namespace\\\", pod=~\\\"$statefulset.*\\\"}) / 1024^3\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"\",\n                        \"title\": \"Memory\",\n                        \"tooltip\": {\n                            \"shared\": false\n                        },\n                        \"type\": \"singlestat\",\n                        \"valueFontSize\": \"80%\",\n                        \"valueMaps\": [\n                            {\n                                \"op\": \"=\",\n                                \"text\": \"0\",\n                                \"value\": \"null\"\n                            }\n                        ],\n                        \"valueName\": \"current\"\n                    },\n                    {\n                        \"cacheTimeout\": null,\n                        \"colorBackground\": false,\n                        \"colorValue\": false,\n                        \"colors\": [\n                            \"#299c46\",\n                            \"rgba(237, 129, 40, 0.89)\",\n                            \"#d44a3a\"\n                        ],\n                        \"datasource\": \"$datasource\",\n                        \"format\": \"none\",\n                        \"gauge\": {\n                            \"maxValue\": 100,\n                            \"minValue\": 0,\n                            \"show\": false,\n                            \"thresholdLabels\": false,\n                            \"thresholdMarkers\": true\n                        },\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 4,\n                        \"interval\": null,\n                        \"links\": [\n\n                        ],\n                        \"mappingType\": 1,\n                        \"mappingTypes\": [\n                            {\n                                \"name\": \"value to text\",\n                                \"value\": 1\n                            },\n                            {\n                                \"name\": \"range to text\",\n                                \"value\": 2\n                            }\n                        ],\n                        \"maxDataPoints\": 100,\n                        \"nullPointMode\": \"connected\",\n                        \"nullText\": null,\n                        \"postfix\": \"Bps\",\n                        \"postfixFontSize\": \"50%\",\n                        \"prefix\": \"\",\n                        \"prefixFontSize\": \"50%\",\n                        \"rangeMaps\": [\n                            {\n                                \"from\": \"null\",\n                                \"text\": \"N/A\",\n                                \"to\": \"null\"\n                            }\n                        ],\n                        \"span\": 4,\n                        \"sparkline\": {\n                            \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                            \"lineColor\": \"rgb(31, 120, 193)\",\n                            \"show\": true\n                        },\n                        \"tableColumn\": \"\",\n                        \"targets\": [\n                            {\n                                \"expr\": \"sum(rate(container_network_transmit_bytes_total{job=\\\"kubelet\\\", metrics_path=\\\"/metrics/cadvisor\\\", cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", pod=~\\\"$statefulset.*\\\"}[3m])) + sum(rate(container_network_receive_bytes_total{job=\\\"kubelet\\\", metrics_path=\\\"/metrics/cadvisor\\\", cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\",pod=~\\\"$statefulset.*\\\"}[3m]))\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"\",\n                        \"title\": \"Network\",\n                        \"tooltip\": {\n                            \"shared\": false\n                        },\n                        \"type\": \"singlestat\",\n                        \"valueFontSize\": \"80%\",\n                        \"valueMaps\": [\n                            {\n                                \"op\": \"=\",\n                                \"text\": \"0\",\n                                \"value\": \"null\"\n                            }\n                        ],\n                        \"valueName\": \"current\"\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"height\": \"100px\",\n                \"panels\": [\n                    {\n                        \"cacheTimeout\": null,\n                        \"colorBackground\": false,\n                        \"colorValue\": false,\n                        \"colors\": [\n                            \"#299c46\",\n                            \"rgba(237, 129, 40, 0.89)\",\n                            \"#d44a3a\"\n                        ],\n                        \"datasource\": \"$datasource\",\n                        \"format\": \"none\",\n                        \"gauge\": {\n                            \"maxValue\": 100,\n                            \"minValue\": 0,\n                            \"show\": false,\n                            \"thresholdLabels\": false,\n                            \"thresholdMarkers\": true\n                        },\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 5,\n                        \"interval\": null,\n                        \"links\": [\n\n                        ],\n                        \"mappingType\": 1,\n                        \"mappingTypes\": [\n                            {\n                                \"name\": \"value to text\",\n                                \"value\": 1\n                            },\n                            {\n                                \"name\": \"range to text\",\n                                \"value\": 2\n                            }\n                        ],\n                        \"maxDataPoints\": 100,\n                        \"nullPointMode\": \"connected\",\n                        \"nullText\": null,\n                        \"postfix\": \"\",\n                        \"postfixFontSize\": \"50%\",\n                        \"prefix\": \"\",\n                        \"prefixFontSize\": \"50%\",\n                        \"rangeMaps\": [\n                            {\n                                \"from\": \"null\",\n                                \"text\": \"N/A\",\n                                \"to\": \"null\"\n                            }\n                        ],\n                        \"span\": 3,\n                        \"sparkline\": {\n                            \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                            \"full\": false,\n                            \"lineColor\": \"rgb(31, 120, 193)\",\n                            \"show\": false\n                        },\n                        \"tableColumn\": \"\",\n                        \"targets\": [\n                            {\n                                \"expr\": \"max(kube_statefulset_replicas{job=\\\"kube-state-metrics\\\", cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", statefulset=\\\"$statefulset\\\"}) without (instance, pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"\",\n                        \"title\": \"Desired Replicas\",\n                        \"tooltip\": {\n                            \"shared\": false\n                        },\n                        \"type\": \"singlestat\",\n                        \"valueFontSize\": \"80%\",\n                        \"valueMaps\": [\n                            {\n                                \"op\": \"=\",\n                                \"text\": \"0\",\n                                \"value\": \"null\"\n                            }\n                        ],\n                        \"valueName\": \"current\"\n                    },\n                    {\n                        \"cacheTimeout\": null,\n                        \"colorBackground\": false,\n                        \"colorValue\": false,\n                        \"colors\": [\n                            \"#299c46\",\n                            \"rgba(237, 129, 40, 0.89)\",\n                            \"#d44a3a\"\n                        ],\n                        \"datasource\": \"$datasource\",\n                        \"format\": \"none\",\n                        \"gauge\": {\n                            \"maxValue\": 100,\n                            \"minValue\": 0,\n                            \"show\": false,\n                            \"thresholdLabels\": false,\n                            \"thresholdMarkers\": true\n                        },\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 6,\n                        \"interval\": null,\n                        \"links\": [\n\n                        ],\n                        \"mappingType\": 1,\n                        \"mappingTypes\": [\n                            {\n                                \"name\": \"value to text\",\n                                \"value\": 1\n                            },\n                            {\n                                \"name\": \"range to text\",\n                                \"value\": 2\n                            }\n                        ],\n                        \"maxDataPoints\": 100,\n                        \"nullPointMode\": \"connected\",\n                        \"nullText\": null,\n                        \"postfix\": \"\",\n                        \"postfixFontSize\": \"50%\",\n                        \"prefix\": \"\",\n                        \"prefixFontSize\": \"50%\",\n                        \"rangeMaps\": [\n                            {\n                                \"from\": \"null\",\n                                \"text\": \"N/A\",\n                                \"to\": \"null\"\n                            }\n                        ],\n                        \"span\": 3,\n                        \"sparkline\": {\n                            \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                            \"full\": false,\n                            \"lineColor\": \"rgb(31, 120, 193)\",\n                            \"show\": false\n                        },\n                        \"tableColumn\": \"\",\n                        \"targets\": [\n                            {\n                                \"expr\": \"min(kube_statefulset_status_replicas_current{job=\\\"kube-state-metrics\\\", cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", statefulset=\\\"$statefulset\\\"}) without (instance, pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"\",\n                        \"title\": \"Replicas of current version\",\n                        \"tooltip\": {\n                            \"shared\": false\n                        },\n                        \"type\": \"singlestat\",\n                        \"valueFontSize\": \"80%\",\n                        \"valueMaps\": [\n                            {\n                                \"op\": \"=\",\n                                \"text\": \"0\",\n                                \"value\": \"null\"\n                            }\n                        ],\n                        \"valueName\": \"current\"\n                    },\n                    {\n                        \"cacheTimeout\": null,\n                        \"colorBackground\": false,\n                        \"colorValue\": false,\n                        \"colors\": [\n                            \"#299c46\",\n                            \"rgba(237, 129, 40, 0.89)\",\n                            \"#d44a3a\"\n                        ],\n                        \"datasource\": \"$datasource\",\n                        \"format\": \"none\",\n                        \"gauge\": {\n                            \"maxValue\": 100,\n                            \"minValue\": 0,\n                            \"show\": false,\n                            \"thresholdLabels\": false,\n                            \"thresholdMarkers\": true\n                        },\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 7,\n                        \"interval\": null,\n                        \"links\": [\n\n                        ],\n                        \"mappingType\": 1,\n                        \"mappingTypes\": [\n                            {\n                                \"name\": \"value to text\",\n                                \"value\": 1\n                            },\n                            {\n                                \"name\": \"range to text\",\n                                \"value\": 2\n                            }\n                        ],\n                        \"maxDataPoints\": 100,\n                        \"nullPointMode\": \"connected\",\n                        \"nullText\": null,\n                        \"postfix\": \"\",\n                        \"postfixFontSize\": \"50%\",\n                        \"prefix\": \"\",\n                        \"prefixFontSize\": \"50%\",\n                        \"rangeMaps\": [\n                            {\n                                \"from\": \"null\",\n                                \"text\": \"N/A\",\n                                \"to\": \"null\"\n                            }\n                        ],\n                        \"span\": 3,\n                        \"sparkline\": {\n                            \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                            \"full\": false,\n                            \"lineColor\": \"rgb(31, 120, 193)\",\n                            \"show\": false\n                        },\n                        \"tableColumn\": \"\",\n                        \"targets\": [\n                            {\n                                \"expr\": \"max(kube_statefulset_status_observed_generation{job=\\\"kube-state-metrics\\\", cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\", statefulset=\\\"$statefulset\\\"}) without (instance, pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"\",\n                        \"title\": \"Observed Generation\",\n                        \"tooltip\": {\n                            \"shared\": false\n                        },\n                        \"type\": \"singlestat\",\n                        \"valueFontSize\": \"80%\",\n                        \"valueMaps\": [\n                            {\n                                \"op\": \"=\",\n                                \"text\": \"0\",\n                                \"value\": \"null\"\n                            }\n                        ],\n                        \"valueName\": \"current\"\n                    },\n                    {\n                        \"cacheTimeout\": null,\n                        \"colorBackground\": false,\n                        \"colorValue\": false,\n                        \"colors\": [\n                            \"#299c46\",\n                            \"rgba(237, 129, 40, 0.89)\",\n                            \"#d44a3a\"\n                        ],\n                        \"datasource\": \"$datasource\",\n                        \"format\": \"none\",\n                        \"gauge\": {\n                            \"maxValue\": 100,\n                            \"minValue\": 0,\n                            \"show\": false,\n                            \"thresholdLabels\": false,\n                            \"thresholdMarkers\": true\n                        },\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 8,\n                        \"interval\": null,\n                        \"links\": [\n\n                        ],\n                        \"mappingType\": 1,\n                        \"mappingTypes\": [\n                            {\n                                \"name\": \"value to text\",\n                                \"value\": 1\n                            },\n                            {\n                                \"name\": \"range to text\",\n                                \"value\": 2\n                            }\n                        ],\n                        \"maxDataPoints\": 100,\n                        \"nullPointMode\": \"connected\",\n                        \"nullText\": null,\n                        \"postfix\": \"\",\n                        \"postfixFontSize\": \"50%\",\n                        \"prefix\": \"\",\n                        \"prefixFontSize\": \"50%\",\n                        \"rangeMaps\": [\n                            {\n                                \"from\": \"null\",\n                                \"text\": \"N/A\",\n                                \"to\": \"null\"\n                            }\n                        ],\n                        \"span\": 3,\n                        \"sparkline\": {\n                            \"fillColor\": \"rgba(31, 118, 189, 0.18)\",\n                            \"full\": false,\n                            \"lineColor\": \"rgb(31, 120, 193)\",\n                            \"show\": false\n                        },\n                        \"tableColumn\": \"\",\n                        \"targets\": [\n                            {\n                                \"expr\": \"max(kube_statefulset_metadata_generation{job=\\\"kube-state-metrics\\\", statefulset=\\\"$statefulset\\\", cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}) without (instance, pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"\",\n                                \"refId\": \"A\"\n                            }\n                        ],\n                        \"thresholds\": \"\",\n                        \"title\": \"Metadata Generation\",\n                        \"tooltip\": {\n                            \"shared\": false\n                        },\n                        \"type\": \"singlestat\",\n                        \"valueFontSize\": \"80%\",\n                        \"valueMaps\": [\n                            {\n                                \"op\": \"=\",\n                                \"text\": \"0\",\n                                \"value\": \"null\"\n                            }\n                        ],\n                        \"valueName\": \"current\"\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 1,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n\n                        },\n                        \"id\": 9,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"nullPointMode\": \"null\",\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"max(kube_statefulset_replicas{job=\\\"kube-state-metrics\\\", statefulset=\\\"$statefulset\\\", cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}) without (instance, pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"replicas specified\",\n                                \"refId\": \"A\"\n                            },\n                            {\n                                \"expr\": \"max(kube_statefulset_status_replicas{job=\\\"kube-state-metrics\\\", statefulset=\\\"$statefulset\\\", cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}) without (instance, pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"replicas created\",\n                                \"refId\": \"B\"\n                            },\n                            {\n                                \"expr\": \"min(kube_statefulset_status_replicas_ready{job=\\\"kube-state-metrics\\\", statefulset=\\\"$statefulset\\\", cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}) without (instance, pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"ready\",\n                                \"refId\": \"C\"\n                            },\n                            {\n                                \"expr\": \"min(kube_statefulset_status_replicas_current{job=\\\"kube-state-metrics\\\", statefulset=\\\"$statefulset\\\", cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}) without (instance, pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"replicas of current version\",\n                                \"refId\": \"D\"\n                            },\n                            {\n                                \"expr\": \"min(kube_statefulset_status_replicas_updated{job=\\\"kube-state-metrics\\\", statefulset=\\\"$statefulset\\\", cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}) without (instance, pod)\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 2,\n                                \"legendFormat\": \"updated\",\n                                \"refId\": \"E\"\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Replicas\",\n                        \"tooltip\": {\n                            \"shared\": false,\n                            \"sort\": 0,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"short\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": null,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": false,\n                \"title\": \"Dashboard Row\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            }\n        ],\n        \"schemaVersion\": 14,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"kubernetes-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }},\n                    \"includeAll\": false,\n                    \"label\": \"cluster\",\n                    \"multi\": false,\n                    \"name\": \"cluster\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_statefulset_metadata_generation, cluster)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": \"Namespace\",\n                    \"multi\": false,\n                    \"name\": \"namespace\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_statefulset_metadata_generation{job=\\\"kube-state-metrics\\\", cluster=\\\"$cluster\\\"}, namespace)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": \"Name\",\n                    \"multi\": false,\n                    \"name\": \"statefulset\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_statefulset_metadata_generation{job=\\\"kube-state-metrics\\\", cluster=\\\"$cluster\\\", namespace=\\\"$namespace\\\"}, statefulset)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"UTC\",\n        \"title\": \"Kubernetes / StatefulSets\",\n        \"uid\": \"a31c1f46e6f727cb37c0d731a7245005\",\n        \"version\": 0\n    }\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14/workload-total.yaml",
    "content": "{{- /*\nGenerated from 'workload-total' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }}\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) \"workload-total\" | trunc 63 | trimSuffix \"-\" }}\n  annotations:\n{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }}\n  labels:\n    {{- if $.Values.grafana.sidecar.dashboards.label }}\n    {{ $.Values.grafana.sidecar.dashboards.label }}: \"1\"\n    {{- end }}\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-grafana\n{{ include \"kube-prometheus-stack.labels\" $ | indent 4 }}\ndata:\n  workload-total.json: |-\n    {\n        \"__inputs\": [\n\n        ],\n        \"__requires\": [\n\n        ],\n        \"annotations\": {\n            \"list\": [\n                {\n                    \"builtIn\": 1,\n                    \"datasource\": \"-- Grafana --\",\n                    \"enable\": true,\n                    \"hide\": true,\n                    \"iconColor\": \"rgba(0, 211, 255, 1)\",\n                    \"name\": \"Annotations & Alerts\",\n                    \"type\": \"dashboard\"\n                }\n            ]\n        },\n        \"editable\": true,\n        \"gnetId\": null,\n        \"graphTooltip\": 0,\n        \"hideControls\": false,\n        \"id\": null,\n        \"links\": [\n\n        ],\n        \"panels\": [\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 0\n                },\n                \"id\": 2,\n                \"panels\": [\n\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Current Bandwidth\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": true,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 2,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 12,\n                    \"x\": 0,\n                    \"y\": 1\n                },\n                \"id\": 3,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": false,\n                    \"current\": true,\n                    \"hideEmpty\": true,\n                    \"hideZero\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"sort\": \"current\",\n                    \"sortDesc\": true,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": false,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"minSpan\": 24,\n                \"nullPointMode\": \"null\",\n                \"paceLength\": 10,\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"span\": 24,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 1,\n                        \"legendFormat\": \"{{`{{`}} pod {{`}}`}}\",\n                        \"refId\": \"A\",\n                        \"step\": 10\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Current Rate of Bytes Received\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 2,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"series\",\n                    \"name\": null,\n                    \"show\": false,\n                    \"values\": [\n                        \"current\"\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": true,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 2,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 12,\n                    \"x\": 12,\n                    \"y\": 1\n                },\n                \"id\": 4,\n                \"legend\": {\n                    \"alignAsTable\": true,\n                    \"avg\": false,\n                    \"current\": true,\n                    \"hideEmpty\": true,\n                    \"hideZero\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": true,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"sort\": \"current\",\n                    \"sortDesc\": true,\n                    \"total\": false,\n                    \"values\": true\n                },\n                \"lines\": false,\n                \"linewidth\": 1,\n                \"links\": [\n\n                ],\n                \"minSpan\": 24,\n                \"nullPointMode\": \"null\",\n                \"paceLength\": 10,\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"span\": 24,\n                \"stack\": false,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 1,\n                        \"legendFormat\": \"{{`{{`}} pod {{`}}`}}\",\n                        \"refId\": \"A\",\n                        \"step\": 10\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Current Rate of Bytes Transmitted\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 2,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"series\",\n                    \"name\": null,\n                    \"show\": false,\n                    \"values\": [\n                        \"current\"\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"collapse\": true,\n                \"collapsed\": true,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 10\n                },\n                \"id\": 5,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": true,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 9,\n                            \"w\": 12,\n                            \"x\": 0,\n                            \"y\": 11\n                        },\n                        \"id\": 6,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": false,\n                            \"current\": true,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"sort\": \"current\",\n                            \"sortDesc\": true,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": false,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 24,\n                        \"nullPointMode\": \"null\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 24,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sort_desc(avg(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}} pod {{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Average Rate of Bytes Received\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"series\",\n                            \"name\": null,\n                            \"show\": false,\n                            \"values\": [\n                                \"current\"\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": true,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 9,\n                            \"w\": 12,\n                            \"x\": 12,\n                            \"y\": 11\n                        },\n                        \"id\": 7,\n                        \"legend\": {\n                            \"alignAsTable\": true,\n                            \"avg\": false,\n                            \"current\": true,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": true,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"sort\": \"current\",\n                            \"sortDesc\": true,\n                            \"total\": false,\n                            \"values\": true\n                        },\n                        \"lines\": false,\n                        \"linewidth\": 1,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 24,\n                        \"nullPointMode\": \"null\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 24,\n                        \"stack\": false,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sort_desc(avg(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}} pod {{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Average Rate of Bytes Transmitted\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"series\",\n                            \"name\": null,\n                            \"show\": false,\n                            \"values\": [\n                                \"current\"\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"Bps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Average Bandwidth\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": false,\n                \"collapsed\": false,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 11\n                },\n                \"id\": 8,\n                \"panels\": [\n\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Bandwidth HIstory\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 2,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 12,\n                    \"x\": 0,\n                    \"y\": 12\n                },\n                \"id\": 9,\n                \"legend\": {\n                    \"alignAsTable\": false,\n                    \"avg\": false,\n                    \"current\": false,\n                    \"hideEmpty\": true,\n                    \"hideZero\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": false,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": false\n                },\n                \"lines\": true,\n                \"linewidth\": 2,\n                \"links\": [\n\n                ],\n                \"minSpan\": 12,\n                \"nullPointMode\": \"connected\",\n                \"paceLength\": 10,\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"span\": 12,\n                \"stack\": true,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_receive_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 1,\n                        \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                        \"refId\": \"A\",\n                        \"step\": 10\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Receive Bandwidth\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 2,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"aliasColors\": {\n\n                },\n                \"bars\": false,\n                \"dashLength\": 10,\n                \"dashes\": false,\n                \"datasource\": \"$datasource\",\n                \"fill\": 2,\n                \"fillGradient\": 0,\n                \"gridPos\": {\n                    \"h\": 9,\n                    \"w\": 12,\n                    \"x\": 12,\n                    \"y\": 12\n                },\n                \"id\": 10,\n                \"legend\": {\n                    \"alignAsTable\": false,\n                    \"avg\": false,\n                    \"current\": false,\n                    \"hideEmpty\": true,\n                    \"hideZero\": true,\n                    \"max\": false,\n                    \"min\": false,\n                    \"rightSide\": false,\n                    \"show\": true,\n                    \"sideWidth\": null,\n                    \"total\": false,\n                    \"values\": false\n                },\n                \"lines\": true,\n                \"linewidth\": 2,\n                \"links\": [\n\n                ],\n                \"minSpan\": 12,\n                \"nullPointMode\": \"connected\",\n                \"paceLength\": 10,\n                \"percentage\": false,\n                \"pointradius\": 5,\n                \"points\": false,\n                \"renderer\": \"flot\",\n                \"repeat\": null,\n                \"seriesOverrides\": [\n\n                ],\n                \"spaceLength\": 10,\n                \"span\": 12,\n                \"stack\": true,\n                \"steppedLine\": false,\n                \"targets\": [\n                    {\n                        \"expr\": \"sort_desc(sum(irate(container_network_transmit_bytes_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                        \"format\": \"time_series\",\n                        \"intervalFactor\": 1,\n                        \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                        \"refId\": \"A\",\n                        \"step\": 10\n                    }\n                ],\n                \"thresholds\": [\n\n                ],\n                \"timeFrom\": null,\n                \"timeShift\": null,\n                \"title\": \"Transmit Bandwidth\",\n                \"tooltip\": {\n                    \"shared\": true,\n                    \"sort\": 2,\n                    \"value_type\": \"individual\"\n                },\n                \"type\": \"graph\",\n                \"xaxis\": {\n                    \"buckets\": null,\n                    \"mode\": \"time\",\n                    \"name\": null,\n                    \"show\": true,\n                    \"values\": [\n\n                    ]\n                },\n                \"yaxes\": [\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    },\n                    {\n                        \"format\": \"Bps\",\n                        \"label\": null,\n                        \"logBase\": 1,\n                        \"max\": null,\n                        \"min\": 0,\n                        \"show\": true\n                    }\n                ]\n            },\n            {\n                \"collapse\": true,\n                \"collapsed\": true,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 21\n                },\n                \"id\": 11,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 9,\n                            \"w\": 12,\n                            \"x\": 0,\n                            \"y\": 22\n                        },\n                        \"id\": 12,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 12,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sort_desc(sum(irate(container_network_receive_packets_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Received Packets\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 9,\n                            \"w\": 12,\n                            \"x\": 12,\n                            \"y\": 22\n                        },\n                        \"id\": 13,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 12,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sort_desc(sum(irate(container_network_transmit_packets_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Transmitted Packets\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Packets\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            },\n            {\n                \"collapse\": true,\n                \"collapsed\": true,\n                \"gridPos\": {\n                    \"h\": 1,\n                    \"w\": 24,\n                    \"x\": 0,\n                    \"y\": 22\n                },\n                \"id\": 14,\n                \"panels\": [\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 9,\n                            \"w\": 12,\n                            \"x\": 0,\n                            \"y\": 23\n                        },\n                        \"id\": 15,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 12,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sort_desc(sum(irate(container_network_receive_packets_dropped_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Received Packets Dropped\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    },\n                    {\n                        \"aliasColors\": {\n\n                        },\n                        \"bars\": false,\n                        \"dashLength\": 10,\n                        \"dashes\": false,\n                        \"datasource\": \"$datasource\",\n                        \"fill\": 2,\n                        \"fillGradient\": 0,\n                        \"gridPos\": {\n                            \"h\": 9,\n                            \"w\": 12,\n                            \"x\": 12,\n                            \"y\": 23\n                        },\n                        \"id\": 16,\n                        \"legend\": {\n                            \"alignAsTable\": false,\n                            \"avg\": false,\n                            \"current\": false,\n                            \"hideEmpty\": true,\n                            \"hideZero\": true,\n                            \"max\": false,\n                            \"min\": false,\n                            \"rightSide\": false,\n                            \"show\": true,\n                            \"sideWidth\": null,\n                            \"total\": false,\n                            \"values\": false\n                        },\n                        \"lines\": true,\n                        \"linewidth\": 2,\n                        \"links\": [\n\n                        ],\n                        \"minSpan\": 12,\n                        \"nullPointMode\": \"connected\",\n                        \"paceLength\": 10,\n                        \"percentage\": false,\n                        \"pointradius\": 5,\n                        \"points\": false,\n                        \"renderer\": \"flot\",\n                        \"repeat\": null,\n                        \"seriesOverrides\": [\n\n                        ],\n                        \"spaceLength\": 10,\n                        \"span\": 12,\n                        \"stack\": true,\n                        \"steppedLine\": false,\n                        \"targets\": [\n                            {\n                                \"expr\": \"sort_desc(sum(irate(container_network_transmit_packets_dropped_total{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}[$interval:$resolution])\\n* on (namespace,pod)\\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\", workload_type=\\\"$type\\\"}) by (pod))\\n\",\n                                \"format\": \"time_series\",\n                                \"intervalFactor\": 1,\n                                \"legendFormat\": \"{{`{{`}}pod{{`}}`}}\",\n                                \"refId\": \"A\",\n                                \"step\": 10\n                            }\n                        ],\n                        \"thresholds\": [\n\n                        ],\n                        \"timeFrom\": null,\n                        \"timeShift\": null,\n                        \"title\": \"Rate of Transmitted Packets Dropped\",\n                        \"tooltip\": {\n                            \"shared\": true,\n                            \"sort\": 2,\n                            \"value_type\": \"individual\"\n                        },\n                        \"type\": \"graph\",\n                        \"xaxis\": {\n                            \"buckets\": null,\n                            \"mode\": \"time\",\n                            \"name\": null,\n                            \"show\": true,\n                            \"values\": [\n\n                            ]\n                        },\n                        \"yaxes\": [\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            },\n                            {\n                                \"format\": \"pps\",\n                                \"label\": null,\n                                \"logBase\": 1,\n                                \"max\": null,\n                                \"min\": 0,\n                                \"show\": true\n                            }\n                        ]\n                    }\n                ],\n                \"repeat\": null,\n                \"repeatIteration\": null,\n                \"repeatRowId\": null,\n                \"showTitle\": true,\n                \"title\": \"Errors\",\n                \"titleSize\": \"h6\",\n                \"type\": \"row\"\n            }\n        ],\n        \"refresh\": \"10s\",\n        \"rows\": [\n\n        ],\n        \"schemaVersion\": 18,\n        \"style\": \"dark\",\n        \"tags\": [\n            \"kubernetes-mixin\"\n        ],\n        \"templating\": {\n            \"list\": [\n                {\n                    \"current\": {\n                        \"text\": \"default\",\n                        \"value\": \"default\"\n                    },\n                    \"hide\": 0,\n                    \"label\": null,\n                    \"name\": \"datasource\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"prometheus\",\n                    \"refresh\": 1,\n                    \"regex\": \"\",\n                    \"type\": \"datasource\"\n                },\n                {\n                    \"allValue\": null,\n                    \"current\": {\n\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }},\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"cluster\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(kube_pod_info, cluster)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"sort\": 0,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": \".+\",\n                    \"auto\": false,\n                    \"auto_count\": 30,\n                    \"auto_min\": \"10s\",\n                    \"current\": {\n                        \"text\": \"kube-system\",\n                        \"value\": \"kube-system\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"definition\": \"label_values(container_network_receive_packets_total{cluster=\\\"$cluster\\\"}, namespace)\",\n                    \"hide\": 0,\n                    \"includeAll\": true,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"namespace\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(container_network_receive_packets_total{cluster=\\\"$cluster\\\"}, namespace)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"skipUrlSync\": false,\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"auto\": false,\n                    \"auto_count\": 30,\n                    \"auto_min\": \"10s\",\n                    \"current\": {\n                        \"text\": \"\",\n                        \"value\": \"\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"definition\": \"label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}, workload)\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"workload\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\"}, workload)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"skipUrlSync\": false,\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"auto\": false,\n                    \"auto_count\": 30,\n                    \"auto_min\": \"10s\",\n                    \"current\": {\n                        \"text\": \"deployment\",\n                        \"value\": \"deployment\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"definition\": \"label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\"}, workload_type)\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"type\",\n                    \"options\": [\n\n                    ],\n                    \"query\": \"label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\\\"$cluster\\\",namespace=~\\\"$namespace\\\", workload=~\\\"$workload\\\"}, workload_type)\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"skipUrlSync\": false,\n                    \"sort\": 0,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"query\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"auto\": false,\n                    \"auto_count\": 30,\n                    \"auto_min\": \"10s\",\n                    \"current\": {\n                        \"text\": \"5m\",\n                        \"value\": \"5m\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 0,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"resolution\",\n                    \"options\": [\n                        {\n                            \"selected\": false,\n                            \"text\": \"30s\",\n                            \"value\": \"30s\"\n                        },\n                        {\n                            \"selected\": true,\n                            \"text\": \"5m\",\n                            \"value\": \"5m\"\n                        },\n                        {\n                            \"selected\": false,\n                            \"text\": \"1h\",\n                            \"value\": \"1h\"\n                        }\n                    ],\n                    \"query\": \"30s,5m,1h\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"skipUrlSync\": false,\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"interval\",\n                    \"useTags\": false\n                },\n                {\n                    \"allValue\": null,\n                    \"auto\": false,\n                    \"auto_count\": 30,\n                    \"auto_min\": \"10s\",\n                    \"current\": {\n                        \"text\": \"5m\",\n                        \"value\": \"5m\"\n                    },\n                    \"datasource\": \"$datasource\",\n                    \"hide\": 2,\n                    \"includeAll\": false,\n                    \"label\": null,\n                    \"multi\": false,\n                    \"name\": \"interval\",\n                    \"options\": [\n                        {\n                            \"selected\": true,\n                            \"text\": \"4h\",\n                            \"value\": \"4h\"\n                        }\n                    ],\n                    \"query\": \"4h\",\n                    \"refresh\": 2,\n                    \"regex\": \"\",\n                    \"skipUrlSync\": false,\n                    \"sort\": 1,\n                    \"tagValuesQuery\": \"\",\n                    \"tags\": [\n\n                    ],\n                    \"tagsQuery\": \"\",\n                    \"type\": \"interval\",\n                    \"useTags\": false\n                }\n            ]\n        },\n        \"time\": {\n            \"from\": \"now-1h\",\n            \"to\": \"now\"\n        },\n        \"timepicker\": {\n            \"refresh_intervals\": [\n                \"5s\",\n                \"10s\",\n                \"30s\",\n                \"1m\",\n                \"5m\",\n                \"15m\",\n                \"30m\",\n                \"1h\",\n                \"2h\",\n                \"1d\"\n            ],\n            \"time_options\": [\n                \"5m\",\n                \"15m\",\n                \"1h\",\n                \"6h\",\n                \"12h\",\n                \"24h\",\n                \"2d\",\n                \"7d\",\n                \"30d\"\n            ]\n        },\n        \"timezone\": \"UTC\",\n        \"title\": \"Kubernetes / Networking / Workload\",\n        \"uid\": \"728bf77cc1166d2f3133bf25846876cc\",\n        \"version\": 0\n    }\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/grafana/servicemonitor.yaml",
    "content": "{{- if and .Values.grafana.enabled .Values.grafana.serviceMonitor.selfMonitor }}\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-grafana\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-grafana\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  selector:\n    matchLabels:\n      app.kubernetes.io/name: grafana\n      app.kubernetes.io/instance: {{ $.Release.Name | quote }}\n  namespaceSelector:\n    matchNames:\n      - {{ printf \"%s\" (include \"kube-prometheus-stack.namespace\" .) | quote }}\n  endpoints:\n  - port: {{ .Values.grafana.service.portName }}\n    {{- if .Values.grafana.serviceMonitor.interval }}\n    interval: {{ .Values.grafana.serviceMonitor.interval }}\n    {{- end }}\n    path: {{ .Values.grafana.serviceMonitor.path | quote }}\n{{- if .Values.grafana.serviceMonitor.metricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.grafana.serviceMonitor.metricRelabelings | indent 6) . }}\n{{- end }}\n{{- if .Values.grafana.serviceMonitor.relabelings }}\n    relabelings:\n{{ toYaml .Values.grafana.serviceMonitor.relabelings | indent 6 }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/_rules.tpl",
    "content": "{{- /*\nGenerated file. Do not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- define \"rules.names\" }}\nrules:\n  - \"alertmanager.rules\"\n  - \"general.rules\"\n  - \"k8s.rules\"\n  - \"kube-apiserver.rules\"\n  - \"kube-apiserver-availability.rules\"\n  - \"kube-apiserver-error\"\n  - \"kube-apiserver-slos\"\n  - \"kube-prometheus-general.rules\"\n  - \"kube-prometheus-node-alerting.rules\"\n  - \"kube-prometheus-node-recording.rules\"\n  - \"kube-scheduler.rules\"\n  - \"kube-state-metrics\"\n  - \"kubelet.rules\"\n  - \"kubernetes-absent\"\n  - \"kubernetes-resources\"\n  - \"kubernetes-storage\"\n  - \"kubernetes-system\"\n  - \"kubernetes-system-apiserver\"\n  - \"kubernetes-system-kubelet\"\n  - \"kubernetes-system-controller-manager\"\n  - \"kubernetes-system-scheduler\"\n  - \"node-exporter.rules\"\n  - \"node-exporter\"\n  - \"node.rules\"\n  - \"node-network\"\n  - \"node-time\"\n  - \"prometheus-operator\"\n  - \"prometheus.rules\"\n  - \"prometheus\"\n  - \"kubernetes-apps\"\n  - \"etcd\"\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/additionalAlertRelabelConfigs.yaml",
    "content": "{{- if and .Values.prometheus.enabled .Values.prometheus.prometheusSpec.additionalAlertRelabelConfigs }}\napiVersion: v1\nkind: Secret\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus-am-relabel-confg\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n{{- if .Values.prometheus.prometheusSpec.additionalPrometheusSecretsAnnotations }}\n  annotations:\n{{ toYaml .Values.prometheus.prometheusSpec.additionalPrometheusSecretsAnnotations | indent 4 }}\n{{- end }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-prometheus-am-relabel-confg\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\ndata:\n  additional-alert-relabel-configs.yaml: {{ toYaml .Values.prometheus.prometheusSpec.additionalAlertRelabelConfigs | b64enc | quote }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/additionalAlertmanagerConfigs.yaml",
    "content": "{{- if and .Values.prometheus.enabled .Values.prometheus.prometheusSpec.additionalAlertManagerConfigs }}\napiVersion: v1\nkind: Secret\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus-am-confg\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n{{- if .Values.prometheus.prometheusSpec.additionalPrometheusSecretsAnnotations }}\n  annotations:\n{{ toYaml .Values.prometheus.prometheusSpec.additionalPrometheusSecretsAnnotations | indent 4 }}\n{{- end }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-prometheus-am-confg\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\ndata:\n  additional-alertmanager-configs.yaml: {{ toYaml .Values.prometheus.prometheusSpec.additionalAlertManagerConfigs | b64enc | quote }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/additionalPrometheusRules.yaml",
    "content": "{{- if or .Values.additionalPrometheusRules .Values.additionalPrometheusRulesMap}}\napiVersion: v1\nkind: List\nmetadata:\n  name: {{ include \"kube-prometheus-stack.fullname\" $ }}-additional-prometheus-rules\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\nitems:\n{{- if .Values.additionalPrometheusRulesMap }}\n{{- range $prometheusRuleName, $prometheusRule := .Values.additionalPrometheusRulesMap }}\n  - apiVersion: monitoring.coreos.com/v1\n    kind: PrometheusRule\n    metadata:\n      name: {{ template \"kube-prometheus-stack.name\" $ }}-{{ $prometheusRuleName }}\n      namespace: {{ template \"kube-prometheus-stack.namespace\" $ }}\n      labels:\n        app: {{ template \"kube-prometheus-stack.name\" $ }}\n{{ include \"kube-prometheus-stack.labels\" $ | indent 8 }}\n    {{- if $prometheusRule.additionalLabels }}\n{{ toYaml $prometheusRule.additionalLabels | indent 8 }}\n    {{- end }}\n    spec:\n      groups:\n{{ toYaml $prometheusRule.groups| indent 8 }}\n{{- end }}\n{{- else }}\n{{- range .Values.additionalPrometheusRules }}\n  - apiVersion: monitoring.coreos.com/v1\n    kind: PrometheusRule\n    metadata:\n      name: {{ template \"kube-prometheus-stack.name\" $ }}-{{ .name }}\n      namespace: {{ template \"kube-prometheus-stack.namespace\" $ }}\n      labels:\n        app: {{ template \"kube-prometheus-stack.name\" $ }}\n{{ include \"kube-prometheus-stack.labels\" $ | indent 8 }}\n    {{- if .additionalLabels }}\n{{ toYaml .additionalLabels | indent 8 }}\n    {{- end }}\n    spec:\n      groups:\n{{ toYaml .groups| indent 8 }}\n{{- end }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/additionalScrapeConfigs.yaml",
    "content": "{{- if and .Values.prometheus.enabled .Values.prometheus.prometheusSpec.additionalScrapeConfigs }}\napiVersion: v1\nkind: Secret\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus-scrape-confg\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n{{- if .Values.prometheus.prometheusSpec.additionalPrometheusSecretsAnnotations }}\n  annotations:\n{{ toYaml .Values.prometheus.prometheusSpec.additionalPrometheusSecretsAnnotations | indent 4 }}\n{{- end }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-prometheus-scrape-confg\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\ndata:\n  additional-scrape-configs.yaml: {{ tpl (toYaml .Values.prometheus.prometheusSpec.additionalScrapeConfigs) $ | b64enc | quote }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/clusterrole.yaml",
    "content": "{{- if and .Values.prometheus.enabled .Values.global.rbac.create }}\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-prometheus\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nrules:\n# This permission are not in the kube-prometheus repo\n# they're grabbed from https://github.com/prometheus/prometheus/blob/master/documentation/examples/rbac-setup.yml\n- apiGroups: [\"\"]\n  resources:\n  - nodes\n  - nodes/metrics\n  - services\n  - endpoints\n  - pods\n  verbs: [\"get\", \"list\", \"watch\"]\n- apiGroups:\n  - \"networking.k8s.io\"\n  resources:\n  - ingresses\n  verbs: [\"get\", \"list\", \"watch\"]\n- nonResourceURLs: [\"/metrics\", \"/metrics/cadvisor\"]\n  verbs: [\"get\"]\n{{- if .Values.prometheus.additionalRulesForClusterRole }}\n{{ toYaml .Values.prometheus.additionalRulesForClusterRole | indent 0 }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/clusterrolebinding.yaml",
    "content": "{{- if and .Values.prometheus.enabled .Values.global.rbac.create }}\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-prometheus\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus\nsubjects:\n  - kind: ServiceAccount\n    name: {{ template \"kube-prometheus-stack.prometheus.serviceAccountName\" . }}\n    namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n{{- end }}\n\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/ingress.yaml",
    "content": "{{- if and .Values.prometheus.enabled .Values.prometheus.ingress.enabled -}}\n  {{- $pathType := .Values.prometheus.ingress.pathType | default \"\" -}}\n  {{- $serviceName := printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"prometheus\" -}}\n  {{- $servicePort := .Values.prometheus.service.port -}}\n  {{- $routePrefix := list .Values.prometheus.prometheusSpec.routePrefix -}}\n  {{- $paths := .Values.prometheus.ingress.paths | default $routePrefix -}}\n  {{- $apiIsStable := eq (include \"kube-prometheus-stack.ingress.isStable\" .) \"true\" -}}\n  {{- $ingressSupportsPathType := eq (include \"kube-prometheus-stack.ingress.supportsPathType\" .) \"true\" -}}\napiVersion: {{ include \"kube-prometheus-stack.ingress.apiVersion\" . }}\nkind: Ingress\nmetadata:\n{{- if .Values.prometheus.ingress.annotations }}\n  annotations:\n{{ toYaml .Values.prometheus.ingress.annotations | indent 4 }}\n{{- end }}\n  name: {{ $serviceName }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-prometheus\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.prometheus.ingress.labels }}\n{{ toYaml .Values.prometheus.ingress.labels | indent 4 }}\n{{- end }}\nspec:\n  {{- if $apiIsStable }}\n  {{- if .Values.prometheus.ingress.ingressClassName }}\n  ingressClassName: {{ .Values.prometheus.ingress.ingressClassName }}\n  {{- end }}\n  {{- end }}\n  rules:\n  {{- if .Values.prometheus.ingress.hosts }}\n  {{- range $host := .Values.prometheus.ingress.hosts }}\n    - host: {{ tpl $host $ }}\n      http:\n        paths:\n  {{- range $p := $paths }}\n          - path: {{ tpl $p $ }}\n            {{- if and $pathType $ingressSupportsPathType }}\n            pathType: {{ $pathType }}\n            {{- end }}\n            backend:\n              {{- if $apiIsStable }}\n              service:\n                name: {{ $serviceName }}\n                port:\n                  number: {{ $servicePort }}\n              {{- else }}\n              serviceName: {{ $serviceName }}\n              servicePort: {{ $servicePort }}\n    {{- end }}\n    {{- end -}}\n  {{- end -}}\n  {{- else }}\n    - http:\n        paths:\n  {{- range $p := $paths }}\n          - path: {{ tpl $p $ }}\n            {{- if and $pathType $ingressSupportsPathType }}\n            pathType: {{ $pathType }}\n            {{- end }}\n            backend:\n              {{- if $apiIsStable }}\n              service:\n                name: {{ $serviceName }}\n                port:\n                  number: {{ $servicePort }}\n              {{- else }}\n              serviceName: {{ $serviceName }}\n              servicePort: {{ $servicePort }}\n  {{- end }}\n  {{- end -}}\n  {{- end -}}\n  {{- if .Values.prometheus.ingress.tls }}\n  tls:\n{{ tpl (toYaml .Values.prometheus.ingress.tls | indent 4) . }}\n  {{- end -}}\n{{- end -}}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/ingressThanosSidecar.yaml",
    "content": "{{- if and .Values.prometheus.enabled .Values.prometheus.thanosIngress.enabled }}\n{{- $pathType := .Values.prometheus.thanosIngress.pathType | default \"\" }}\n{{- $serviceName := printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"prometheus\" }}\n{{- $thanosPort := .Values.prometheus.thanosIngress.servicePort -}}\n{{- $routePrefix := list .Values.prometheus.prometheusSpec.routePrefix }}\n{{- $paths := .Values.prometheus.thanosIngress.paths | default $routePrefix -}}\n{{- $apiIsStable := eq (include \"kube-prometheus-stack.ingress.isStable\" .) \"true\" -}}\n{{- $ingressSupportsPathType := eq (include \"kube-prometheus-stack.ingress.supportsPathType\" .) \"true\" -}}\napiVersion: {{ include \"kube-prometheus-stack.ingress.apiVersion\" . }}\nkind: Ingress\nmetadata:\n{{- if .Values.prometheus.thanosIngress.annotations }}\n  annotations:\n{{ toYaml .Values.prometheus.thanosIngress.annotations | indent 4 }}\n{{- end }}\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-thanos-gateway\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-prometheus\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.prometheus.thanosIngress.labels }}\n{{ toYaml .Values.prometheus.thanosIngress.labels | indent 4 }}\n{{- end }}\nspec:\n  {{- if $apiIsStable }}\n  {{- if .Values.prometheus.thanosIngress.ingressClassName }}\n  ingressClassName: {{ .Values.prometheus.thanosIngress.ingressClassName }}\n  {{- end }}\n  {{- end }}\n  rules:\n  {{- if .Values.prometheus.thanosIngress.hosts }}\n  {{- range $host := .Values.prometheus.thanosIngress.hosts }}\n    - host: {{ tpl $host $ }}\n      http:\n        paths:\n  {{- range $p := $paths }}\n          - path: {{ tpl $p $ }}\n            {{- if and $pathType $ingressSupportsPathType }}\n            pathType: {{ $pathType }}\n            {{- end }}\n            backend:\n              {{- if $apiIsStable }}\n              service:\n                name: {{ $serviceName }}\n                port:\n                  number: {{ $thanosPort }}\n              {{- else }}\n              serviceName: {{ $serviceName }}\n              servicePort: {{ $thanosPort }}\n    {{- end }}\n    {{- end -}}\n  {{- end -}}\n  {{- else }}\n    - http:\n        paths:\n  {{- range $p := $paths }}\n          - path: {{ tpl $p $ }}\n            {{- if and $pathType $ingressSupportsPathType }}\n            pathType: {{ $pathType }}\n            {{- end }}\n            backend:\n              {{- if $apiIsStable }}\n              service:\n                name: {{ $serviceName }}\n                port:\n                  number: {{ $thanosPort }}\n              {{- else }}\n              serviceName: {{ $serviceName }}\n              servicePort: {{ $thanosPort }}\n  {{- end }}\n  {{- end -}}\n  {{- end -}}\n  {{- if .Values.prometheus.thanosIngress.tls }}\n  tls:\n{{ toYaml .Values.prometheus.thanosIngress.tls | indent 4 }}\n  {{- end -}}\n{{- end -}}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/ingressperreplica.yaml",
    "content": "{{- if and .Values.prometheus.enabled .Values.prometheus.servicePerReplica.enabled .Values.prometheus.ingressPerReplica.enabled }}\n{{- $pathType := .Values.prometheus.ingressPerReplica.pathType | default \"\" }}\n{{- $count := .Values.prometheus.prometheusSpec.replicas | int -}}\n{{- $servicePort := .Values.prometheus.servicePerReplica.port -}}\n{{- $ingressValues := .Values.prometheus.ingressPerReplica -}}\n{{- $apiIsStable := eq (include \"kube-prometheus-stack.ingress.isStable\" .) \"true\" -}}\n{{- $ingressSupportsPathType := eq (include \"kube-prometheus-stack.ingress.supportsPathType\" .) \"true\" -}}\napiVersion: v1\nkind: List\nmetadata:\n  name: {{ include \"kube-prometheus-stack.fullname\" $ }}-prometheus-ingressperreplica\n  namespace: {{ template \"kube-prometheus-stack.namespace\" $ }}\nitems:\n{{ range $i, $e := until $count }}\n  - kind: Ingress\n    apiVersion: {{ include \"kube-prometheus-stack.ingress.apiVersion\" $ }}\n    metadata:\n      name: {{ include \"kube-prometheus-stack.fullname\" $ }}-prometheus-{{ $i }}\n      namespace: {{ template \"kube-prometheus-stack.namespace\" $ }}\n      labels:\n        app: {{ include \"kube-prometheus-stack.name\" $ }}-prometheus\n      {{ include \"kube-prometheus-stack.labels\" $ | indent 8 }}\n      {{- if $ingressValues.labels }}\n{{ toYaml $ingressValues.labels | indent 8 }}\n      {{- end }}\n      {{- if $ingressValues.annotations }}\n      annotations:\n{{ toYaml $ingressValues.annotations | indent 8 }}\n      {{- end }}\n    spec:\n      {{- if $apiIsStable }}\n      {{- if $ingressValues.ingressClassName }}\n      ingressClassName: {{ $ingressValues.ingressClassName }}\n      {{- end }}\n      {{- end }}\n      rules:\n        - host: {{ $ingressValues.hostPrefix }}-{{ $i }}.{{ $ingressValues.hostDomain }}\n          http:\n            paths:\n      {{- range $p := $ingressValues.paths }}\n              - path: {{ tpl $p $ }}\n                {{- if and $pathType $ingressSupportsPathType }}\n                pathType: {{ $pathType }}\n                {{- end }}\n                backend:\n                  {{- if $apiIsStable }}\n                  service:\n                    name: {{ include \"kube-prometheus-stack.fullname\" $ }}-prometheus-{{ $i }}\n                    port:\n                      number: {{ $servicePort }}\n                  {{- else }}\n                  serviceName: {{ include \"kube-prometheus-stack.fullname\" $ }}-prometheus-{{ $i }}\n                  servicePort: {{ $servicePort }}\n      {{- end }}\n      {{- end -}}\n      {{- if or $ingressValues.tlsSecretName $ingressValues.tlsSecretPerReplica.enabled }}\n      tls:\n        - hosts:\n            - {{ $ingressValues.hostPrefix }}-{{ $i }}.{{ $ingressValues.hostDomain }}\n          {{- if $ingressValues.tlsSecretPerReplica.enabled }}\n          secretName: {{ $ingressValues.tlsSecretPerReplica.prefix }}-{{ $i }}\n          {{- else }}\n          secretName: {{ $ingressValues.tlsSecretName }}\n          {{- end }}\n      {{- end }}\n{{- end -}}\n{{- end -}}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/podDisruptionBudget.yaml",
    "content": "{{- if and .Values.prometheus.enabled .Values.prometheus.podDisruptionBudget.enabled }}\napiVersion: policy/v1beta1\nkind: PodDisruptionBudget\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-prometheus\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  {{- if .Values.prometheus.podDisruptionBudget.minAvailable }}\n  minAvailable: {{ .Values.prometheus.podDisruptionBudget.minAvailable }}\n  {{- end  }}\n  {{- if .Values.prometheus.podDisruptionBudget.maxUnavailable }}\n  maxUnavailable: {{ .Values.prometheus.podDisruptionBudget.maxUnavailable }}\n  {{- end  }}\n  selector:\n    matchLabels:\n      app.kubernetes.io/name: prometheus\n      prometheus: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/podmonitors.yaml",
    "content": "{{- if and .Values.prometheus.enabled .Values.prometheus.additionalPodMonitors }}\napiVersion: v1\nkind: List\nitems:\n{{- range .Values.prometheus.additionalPodMonitors }}\n  - apiVersion: monitoring.coreos.com/v1\n    kind: PodMonitor\n    metadata:\n      name: {{ .name }}\n      namespace: {{ template \"kube-prometheus-stack.namespace\" $ }}\n      labels:\n        app: {{ template \"kube-prometheus-stack.name\" $ }}-prometheus\n{{ include \"kube-prometheus-stack.labels\" $ | indent 8 }}\n        {{- if .additionalLabels }}\n{{ toYaml .additionalLabels | indent 8 }}\n        {{- end }}\n    spec:\n      podMetricsEndpoints:\n{{ toYaml .podMetricsEndpoints | indent 8 }}\n    {{- if .jobLabel }}\n      jobLabel: {{ .jobLabel }}\n    {{- end }}\n    {{- if .namespaceSelector }}\n      namespaceSelector:\n{{ toYaml .namespaceSelector | indent 8 }}\n    {{- end }}\n      selector:\n{{ toYaml .selector | indent 8 }}\n    {{- if .podTargetLabels }}\n      podTargetLabels:\n{{ toYaml .podTargetLabels | indent 8 }}\n    {{- end }}\n    {{- if .sampleLimit }}\n      sampleLimit: {{ .sampleLimit }}\n    {{- end }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/prometheus.yaml",
    "content": "{{- if .Values.prometheus.enabled }}\napiVersion: monitoring.coreos.com/v1\nkind: Prometheus\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-prometheus\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.prometheus.annotations }}\n  annotations:\n{{ toYaml .Values.prometheus.annotations | indent 4 }}\n{{- end }}\nspec:\n  alerting:\n    alertmanagers:\n{{- if .Values.prometheus.prometheusSpec.alertingEndpoints }}\n{{ toYaml .Values.prometheus.prometheusSpec.alertingEndpoints | indent 6 }}\n{{- else if .Values.alertmanager.enabled }}\n      - namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n        name: {{ template \"kube-prometheus-stack.fullname\" . }}-alertmanager\n        port: {{ .Values.alertmanager.alertmanagerSpec.portName }}\n        {{- if .Values.alertmanager.alertmanagerSpec.routePrefix }}\n        pathPrefix: \"{{ .Values.alertmanager.alertmanagerSpec.routePrefix }}\"\n        {{- end }}\n        apiVersion: {{ .Values.alertmanager.apiVersion }}\n{{- else }}\n      []\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.apiserverConfig }}\n  apiserverConfig:\n{{ toYaml .Values.prometheus.prometheusSpec.apiserverConfig | indent 4}}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.image }}\n  image: {{ .Values.prometheus.prometheusSpec.image.repository }}:{{ .Values.prometheus.prometheusSpec.image.tag }}\n  version: {{ .Values.prometheus.prometheusSpec.image.tag }}\n  {{- if .Values.prometheus.prometheusSpec.image.sha }}\n  sha: {{ .Values.prometheus.prometheusSpec.image.sha }}\n  {{- end }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.externalLabels }}\n  externalLabels:\n{{ tpl (toYaml .Values.prometheus.prometheusSpec.externalLabels | indent 4) . }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.prometheusExternalLabelNameClear }}\n  prometheusExternalLabelName: \"\"\n{{- else if .Values.prometheus.prometheusSpec.prometheusExternalLabelName }}\n  prometheusExternalLabelName: \"{{ .Values.prometheus.prometheusSpec.prometheusExternalLabelName }}\"\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.replicaExternalLabelNameClear }}\n  replicaExternalLabelName: \"\"\n{{- else if .Values.prometheus.prometheusSpec.replicaExternalLabelName }}\n  replicaExternalLabelName: \"{{ .Values.prometheus.prometheusSpec.replicaExternalLabelName }}\"\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.externalUrl }}\n  externalUrl: \"{{ tpl .Values.prometheus.prometheusSpec.externalUrl . }}\"\n{{- else if and .Values.prometheus.ingress.enabled .Values.prometheus.ingress.hosts }}\n  externalUrl: \"http://{{ tpl (index .Values.prometheus.ingress.hosts 0) . }}{{ .Values.prometheus.prometheusSpec.routePrefix }}\"\n{{- else }}\n  externalUrl: http://{{ template \"kube-prometheus-stack.fullname\" . }}-prometheus.{{ template \"kube-prometheus-stack.namespace\" . }}:{{ .Values.prometheus.service.port }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.nodeSelector }}\n  nodeSelector:\n{{ toYaml .Values.prometheus.prometheusSpec.nodeSelector | indent 4 }}\n{{- end }}\n  paused: {{ .Values.prometheus.prometheusSpec.paused }}\n  replicas: {{ .Values.prometheus.prometheusSpec.replicas }}\n  shards: {{ .Values.prometheus.prometheusSpec.shards }}\n  logLevel:  {{ .Values.prometheus.prometheusSpec.logLevel }}\n  logFormat:  {{ .Values.prometheus.prometheusSpec.logFormat }}\n  listenLocal: {{ .Values.prometheus.prometheusSpec.listenLocal }}\n  enableAdminAPI: {{ .Values.prometheus.prometheusSpec.enableAdminAPI }}\n{{- if .Values.prometheus.prometheusSpec.enableFeatures }}\n  enableFeatures:\n{{- range $enableFeatures := .Values.prometheus.prometheusSpec.enableFeatures }}\n  - {{ tpl $enableFeatures $ }}\n{{- end }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.scrapeInterval }}\n  scrapeInterval: {{ .Values.prometheus.prometheusSpec.scrapeInterval }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.scrapeTimeout }}\n  scrapeTimeout: {{ .Values.prometheus.prometheusSpec.scrapeTimeout }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.evaluationInterval }}\n  evaluationInterval: {{ .Values.prometheus.prometheusSpec.evaluationInterval }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.resources }}\n  resources:\n{{ toYaml .Values.prometheus.prometheusSpec.resources | indent 4 }}\n{{- end }}\n  retention: {{ .Values.prometheus.prometheusSpec.retention | quote  }}\n{{- if .Values.prometheus.prometheusSpec.retentionSize }}\n  retentionSize: {{ .Values.prometheus.prometheusSpec.retentionSize | quote }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.walCompression }}\n  walCompression: {{ .Values.prometheus.prometheusSpec.walCompression }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.routePrefix }}\n  routePrefix: {{ .Values.prometheus.prometheusSpec.routePrefix | quote  }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.secrets }}\n  secrets:\n{{ toYaml .Values.prometheus.prometheusSpec.secrets | indent 4 }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.configMaps }}\n  configMaps:\n{{ toYaml .Values.prometheus.prometheusSpec.configMaps | indent 4 }}\n{{- end }}\n  serviceAccountName: {{ template \"kube-prometheus-stack.prometheus.serviceAccountName\" . }}\n{{- if .Values.prometheus.prometheusSpec.serviceMonitorSelector }}\n  serviceMonitorSelector:\n{{ toYaml .Values.prometheus.prometheusSpec.serviceMonitorSelector | indent 4 }}\n{{ else if .Values.prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues  }}\n  serviceMonitorSelector:\n    matchLabels:\n      release: {{ $.Release.Name | quote }}\n{{ else }}\n  serviceMonitorSelector: {}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.serviceMonitorNamespaceSelector }}\n  serviceMonitorNamespaceSelector:\n{{ toYaml .Values.prometheus.prometheusSpec.serviceMonitorNamespaceSelector | indent 4 }}\n{{ else }}\n  serviceMonitorNamespaceSelector: {}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.podMonitorSelector }}\n  podMonitorSelector:\n{{ toYaml .Values.prometheus.prometheusSpec.podMonitorSelector | indent 4 }}\n{{ else if .Values.prometheus.prometheusSpec.podMonitorSelectorNilUsesHelmValues  }}\n  podMonitorSelector:\n    matchLabels:\n      release: {{ $.Release.Name | quote }}\n{{ else }}\n  podMonitorSelector: {}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.podMonitorNamespaceSelector }}\n  podMonitorNamespaceSelector:\n{{ toYaml .Values.prometheus.prometheusSpec.podMonitorNamespaceSelector | indent 4 }}\n{{ else }}\n  podMonitorNamespaceSelector: {}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.probeSelector }}\n  probeSelector:\n{{ toYaml .Values.prometheus.prometheusSpec.probeSelector | indent 4 }}\n{{ else if .Values.prometheus.prometheusSpec.probeSelectorNilUsesHelmValues  }}\n  probeSelector:\n    matchLabels:\n      release: {{ $.Release.Name | quote }}\n{{ else }}\n  probeSelector: {}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.probeNamespaceSelector }}\n  probeNamespaceSelector:\n{{ toYaml .Values.prometheus.prometheusSpec.probeNamespaceSelector | indent 4 }}\n{{ else }}\n  probeNamespaceSelector: {}\n{{- end }}\n{{- if (or .Values.prometheus.prometheusSpec.remoteRead .Values.prometheus.prometheusSpec.additionalRemoteRead) }}\n  remoteRead:\n{{- if .Values.prometheus.prometheusSpec.remoteRead }}\n{{ tpl (toYaml .Values.prometheus.prometheusSpec.remoteRead | indent 4) . }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.additionalRemoteRead }}\n{{ toYaml .Values.prometheus.prometheusSpec.additionalRemoteRead | indent 4 }}\n{{- end }}\n{{- end }}\n{{- if (or .Values.prometheus.prometheusSpec.remoteWrite .Values.prometheus.prometheusSpec.additionalRemoteWrite) }}\n  remoteWrite:\n{{- if .Values.prometheus.prometheusSpec.remoteWrite }}\n{{ tpl (toYaml .Values.prometheus.prometheusSpec.remoteWrite | indent 4) . }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.additionalRemoteWrite }}\n{{ toYaml .Values.prometheus.prometheusSpec.additionalRemoteWrite | indent 4 }}\n{{- end }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.securityContext }}\n  securityContext:\n{{ toYaml .Values.prometheus.prometheusSpec.securityContext | indent 4 }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.ruleNamespaceSelector }}\n  ruleNamespaceSelector:\n{{ toYaml .Values.prometheus.prometheusSpec.ruleNamespaceSelector | indent 4 }}\n{{ else }}\n  ruleNamespaceSelector: {}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.ruleSelector }}\n  ruleSelector:\n{{ toYaml .Values.prometheus.prometheusSpec.ruleSelector | indent 4}}\n{{- else if .Values.prometheus.prometheusSpec.ruleSelectorNilUsesHelmValues }}\n  ruleSelector:\n    matchLabels:\n      app: {{ template \"kube-prometheus-stack.name\" . }}\n      release: {{ $.Release.Name | quote }}\n{{ else }}\n  ruleSelector: {}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.storageSpec }}\n  storage:\n{{ toYaml .Values.prometheus.prometheusSpec.storageSpec | indent 4 }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.podMetadata }}\n  podMetadata:\n{{ tpl (toYaml .Values.prometheus.prometheusSpec.podMetadata | indent 4) . }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.query }}\n  query:\n{{ toYaml .Values.prometheus.prometheusSpec.query | indent 4}}\n{{- end }}\n{{- if or .Values.prometheus.prometheusSpec.podAntiAffinity .Values.prometheus.prometheusSpec.affinity }}\n  affinity:\n{{- if .Values.prometheus.prometheusSpec.affinity }}\n{{ toYaml .Values.prometheus.prometheusSpec.affinity | indent 4 }}\n{{- end }}\n{{- if eq .Values.prometheus.prometheusSpec.podAntiAffinity \"hard\" }}\n    podAntiAffinity:\n      requiredDuringSchedulingIgnoredDuringExecution:\n      - topologyKey: {{ .Values.prometheus.prometheusSpec.podAntiAffinityTopologyKey }}\n        labelSelector:\n          matchExpressions:\n            - {key: app.kubernetes.io/name, operator: In, values: [prometheus]}\n            - {key: prometheus, operator: In, values: [{{ template \"kube-prometheus-stack.fullname\" . }}-prometheus]}\n{{- else if eq .Values.prometheus.prometheusSpec.podAntiAffinity \"soft\" }}\n    podAntiAffinity:\n      preferredDuringSchedulingIgnoredDuringExecution:\n      - weight: 100\n        podAffinityTerm:\n          topologyKey: {{ .Values.prometheus.prometheusSpec.podAntiAffinityTopologyKey }}\n          labelSelector:\n            matchExpressions:\n              - {key: app.kubernetes.io/name, operator: In, values: [prometheus]}\n              - {key: prometheus, operator: In, values: [{{ template \"kube-prometheus-stack.fullname\" . }}-prometheus]}\n{{- end }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.tolerations }}\n  tolerations:\n{{ toYaml .Values.prometheus.prometheusSpec.tolerations | indent 4 }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.topologySpreadConstraints }}\n  topologySpreadConstraints:\n{{ toYaml .Values.prometheus.prometheusSpec.topologySpreadConstraints | indent 4 }}\n{{- end }}\n{{- if .Values.global.imagePullSecrets }}\n  imagePullSecrets:\n{{ toYaml .Values.global.imagePullSecrets | indent 4 }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.additionalScrapeConfigs }}\n  additionalScrapeConfigs:\n    name: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus-scrape-confg\n    key: additional-scrape-configs.yaml\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.additionalScrapeConfigsSecret.enabled }}\n  additionalScrapeConfigs:\n    name: {{ .Values.prometheus.prometheusSpec.additionalScrapeConfigsSecret.name }}\n    key: {{ .Values.prometheus.prometheusSpec.additionalScrapeConfigsSecret.key }}\n{{- end }}\n{{- if or .Values.prometheus.prometheusSpec.additionalAlertManagerConfigs .Values.prometheus.prometheusSpec.additionalAlertManagerConfigsSecret }}\n  additionalAlertManagerConfigs:\n{{- if .Values.prometheus.prometheusSpec.additionalAlertManagerConfigs }}\n    name: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus-am-confg\n    key: additional-alertmanager-configs.yaml\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.additionalAlertManagerConfigsSecret }}\n    name: {{ .Values.prometheus.prometheusSpec.additionalAlertManagerConfigsSecret.name }}\n    key: {{ .Values.prometheus.prometheusSpec.additionalAlertManagerConfigsSecret.key }}\n{{- end }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.additionalAlertRelabelConfigs }}\n  additionalAlertRelabelConfigs:\n    name: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus-am-relabel-confg\n    key: additional-alert-relabel-configs.yaml\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.containers }}\n  containers:\n{{ toYaml .Values.prometheus.prometheusSpec.containers | indent 4 }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.initContainers }}\n  initContainers:\n{{ toYaml .Values.prometheus.prometheusSpec.initContainers | indent 4 }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.priorityClassName }}\n  priorityClassName: {{ .Values.prometheus.prometheusSpec.priorityClassName }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.thanos }}\n  thanos:\n{{ toYaml .Values.prometheus.prometheusSpec.thanos | indent 4 }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.disableCompaction }}\n  disableCompaction: {{ .Values.prometheus.prometheusSpec.disableCompaction }}\n{{- end }}\n  portName: {{ .Values.prometheus.prometheusSpec.portName }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.volumes }}\n  volumes:\n{{ toYaml .Values.prometheus.prometheusSpec.volumes | indent 4 }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.volumeMounts }}\n  volumeMounts:\n{{ toYaml .Values.prometheus.prometheusSpec.volumeMounts | indent 4 }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.arbitraryFSAccessThroughSMs }}\n  arbitraryFSAccessThroughSMs:\n{{ toYaml .Values.prometheus.prometheusSpec.arbitraryFSAccessThroughSMs | indent 4 }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.overrideHonorLabels }}\n  overrideHonorLabels: {{ .Values.prometheus.prometheusSpec.overrideHonorLabels }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.overrideHonorTimestamps }}\n  overrideHonorTimestamps: {{ .Values.prometheus.prometheusSpec.overrideHonorTimestamps }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.ignoreNamespaceSelectors }}\n  ignoreNamespaceSelectors: {{ .Values.prometheus.prometheusSpec.ignoreNamespaceSelectors }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.enforcedNamespaceLabel }}\n  enforcedNamespaceLabel: {{ .Values.prometheus.prometheusSpec.enforcedNamespaceLabel }}\n{{- $prometheusDefaultRulesExcludedFromEnforce := (include \"rules.names\" .) | fromYaml }}\n  prometheusRulesExcludedFromEnforce:\n{{- range $prometheusDefaultRulesExcludedFromEnforce.rules }}\n    - ruleNamespace: \"{{ template \"kube-prometheus-stack.namespace\" $ }}\"\n      ruleName: \"{{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" $) . | trunc 63 | trimSuffix \"-\" }}\"\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.prometheusRulesExcludedFromEnforce }}\n{{ toYaml .Values.prometheus.prometheusSpec.prometheusRulesExcludedFromEnforce | indent 4 }}\n{{- end }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.queryLogFile }}\n  queryLogFile: {{ .Values.prometheus.prometheusSpec.queryLogFile }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.enforcedSampleLimit }}\n  enforcedSampleLimit: {{ .Values.prometheus.prometheusSpec.enforcedSampleLimit }}\n{{- end }}\n{{- if .Values.prometheus.prometheusSpec.allowOverlappingBlocks }}\n  allowOverlappingBlocks: {{ .Values.prometheus.prometheusSpec.allowOverlappingBlocks }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/psp-clusterrole.yaml",
    "content": "{{- if and .Values.prometheus.enabled .Values.global.rbac.create .Values.global.rbac.pspEnabled }}\nkind: ClusterRole\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus-psp\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-prometheus\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nrules:\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if semverCompare \"> 1.15.0-0\" $kubeTargetVersion }}\n- apiGroups: ['policy']\n{{- else }}\n- apiGroups: ['extensions']\n{{- end }}\n  resources: ['podsecuritypolicies']\n  verbs:     ['use']\n  resourceNames:\n  - {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/psp-clusterrolebinding.yaml",
    "content": "{{- if and .Values.prometheus.enabled .Values.global.rbac.create .Values.global.rbac.pspEnabled }}\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus-psp\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-prometheus\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus-psp\nsubjects:\n  - kind: ServiceAccount\n    name: {{ template \"kube-prometheus-stack.prometheus.serviceAccountName\" . }}\n    namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n{{- end }}\n\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/psp.yaml",
    "content": "{{- if and .Values.prometheus.enabled .Values.global.rbac.create .Values.global.rbac.pspEnabled }}\napiVersion: policy/v1beta1\nkind: PodSecurityPolicy\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-prometheus\n{{- if .Values.global.rbac.pspAnnotations }}\n  annotations:\n{{ toYaml .Values.global.rbac.pspAnnotations | indent 4 }}\n{{- end }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  privileged: false\n  # Required to prevent escalations to root.\n  # allowPrivilegeEscalation: false\n  # This is redundant with non-root + disallow privilege escalation,\n  # but we can provide it for defense in depth.\n  #requiredDropCapabilities:\n  #  - ALL\n  # Allow core volume types.\n  volumes:\n    - 'configMap'\n    - 'emptyDir'\n    - 'projected'\n    - 'secret'\n    - 'downwardAPI'\n    - 'persistentVolumeClaim'\n{{- if .Values.prometheus.podSecurityPolicy.volumes }}\n{{ toYaml .Values.prometheus.podSecurityPolicy.volumes | indent 4 }}\n{{- end }}\n  hostNetwork: false\n  hostIPC: false\n  hostPID: false\n  runAsUser:\n    # Permits the container to run with root privileges as well.\n    rule: 'RunAsAny'\n  seLinux:\n    # This policy assumes the nodes are using AppArmor rather than SELinux.\n    rule: 'RunAsAny'\n  supplementalGroups:\n    rule: 'MustRunAs'\n    ranges:\n      # Forbid adding the root group.\n      - min: 0\n        max: 65535\n  fsGroup:\n    rule: 'MustRunAs'\n    ranges:\n      # Forbid adding the root group.\n      - min: 0\n        max: 65535\n  readOnlyRootFilesystem: false\n{{- if .Values.prometheus.podSecurityPolicy.allowedCapabilities }}\n  allowedCapabilities:\n{{ toYaml .Values.prometheus.podSecurityPolicy.allowedCapabilities | indent 4 }}\n{{- end }}\n{{- if .Values.prometheus.podSecurityPolicy.allowedHostPaths }}\n  allowedHostPaths:\n{{ toYaml .Values.prometheus.podSecurityPolicy.allowedHostPaths | indent 4 }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/alertmanager.rules.yaml",
    "content": "{{- /*\nGenerated from 'alertmanager.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/alertmanager-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.alertmanager }}\n{{- $alertmanagerJob := printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"alertmanager\" }}\n{{- $namespace := printf \"%s\" (include \"kube-prometheus-stack.namespace\" .) }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"alertmanager.rules\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: alertmanager.rules\n    rules:\n    - alert: AlertmanagerFailedReload\n      annotations:\n        description: Configuration has failed to load for {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod{{`}}`}}.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-alertmanagerfailedreload\n        summary: Reloading an Alertmanager configuration has failed.\n      expr: |-\n        # Without max_over_time, failed scrapes could create false negatives, see\n        # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details.\n        max_over_time(alertmanager_config_last_reload_successful{job=\"{{ $alertmanagerJob }}\",namespace=\"{{ $namespace }}\"}[5m]) == 0\n      for: 10m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: AlertmanagerMembersInconsistent\n      annotations:\n        description: Alertmanager {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod{{`}}`}} has only found {{`{{`}} $value {{`}}`}} members of the {{`{{`}}$labels.job{{`}}`}} cluster.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-alertmanagermembersinconsistent\n        summary: A member of an Alertmanager cluster has not found all other cluster members.\n      expr: |-\n        # Without max_over_time, failed scrapes could create false negatives, see\n        # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details.\n          max_over_time(alertmanager_cluster_members{job=\"{{ $alertmanagerJob }}\",namespace=\"{{ $namespace }}\"}[5m])\n        < on (namespace,service) group_left\n          count by (namespace,service) (max_over_time(alertmanager_cluster_members{job=\"{{ $alertmanagerJob }}\",namespace=\"{{ $namespace }}\"}[5m]))\n      for: 15m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: AlertmanagerFailedToSendAlerts\n      annotations:\n        description: Alertmanager {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod{{`}}`}} failed to send {{`{{`}} $value | humanizePercentage {{`}}`}} of notifications to {{`{{`}} $labels.integration {{`}}`}}.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-alertmanagerfailedtosendalerts\n        summary: An Alertmanager instance failed to send notifications.\n      expr: |-\n        (\n          rate(alertmanager_notifications_failed_total{job=\"{{ $alertmanagerJob }}\",namespace=\"{{ $namespace }}\"}[5m])\n        /\n          rate(alertmanager_notifications_total{job=\"{{ $alertmanagerJob }}\",namespace=\"{{ $namespace }}\"}[5m])\n        )\n        > 0.01\n      for: 5m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: AlertmanagerClusterFailedToSendAlerts\n      annotations:\n        description: The minimum notification failure rate to {{`{{`}} $labels.integration {{`}}`}} sent from any instance in the {{`{{`}}$labels.job{{`}}`}} cluster is {{`{{`}} $value | humanizePercentage {{`}}`}}.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-alertmanagerclusterfailedtosendalerts\n        summary: All Alertmanager instances in a cluster failed to send notifications to a critical integration.\n      expr: |-\n        min by (namespace,service, integration) (\n          rate(alertmanager_notifications_failed_total{job=\"{{ $alertmanagerJob }}\",namespace=\"{{ $namespace }}\", integration=~`.*`}[5m])\n        /\n          rate(alertmanager_notifications_total{job=\"{{ $alertmanagerJob }}\",namespace=\"{{ $namespace }}\", integration=~`.*`}[5m])\n        )\n        > 0.01\n      for: 5m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: AlertmanagerClusterFailedToSendAlerts\n      annotations:\n        description: The minimum notification failure rate to {{`{{`}} $labels.integration {{`}}`}} sent from any instance in the {{`{{`}}$labels.job{{`}}`}} cluster is {{`{{`}} $value | humanizePercentage {{`}}`}}.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-alertmanagerclusterfailedtosendalerts\n        summary: All Alertmanager instances in a cluster failed to send notifications to a non-critical integration.\n      expr: |-\n        min by (namespace,service, integration) (\n          rate(alertmanager_notifications_failed_total{job=\"{{ $alertmanagerJob }}\",namespace=\"{{ $namespace }}\", integration!~`.*`}[5m])\n        /\n          rate(alertmanager_notifications_total{job=\"{{ $alertmanagerJob }}\",namespace=\"{{ $namespace }}\", integration!~`.*`}[5m])\n        )\n        > 0.01\n      for: 5m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: AlertmanagerConfigInconsistent\n      annotations:\n        description: Alertmanager instances within the {{`{{`}}$labels.job{{`}}`}} cluster have different configurations.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-alertmanagerconfiginconsistent\n        summary: Alertmanager instances within the same cluster have different configurations.\n      expr: |-\n        count by (namespace,service) (\n          count_values by (namespace,service) (\"config_hash\", alertmanager_config_hash{job=\"{{ $alertmanagerJob }}\",namespace=\"{{ $namespace }}\"})\n        )\n        != 1\n      for: 20m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: AlertmanagerClusterDown\n      annotations:\n        description: '{{`{{`}} $value | humanizePercentage {{`}}`}} of Alertmanager instances within the {{`{{`}}$labels.job{{`}}`}} cluster have been up for less than half of the last 5m.'\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-alertmanagerclusterdown\n        summary: Half or more of the Alertmanager instances within the same cluster are down.\n      expr: |-\n        (\n          count by (namespace,service) (\n            avg_over_time(up{job=\"{{ $alertmanagerJob }}\",namespace=\"{{ $namespace }}\"}[5m]) < 0.5\n          )\n        /\n          count by (namespace,service) (\n            up{job=\"{{ $alertmanagerJob }}\",namespace=\"{{ $namespace }}\"}\n          )\n        )\n        >= 0.5\n      for: 5m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: AlertmanagerClusterCrashlooping\n      annotations:\n        description: '{{`{{`}} $value | humanizePercentage {{`}}`}} of Alertmanager instances within the {{`{{`}}$labels.job{{`}}`}} cluster have restarted at least 5 times in the last 10m.'\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-alertmanagerclustercrashlooping\n        summary: Half or more of the Alertmanager instances within the same cluster are crashlooping.\n      expr: |-\n        (\n          count by (namespace,service) (\n            changes(process_start_time_seconds{job=\"{{ $alertmanagerJob }}\",namespace=\"{{ $namespace }}\"}[10m]) > 4\n          )\n        /\n          count by (namespace,service) (\n            up{job=\"{{ $alertmanagerJob }}\",namespace=\"{{ $namespace }}\"}\n          )\n        )\n        >= 0.5\n      for: 5m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/etcd.yaml",
    "content": "{{- /*\nGenerated from 'etcd' group from https://raw.githubusercontent.com/etcd-io/website/master/content/en/docs/v3.4/op-guide/etcd3_alert.rules.yml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.kubeEtcd.enabled .Values.defaultRules.rules.etcd }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"etcd\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: etcd\n    rules:\n    - alert: etcdInsufficientMembers\n      annotations:\n        message: 'etcd cluster \"{{`{{`}} $labels.job {{`}}`}}\": insufficient members ({{`{{`}} $value {{`}}`}}).'\n      expr: sum(up{job=~\".*etcd.*\"} == bool 1) by (job) < ((count(up{job=~\".*etcd.*\"}) by (job) + 1) / 2)\n      for: 3m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: etcdNoLeader\n      annotations:\n        message: 'etcd cluster \"{{`{{`}} $labels.job {{`}}`}}\": member {{`{{`}} $labels.instance {{`}}`}} has no leader.'\n      expr: etcd_server_has_leader{job=~\".*etcd.*\"} == 0\n      for: 1m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: etcdHighNumberOfLeaderChanges\n      annotations:\n        message: 'etcd cluster \"{{`{{`}} $labels.job {{`}}`}}\": instance {{`{{`}} $labels.instance {{`}}`}} has seen {{`{{`}} $value {{`}}`}} leader changes within the last hour.'\n      expr: rate(etcd_server_leader_changes_seen_total{job=~\".*etcd.*\"}[15m]) > 3\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: etcdHighNumberOfFailedGRPCRequests\n      annotations:\n        message: 'etcd cluster \"{{`{{`}} $labels.job {{`}}`}}\": {{`{{`}} $value {{`}}`}}% of requests for {{`{{`}} $labels.grpc_method {{`}}`}} failed on etcd instance {{`{{`}} $labels.instance {{`}}`}}.'\n      expr: |-\n        100 * sum(rate(grpc_server_handled_total{job=~\".*etcd.*\", grpc_code!=\"OK\"}[5m])) BY (job, instance, grpc_service, grpc_method)\n          /\n        sum(rate(grpc_server_handled_total{job=~\".*etcd.*\"}[5m])) BY (job, instance, grpc_service, grpc_method)\n          > 1\n      for: 10m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: etcdHighNumberOfFailedGRPCRequests\n      annotations:\n        message: 'etcd cluster \"{{`{{`}} $labels.job {{`}}`}}\": {{`{{`}} $value {{`}}`}}% of requests for {{`{{`}} $labels.grpc_method {{`}}`}} failed on etcd instance {{`{{`}} $labels.instance {{`}}`}}.'\n      expr: |-\n        100 * sum(rate(grpc_server_handled_total{job=~\".*etcd.*\", grpc_code!=\"OK\"}[5m])) BY (job, instance, grpc_service, grpc_method)\n          /\n        sum(rate(grpc_server_handled_total{job=~\".*etcd.*\"}[5m])) BY (job, instance, grpc_service, grpc_method)\n          > 5\n      for: 5m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: etcdGRPCRequestsSlow\n      annotations:\n        message: 'etcd cluster \"{{`{{`}} $labels.job {{`}}`}}\": gRPC requests to {{`{{`}} $labels.grpc_method {{`}}`}} are taking {{`{{`}} $value {{`}}`}}s on etcd instance {{`{{`}} $labels.instance {{`}}`}}.'\n      expr: |-\n        histogram_quantile(0.99, sum(rate(grpc_server_handling_seconds_bucket{job=~\".*etcd.*\", grpc_type=\"unary\"}[5m])) by (job, instance, grpc_service, grpc_method, le))\n        > 0.15\n      for: 10m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: etcdMemberCommunicationSlow\n      annotations:\n        message: 'etcd cluster \"{{`{{`}} $labels.job {{`}}`}}\": member communication with {{`{{`}} $labels.To {{`}}`}} is taking {{`{{`}} $value {{`}}`}}s on etcd instance {{`{{`}} $labels.instance {{`}}`}}.'\n      expr: |-\n        histogram_quantile(0.99, rate(etcd_network_peer_round_trip_time_seconds_bucket{job=~\".*etcd.*\"}[5m]))\n        > 0.15\n      for: 10m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: etcdHighNumberOfFailedProposals\n      annotations:\n        message: 'etcd cluster \"{{`{{`}} $labels.job {{`}}`}}\": {{`{{`}} $value {{`}}`}} proposal failures within the last hour on etcd instance {{`{{`}} $labels.instance {{`}}`}}.'\n      expr: rate(etcd_server_proposals_failed_total{job=~\".*etcd.*\"}[15m]) > 5\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: etcdHighFsyncDurations\n      annotations:\n        message: 'etcd cluster \"{{`{{`}} $labels.job {{`}}`}}\": 99th percentile fync durations are {{`{{`}} $value {{`}}`}}s on etcd instance {{`{{`}} $labels.instance {{`}}`}}.'\n      expr: |-\n        histogram_quantile(0.99, rate(etcd_disk_wal_fsync_duration_seconds_bucket{job=~\".*etcd.*\"}[5m]))\n        > 0.5\n      for: 10m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: etcdHighCommitDurations\n      annotations:\n        message: 'etcd cluster \"{{`{{`}} $labels.job {{`}}`}}\": 99th percentile commit durations {{`{{`}} $value {{`}}`}}s on etcd instance {{`{{`}} $labels.instance {{`}}`}}.'\n      expr: |-\n        histogram_quantile(0.99, rate(etcd_disk_backend_commit_duration_seconds_bucket{job=~\".*etcd.*\"}[5m]))\n        > 0.25\n      for: 10m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: etcdHighNumberOfFailedHTTPRequests\n      annotations:\n        message: '{{`{{`}} $value {{`}}`}}% of requests for {{`{{`}} $labels.method {{`}}`}} failed on etcd instance {{`{{`}} $labels.instance {{`}}`}}'\n      expr: |-\n        sum(rate(etcd_http_failed_total{job=~\".*etcd.*\", code!=\"404\"}[5m])) BY (method) / sum(rate(etcd_http_received_total{job=~\".*etcd.*\"}[5m]))\n        BY (method) > 0.01\n      for: 10m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: etcdHighNumberOfFailedHTTPRequests\n      annotations:\n        message: '{{`{{`}} $value {{`}}`}}% of requests for {{`{{`}} $labels.method {{`}}`}} failed on etcd instance {{`{{`}} $labels.instance {{`}}`}}.'\n      expr: |-\n        sum(rate(etcd_http_failed_total{job=~\".*etcd.*\", code!=\"404\"}[5m])) BY (method) / sum(rate(etcd_http_received_total{job=~\".*etcd.*\"}[5m]))\n        BY (method) > 0.05\n      for: 10m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: etcdHTTPRequestsSlow\n      annotations:\n        message: etcd instance {{`{{`}} $labels.instance {{`}}`}} HTTP requests to {{`{{`}} $labels.method {{`}}`}} are slow.\n      expr: |-\n        histogram_quantile(0.99, rate(etcd_http_successful_duration_seconds_bucket[5m]))\n        > 0.15\n      for: 10m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/general.rules.yaml",
    "content": "{{- /*\nGenerated from 'general.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kube-prometheus-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.general }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"general.rules\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: general.rules\n    rules:\n    - alert: TargetDown\n      annotations:\n        description: '{{`{{`}} printf \"%.4g\" $value {{`}}`}}% of the {{`{{`}} $labels.job {{`}}`}}/{{`{{`}} $labels.service {{`}}`}} targets in {{`{{`}} $labels.namespace {{`}}`}} namespace are down.'\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-targetdown\n        summary: One or more targets are unreachable.\n      expr: 100 * (count(up == 0) BY (job, namespace, service) / count(up) BY (job, namespace, service)) > 10\n      for: 10m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: Watchdog\n      annotations:\n        description: 'This is an alert meant to ensure that the entire alerting pipeline is functional.\n\n          This alert is always firing, therefore it should always be firing in Alertmanager\n\n          and always fire against a receiver. There are integrations with various notification\n\n          mechanisms that send a notification when this alert is not firing. For example the\n\n          \"DeadMansSnitch\" integration in PagerDuty.\n\n          '\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-watchdog\n        summary: An alert that should always be firing to certify that Alertmanager is working properly.\n      expr: vector(1)\n      labels:\n        severity: none\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/k8s.rules.yaml",
    "content": "{{- /*\nGenerated from 'k8s.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetes-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.k8s }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"k8s.rules\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: k8s.rules\n    rules:\n    - expr: |-\n        sum by (cluster, namespace, pod, container) (\n          irate(container_cpu_usage_seconds_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", image!=\"\"}[5m])\n        ) * on (cluster, namespace, pod) group_left(node) topk by (cluster, namespace, pod) (\n          1, max by(cluster, namespace, pod, node) (kube_pod_info{node!=\"\"})\n        )\n      record: node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate\n    - expr: |-\n        container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", image!=\"\"}\n        * on (namespace, pod) group_left(node) topk by(namespace, pod) (1,\n          max by(namespace, pod, node) (kube_pod_info{node!=\"\"})\n        )\n      record: node_namespace_pod_container:container_memory_working_set_bytes\n    - expr: |-\n        container_memory_rss{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", image!=\"\"}\n        * on (namespace, pod) group_left(node) topk by(namespace, pod) (1,\n          max by(namespace, pod, node) (kube_pod_info{node!=\"\"})\n        )\n      record: node_namespace_pod_container:container_memory_rss\n    - expr: |-\n        container_memory_cache{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", image!=\"\"}\n        * on (namespace, pod) group_left(node) topk by(namespace, pod) (1,\n          max by(namespace, pod, node) (kube_pod_info{node!=\"\"})\n        )\n      record: node_namespace_pod_container:container_memory_cache\n    - expr: |-\n        container_memory_swap{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", image!=\"\"}\n        * on (namespace, pod) group_left(node) topk by(namespace, pod) (1,\n          max by(namespace, pod, node) (kube_pod_info{node!=\"\"})\n        )\n      record: node_namespace_pod_container:container_memory_swap\n    - expr: |-\n        kube_pod_container_resource_requests{resource=\"memory\",job=\"kube-state-metrics\"}  * on (namespace, pod, cluster)\n        group_left() max by (namespace, pod) (\n          (kube_pod_status_phase{phase=~\"Pending|Running\"} == 1)\n        )\n      record: cluster:namespace:pod_memory:active:kube_pod_container_resource_requests\n    - expr: |-\n        sum by (namespace, cluster) (\n            sum by (namespace, pod, cluster) (\n                max by (namespace, pod, container, cluster) (\n                  kube_pod_container_resource_requests{resource=\"memory\",job=\"kube-state-metrics\"}\n                ) * on(namespace, pod, cluster) group_left() max by (namespace, pod) (\n                  kube_pod_status_phase{phase=~\"Pending|Running\"} == 1\n                )\n            )\n        )\n      record: namespace_memory:kube_pod_container_resource_requests:sum\n    - expr: |-\n        kube_pod_container_resource_requests{resource=\"cpu\",job=\"kube-state-metrics\"}  * on (namespace, pod, cluster)\n        group_left() max by (namespace, pod) (\n          (kube_pod_status_phase{phase=~\"Pending|Running\"} == 1)\n        )\n      record: cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests\n    - expr: |-\n        sum by (namespace, cluster) (\n            sum by (namespace, pod, cluster) (\n                max by (namespace, pod, container, cluster) (\n                  kube_pod_container_resource_requests{resource=\"cpu\",job=\"kube-state-metrics\"}\n                ) * on(namespace, pod, cluster) group_left() max by (namespace, pod) (\n                  kube_pod_status_phase{phase=~\"Pending|Running\"} == 1\n                )\n            )\n        )\n      record: namespace_cpu:kube_pod_container_resource_requests:sum\n    - expr: |-\n        kube_pod_container_resource_limits{resource=\"memory\",job=\"kube-state-metrics\"}  * on (namespace, pod, cluster)\n        group_left() max by (namespace, pod) (\n          (kube_pod_status_phase{phase=~\"Pending|Running\"} == 1)\n        )\n      record: cluster:namespace:pod_memory:active:kube_pod_container_resource_limits\n    - expr: |-\n        sum by (namespace, cluster) (\n            sum by (namespace, pod, cluster) (\n                max by (namespace, pod, container, cluster) (\n                  kube_pod_container_resource_limits{resource=\"memory\",job=\"kube-state-metrics\"}\n                ) * on(namespace, pod, cluster) group_left() max by (namespace, pod) (\n                  kube_pod_status_phase{phase=~\"Pending|Running\"} == 1\n                )\n            )\n        )\n      record: namespace_memory:kube_pod_container_resource_limits:sum\n    - expr: |-\n        kube_pod_container_resource_limits{resource=\"cpu\",job=\"kube-state-metrics\"}  * on (namespace, pod, cluster)\n        group_left() max by (namespace, pod) (\n         (kube_pod_status_phase{phase=~\"Pending|Running\"} == 1)\n         )\n      record: cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits\n    - expr: |-\n        sum by (namespace, cluster) (\n            sum by (namespace, pod, cluster) (\n                max by (namespace, pod, container, cluster) (\n                  kube_pod_container_resource_limits{resource=\"cpu\",job=\"kube-state-metrics\"}\n                ) * on(namespace, pod, cluster) group_left() max by (namespace, pod) (\n                  kube_pod_status_phase{phase=~\"Pending|Running\"} == 1\n                )\n            )\n        )\n      record: namespace_cpu:kube_pod_container_resource_limits:sum\n    - expr: |-\n        max by (cluster, namespace, workload, pod) (\n          label_replace(\n            label_replace(\n              kube_pod_owner{job=\"kube-state-metrics\", owner_kind=\"ReplicaSet\"},\n              \"replicaset\", \"$1\", \"owner_name\", \"(.*)\"\n            ) * on(replicaset, namespace) group_left(owner_name) topk by(replicaset, namespace) (\n              1, max by (replicaset, namespace, owner_name) (\n                kube_replicaset_owner{job=\"kube-state-metrics\"}\n              )\n            ),\n            \"workload\", \"$1\", \"owner_name\", \"(.*)\"\n          )\n        )\n      labels:\n        workload_type: deployment\n      record: namespace_workload_pod:kube_pod_owner:relabel\n    - expr: |-\n        max by (cluster, namespace, workload, pod) (\n          label_replace(\n            kube_pod_owner{job=\"kube-state-metrics\", owner_kind=\"DaemonSet\"},\n            \"workload\", \"$1\", \"owner_name\", \"(.*)\"\n          )\n        )\n      labels:\n        workload_type: daemonset\n      record: namespace_workload_pod:kube_pod_owner:relabel\n    - expr: |-\n        max by (cluster, namespace, workload, pod) (\n          label_replace(\n            kube_pod_owner{job=\"kube-state-metrics\", owner_kind=\"StatefulSet\"},\n            \"workload\", \"$1\", \"owner_name\", \"(.*)\"\n          )\n        )\n      labels:\n        workload_type: statefulset\n      record: namespace_workload_pod:kube_pod_owner:relabel\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-apiserver-availability.rules.yaml",
    "content": "{{- /*\nGenerated from 'kube-apiserver-availability.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetes-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.kubeApiServer.enabled .Values.defaultRules.rules.kubeApiserverAvailability }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"kube-apiserver-availability.rules\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - interval: 3m\n    name: kube-apiserver-availability.rules\n    rules:\n    - expr: avg_over_time(code_verb:apiserver_request_total:increase1h[30d]) * 24 * 30\n      record: code_verb:apiserver_request_total:increase30d\n    - expr: sum by (cluster, code) (code_verb:apiserver_request_total:increase30d{verb=~\"LIST|GET\"})\n      labels:\n        verb: read\n      record: code:apiserver_request_total:increase30d\n    - expr: sum by (cluster, code) (code_verb:apiserver_request_total:increase30d{verb=~\"POST|PUT|PATCH|DELETE\"})\n      labels:\n        verb: write\n      record: code:apiserver_request_total:increase30d\n    - expr: |-\n        1 - (\n          (\n            # write too slow\n            sum by (cluster) (increase(apiserver_request_duration_seconds_count{verb=~\"POST|PUT|PATCH|DELETE\"}[30d]))\n            -\n            sum by (cluster) (increase(apiserver_request_duration_seconds_bucket{verb=~\"POST|PUT|PATCH|DELETE\",le=\"1\"}[30d]))\n          ) +\n          (\n            # read too slow\n            sum by (cluster) (increase(apiserver_request_duration_seconds_count{verb=~\"LIST|GET\"}[30d]))\n            -\n            (\n              (\n                sum by (cluster) (increase(apiserver_request_duration_seconds_bucket{verb=~\"LIST|GET\",scope=~\"resource|\",le=\"1\"}[30d]))\n                or\n                vector(0)\n              )\n              +\n              sum by (cluster) (increase(apiserver_request_duration_seconds_bucket{verb=~\"LIST|GET\",scope=\"namespace\",le=\"5\"}[30d]))\n              +\n              sum by (cluster) (increase(apiserver_request_duration_seconds_bucket{verb=~\"LIST|GET\",scope=\"cluster\",le=\"40\"}[30d]))\n            )\n          ) +\n          # errors\n          sum by (cluster) (code:apiserver_request_total:increase30d{code=~\"5..\"} or vector(0))\n        )\n        /\n        sum by (cluster) (code:apiserver_request_total:increase30d)\n      labels:\n        verb: all\n      record: apiserver_request:availability30d\n    - expr: |-\n        1 - (\n          sum by (cluster) (increase(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"LIST|GET\"}[30d]))\n          -\n          (\n            # too slow\n            (\n              sum by (cluster) (increase(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=~\"resource|\",le=\"1\"}[30d]))\n              or\n              vector(0)\n            )\n            +\n            sum by (cluster) (increase(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"namespace\",le=\"5\"}[30d]))\n            +\n            sum by (cluster) (increase(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"cluster\",le=\"40\"}[30d]))\n          )\n          +\n          # errors\n          sum by (cluster) (code:apiserver_request_total:increase30d{verb=\"read\",code=~\"5..\"} or vector(0))\n        )\n        /\n        sum by (cluster) (code:apiserver_request_total:increase30d{verb=\"read\"})\n      labels:\n        verb: read\n      record: apiserver_request:availability30d\n    - expr: |-\n        1 - (\n          (\n            # too slow\n            sum by (cluster) (increase(apiserver_request_duration_seconds_count{verb=~\"POST|PUT|PATCH|DELETE\"}[30d]))\n            -\n            sum by (cluster) (increase(apiserver_request_duration_seconds_bucket{verb=~\"POST|PUT|PATCH|DELETE\",le=\"1\"}[30d]))\n          )\n          +\n          # errors\n          sum by (cluster) (code:apiserver_request_total:increase30d{verb=\"write\",code=~\"5..\"} or vector(0))\n        )\n        /\n        sum by (cluster) (code:apiserver_request_total:increase30d{verb=\"write\"})\n      labels:\n        verb: write\n      record: apiserver_request:availability30d\n    - expr: sum by (cluster,code,resource) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\"}[5m]))\n      labels:\n        verb: read\n      record: code_resource:apiserver_request_total:rate5m\n    - expr: sum by (cluster,code,resource) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[5m]))\n      labels:\n        verb: write\n      record: code_resource:apiserver_request_total:rate5m\n    - expr: sum by (cluster, code, verb) (increase(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET|POST|PUT|PATCH|DELETE\",code=~\"2..\"}[1h]))\n      record: code_verb:apiserver_request_total:increase1h\n    - expr: sum by (cluster, code, verb) (increase(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET|POST|PUT|PATCH|DELETE\",code=~\"3..\"}[1h]))\n      record: code_verb:apiserver_request_total:increase1h\n    - expr: sum by (cluster, code, verb) (increase(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET|POST|PUT|PATCH|DELETE\",code=~\"4..\"}[1h]))\n      record: code_verb:apiserver_request_total:increase1h\n    - expr: sum by (cluster, code, verb) (increase(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET|POST|PUT|PATCH|DELETE\",code=~\"5..\"}[1h]))\n      record: code_verb:apiserver_request_total:increase1h\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-apiserver-burnrate.rules.yaml",
    "content": "{{- /*\nGenerated from 'kube-apiserver-burnrate.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetes-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"kube-apiserver-burnrate.rules\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: kube-apiserver-burnrate.rules\n    rules:\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"LIST|GET\"}[1d]))\n            -\n            (\n              (\n                sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=~\"resource|\",le=\"1\"}[1d]))\n                or\n                vector(0)\n              )\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"namespace\",le=\"5\"}[1d]))\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"cluster\",le=\"40\"}[1d]))\n            )\n          )\n          +\n          # errors\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\",code=~\"5..\"}[1d]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\"}[1d]))\n      labels:\n        verb: read\n      record: apiserver_request:burnrate1d\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"LIST|GET\"}[1h]))\n            -\n            (\n              (\n                sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=~\"resource|\",le=\"1\"}[1h]))\n                or\n                vector(0)\n              )\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"namespace\",le=\"5\"}[1h]))\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"cluster\",le=\"40\"}[1h]))\n            )\n          )\n          +\n          # errors\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\",code=~\"5..\"}[1h]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\"}[1h]))\n      labels:\n        verb: read\n      record: apiserver_request:burnrate1h\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"LIST|GET\"}[2h]))\n            -\n            (\n              (\n                sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=~\"resource|\",le=\"1\"}[2h]))\n                or\n                vector(0)\n              )\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"namespace\",le=\"5\"}[2h]))\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"cluster\",le=\"40\"}[2h]))\n            )\n          )\n          +\n          # errors\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\",code=~\"5..\"}[2h]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\"}[2h]))\n      labels:\n        verb: read\n      record: apiserver_request:burnrate2h\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"LIST|GET\"}[30m]))\n            -\n            (\n              (\n                sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=~\"resource|\",le=\"1\"}[30m]))\n                or\n                vector(0)\n              )\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"namespace\",le=\"5\"}[30m]))\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"cluster\",le=\"40\"}[30m]))\n            )\n          )\n          +\n          # errors\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\",code=~\"5..\"}[30m]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\"}[30m]))\n      labels:\n        verb: read\n      record: apiserver_request:burnrate30m\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"LIST|GET\"}[3d]))\n            -\n            (\n              (\n                sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=~\"resource|\",le=\"1\"}[3d]))\n                or\n                vector(0)\n              )\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"namespace\",le=\"5\"}[3d]))\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"cluster\",le=\"40\"}[3d]))\n            )\n          )\n          +\n          # errors\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\",code=~\"5..\"}[3d]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\"}[3d]))\n      labels:\n        verb: read\n      record: apiserver_request:burnrate3d\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"LIST|GET\"}[5m]))\n            -\n            (\n              (\n                sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=~\"resource|\",le=\"1\"}[5m]))\n                or\n                vector(0)\n              )\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"namespace\",le=\"5\"}[5m]))\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"cluster\",le=\"40\"}[5m]))\n            )\n          )\n          +\n          # errors\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\",code=~\"5..\"}[5m]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\"}[5m]))\n      labels:\n        verb: read\n      record: apiserver_request:burnrate5m\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"LIST|GET\"}[6h]))\n            -\n            (\n              (\n                sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=~\"resource|\",le=\"1\"}[6h]))\n                or\n                vector(0)\n              )\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"namespace\",le=\"5\"}[6h]))\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"cluster\",le=\"40\"}[6h]))\n            )\n          )\n          +\n          # errors\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\",code=~\"5..\"}[6h]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\"}[6h]))\n      labels:\n        verb: read\n      record: apiserver_request:burnrate6h\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[1d]))\n            -\n            sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",le=\"1\"}[1d]))\n          )\n          +\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",code=~\"5..\"}[1d]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[1d]))\n      labels:\n        verb: write\n      record: apiserver_request:burnrate1d\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[1h]))\n            -\n            sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",le=\"1\"}[1h]))\n          )\n          +\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",code=~\"5..\"}[1h]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[1h]))\n      labels:\n        verb: write\n      record: apiserver_request:burnrate1h\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[2h]))\n            -\n            sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",le=\"1\"}[2h]))\n          )\n          +\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",code=~\"5..\"}[2h]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[2h]))\n      labels:\n        verb: write\n      record: apiserver_request:burnrate2h\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[30m]))\n            -\n            sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",le=\"1\"}[30m]))\n          )\n          +\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",code=~\"5..\"}[30m]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[30m]))\n      labels:\n        verb: write\n      record: apiserver_request:burnrate30m\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[3d]))\n            -\n            sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",le=\"1\"}[3d]))\n          )\n          +\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",code=~\"5..\"}[3d]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[3d]))\n      labels:\n        verb: write\n      record: apiserver_request:burnrate3d\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[5m]))\n            -\n            sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",le=\"1\"}[5m]))\n          )\n          +\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",code=~\"5..\"}[5m]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[5m]))\n      labels:\n        verb: write\n      record: apiserver_request:burnrate5m\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[6h]))\n            -\n            sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",le=\"1\"}[6h]))\n          )\n          +\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",code=~\"5..\"}[6h]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[6h]))\n      labels:\n        verb: write\n      record: apiserver_request:burnrate6h\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-apiserver-histogram.rules.yaml",
    "content": "{{- /*\nGenerated from 'kube-apiserver-histogram.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetes-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"kube-apiserver-histogram.rules\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: kube-apiserver-histogram.rules\n    rules:\n    - expr: histogram_quantile(0.99, sum by (cluster, le, resource) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\"}[5m]))) > 0\n      labels:\n        quantile: '0.99'\n        verb: read\n      record: cluster_quantile:apiserver_request_duration_seconds:histogram_quantile\n    - expr: histogram_quantile(0.99, sum by (cluster, le, resource) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[5m]))) > 0\n      labels:\n        quantile: '0.99'\n        verb: write\n      record: cluster_quantile:apiserver_request_duration_seconds:histogram_quantile\n    - expr: histogram_quantile(0.99, sum(rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",subresource!=\"log\",verb!~\"LIST|WATCH|WATCHLIST|DELETECOLLECTION|PROXY|CONNECT\"}[5m])) without(instance, pod))\n      labels:\n        quantile: '0.99'\n      record: cluster_quantile:apiserver_request_duration_seconds:histogram_quantile\n    - expr: histogram_quantile(0.9, sum(rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",subresource!=\"log\",verb!~\"LIST|WATCH|WATCHLIST|DELETECOLLECTION|PROXY|CONNECT\"}[5m])) without(instance, pod))\n      labels:\n        quantile: '0.9'\n      record: cluster_quantile:apiserver_request_duration_seconds:histogram_quantile\n    - expr: histogram_quantile(0.5, sum(rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",subresource!=\"log\",verb!~\"LIST|WATCH|WATCHLIST|DELETECOLLECTION|PROXY|CONNECT\"}[5m])) without(instance, pod))\n      labels:\n        quantile: '0.5'\n      record: cluster_quantile:apiserver_request_duration_seconds:histogram_quantile\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-apiserver-slos.yaml",
    "content": "{{- /*\nGenerated from 'kube-apiserver-slos' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetes-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.kubeApiServer.enabled .Values.defaultRules.rules.kubeApiserverSlos }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"kube-apiserver-slos\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: kube-apiserver-slos\n    rules:\n    - alert: KubeAPIErrorBudgetBurn\n      annotations:\n        description: The API server is burning too much error budget.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeapierrorbudgetburn\n        summary: The API server is burning too much error budget.\n      expr: |-\n        sum(apiserver_request:burnrate1h) > (14.40 * 0.01000)\n        and\n        sum(apiserver_request:burnrate5m) > (14.40 * 0.01000)\n      for: 2m\n      labels:\n        long: 1h\n        severity: critical\n        short: 5m\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeAPIErrorBudgetBurn\n      annotations:\n        description: The API server is burning too much error budget.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeapierrorbudgetburn\n        summary: The API server is burning too much error budget.\n      expr: |-\n        sum(apiserver_request:burnrate6h) > (6.00 * 0.01000)\n        and\n        sum(apiserver_request:burnrate30m) > (6.00 * 0.01000)\n      for: 15m\n      labels:\n        long: 6h\n        severity: critical\n        short: 30m\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeAPIErrorBudgetBurn\n      annotations:\n        description: The API server is burning too much error budget.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeapierrorbudgetburn\n        summary: The API server is burning too much error budget.\n      expr: |-\n        sum(apiserver_request:burnrate1d) > (3.00 * 0.01000)\n        and\n        sum(apiserver_request:burnrate2h) > (3.00 * 0.01000)\n      for: 1h\n      labels:\n        long: 1d\n        severity: warning\n        short: 2h\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeAPIErrorBudgetBurn\n      annotations:\n        description: The API server is burning too much error budget.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeapierrorbudgetburn\n        summary: The API server is burning too much error budget.\n      expr: |-\n        sum(apiserver_request:burnrate3d) > (1.00 * 0.01000)\n        and\n        sum(apiserver_request:burnrate6h) > (1.00 * 0.01000)\n      for: 3h\n      labels:\n        long: 3d\n        severity: warning\n        short: 6h\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-apiserver.rules.yaml",
    "content": "{{- /*\nGenerated from 'kube-apiserver.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetes-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.kubeApiServer.enabled .Values.defaultRules.rules.kubeApiserver }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"kube-apiserver.rules\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: kube-apiserver.rules\n    rules:\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"LIST|GET\"}[1d]))\n            -\n            (\n              (\n                sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=~\"resource|\",le=\"0.1\"}[1d]))\n                or\n                vector(0)\n              )\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"namespace\",le=\"0.5\"}[1d]))\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"cluster\",le=\"5\"}[1d]))\n            )\n          )\n          +\n          # errors\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\",code=~\"5..\"}[1d]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\"}[1d]))\n      labels:\n        verb: read\n      record: apiserver_request:burnrate1d\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"LIST|GET\"}[1h]))\n            -\n            (\n              (\n                sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=~\"resource|\",le=\"0.1\"}[1h]))\n                or\n                vector(0)\n              )\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"namespace\",le=\"0.5\"}[1h]))\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"cluster\",le=\"5\"}[1h]))\n            )\n          )\n          +\n          # errors\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\",code=~\"5..\"}[1h]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\"}[1h]))\n      labels:\n        verb: read\n      record: apiserver_request:burnrate1h\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"LIST|GET\"}[2h]))\n            -\n            (\n              (\n                sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=~\"resource|\",le=\"0.1\"}[2h]))\n                or\n                vector(0)\n              )\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"namespace\",le=\"0.5\"}[2h]))\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"cluster\",le=\"5\"}[2h]))\n            )\n          )\n          +\n          # errors\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\",code=~\"5..\"}[2h]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\"}[2h]))\n      labels:\n        verb: read\n      record: apiserver_request:burnrate2h\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"LIST|GET\"}[30m]))\n            -\n            (\n              (\n                sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=~\"resource|\",le=\"0.1\"}[30m]))\n                or\n                vector(0)\n              )\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"namespace\",le=\"0.5\"}[30m]))\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"cluster\",le=\"5\"}[30m]))\n            )\n          )\n          +\n          # errors\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\",code=~\"5..\"}[30m]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\"}[30m]))\n      labels:\n        verb: read\n      record: apiserver_request:burnrate30m\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"LIST|GET\"}[3d]))\n            -\n            (\n              (\n                sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=~\"resource|\",le=\"0.1\"}[3d]))\n                or\n                vector(0)\n              )\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"namespace\",le=\"0.5\"}[3d]))\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"cluster\",le=\"5\"}[3d]))\n            )\n          )\n          +\n          # errors\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\",code=~\"5..\"}[3d]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\"}[3d]))\n      labels:\n        verb: read\n      record: apiserver_request:burnrate3d\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"LIST|GET\"}[5m]))\n            -\n            (\n              (\n                sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=~\"resource|\",le=\"0.1\"}[5m]))\n                or\n                vector(0)\n              )\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"namespace\",le=\"0.5\"}[5m]))\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"cluster\",le=\"5\"}[5m]))\n            )\n          )\n          +\n          # errors\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\",code=~\"5..\"}[5m]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\"}[5m]))\n      labels:\n        verb: read\n      record: apiserver_request:burnrate5m\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"LIST|GET\"}[6h]))\n            -\n            (\n              (\n                sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=~\"resource|\",le=\"0.1\"}[6h]))\n                or\n                vector(0)\n              )\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"namespace\",le=\"0.5\"}[6h]))\n              +\n              sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\",scope=\"cluster\",le=\"5\"}[6h]))\n            )\n          )\n          +\n          # errors\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\",code=~\"5..\"}[6h]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\"}[6h]))\n      labels:\n        verb: read\n      record: apiserver_request:burnrate6h\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[1d]))\n            -\n            sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",le=\"1\"}[1d]))\n          )\n          +\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",code=~\"5..\"}[1d]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[1d]))\n      labels:\n        verb: write\n      record: apiserver_request:burnrate1d\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[1h]))\n            -\n            sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",le=\"1\"}[1h]))\n          )\n          +\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",code=~\"5..\"}[1h]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[1h]))\n      labels:\n        verb: write\n      record: apiserver_request:burnrate1h\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[2h]))\n            -\n            sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",le=\"1\"}[2h]))\n          )\n          +\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",code=~\"5..\"}[2h]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[2h]))\n      labels:\n        verb: write\n      record: apiserver_request:burnrate2h\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[30m]))\n            -\n            sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",le=\"1\"}[30m]))\n          )\n          +\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",code=~\"5..\"}[30m]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[30m]))\n      labels:\n        verb: write\n      record: apiserver_request:burnrate30m\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[3d]))\n            -\n            sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",le=\"1\"}[3d]))\n          )\n          +\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",code=~\"5..\"}[3d]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[3d]))\n      labels:\n        verb: write\n      record: apiserver_request:burnrate3d\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[5m]))\n            -\n            sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",le=\"1\"}[5m]))\n          )\n          +\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",code=~\"5..\"}[5m]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[5m]))\n      labels:\n        verb: write\n      record: apiserver_request:burnrate5m\n    - expr: |-\n        (\n          (\n            # too slow\n            sum by (cluster) (rate(apiserver_request_duration_seconds_count{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[6h]))\n            -\n            sum by (cluster) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",le=\"1\"}[6h]))\n          )\n          +\n          sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\",code=~\"5..\"}[6h]))\n        )\n        /\n        sum by (cluster) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[6h]))\n      labels:\n        verb: write\n      record: apiserver_request:burnrate6h\n    - expr: sum by (cluster,code,resource) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"LIST|GET\"}[5m]))\n      labels:\n        verb: read\n      record: code_resource:apiserver_request_total:rate5m\n    - expr: sum by (cluster,code,resource) (rate(apiserver_request_total{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[5m]))\n      labels:\n        verb: write\n      record: code_resource:apiserver_request_total:rate5m\n    - expr: histogram_quantile(0.99, sum by (cluster, le, resource) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"LIST|GET\"}[5m]))) > 0\n      labels:\n        quantile: '0.99'\n        verb: read\n      record: cluster_quantile:apiserver_request_duration_seconds:histogram_quantile\n    - expr: histogram_quantile(0.99, sum by (cluster, le, resource) (rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",verb=~\"POST|PUT|PATCH|DELETE\"}[5m]))) > 0\n      labels:\n        quantile: '0.99'\n        verb: write\n      record: cluster_quantile:apiserver_request_duration_seconds:histogram_quantile\n    - expr: histogram_quantile(0.99, sum(rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",subresource!=\"log\",verb!~\"LIST|WATCH|WATCHLIST|DELETECOLLECTION|PROXY|CONNECT\"}[5m])) without(instance, pod))\n      labels:\n        quantile: '0.99'\n      record: cluster_quantile:apiserver_request_duration_seconds:histogram_quantile\n    - expr: histogram_quantile(0.9, sum(rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",subresource!=\"log\",verb!~\"LIST|WATCH|WATCHLIST|DELETECOLLECTION|PROXY|CONNECT\"}[5m])) without(instance, pod))\n      labels:\n        quantile: '0.9'\n      record: cluster_quantile:apiserver_request_duration_seconds:histogram_quantile\n    - expr: histogram_quantile(0.5, sum(rate(apiserver_request_duration_seconds_bucket{job=\"apiserver\",subresource!=\"log\",verb!~\"LIST|WATCH|WATCHLIST|DELETECOLLECTION|PROXY|CONNECT\"}[5m])) without(instance, pod))\n      labels:\n        quantile: '0.5'\n      record: cluster_quantile:apiserver_request_duration_seconds:histogram_quantile\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-prometheus-general.rules.yaml",
    "content": "{{- /*\nGenerated from 'kube-prometheus-general.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kube-prometheus-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubePrometheusGeneral }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"kube-prometheus-general.rules\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: kube-prometheus-general.rules\n    rules:\n    - expr: count without(instance, pod, node) (up == 1)\n      record: count:up1\n    - expr: count without(instance, pod, node) (up == 0)\n      record: count:up0\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-prometheus-node-recording.rules.yaml",
    "content": "{{- /*\nGenerated from 'kube-prometheus-node-recording.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kube-prometheus-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubePrometheusNodeRecording }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"kube-prometheus-node-recording.rules\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: kube-prometheus-node-recording.rules\n    rules:\n    - expr: sum(rate(node_cpu_seconds_total{mode!=\"idle\",mode!=\"iowait\",mode!=\"steal\"}[3m])) BY (instance)\n      record: instance:node_cpu:rate:sum\n    - expr: sum(rate(node_network_receive_bytes_total[3m])) BY (instance)\n      record: instance:node_network_receive_bytes:rate:sum\n    - expr: sum(rate(node_network_transmit_bytes_total[3m])) BY (instance)\n      record: instance:node_network_transmit_bytes:rate:sum\n    - expr: sum(rate(node_cpu_seconds_total{mode!=\"idle\",mode!=\"iowait\",mode!=\"steal\"}[5m])) WITHOUT (cpu, mode) / ON(instance) GROUP_LEFT() count(sum(node_cpu_seconds_total) BY (instance, cpu)) BY (instance)\n      record: instance:node_cpu:ratio\n    - expr: sum(rate(node_cpu_seconds_total{mode!=\"idle\",mode!=\"iowait\",mode!=\"steal\"}[5m]))\n      record: cluster:node_cpu:sum_rate5m\n    - expr: cluster:node_cpu_seconds_total:rate5m / count(sum(node_cpu_seconds_total) BY (instance, cpu))\n      record: cluster:node_cpu:ratio\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-scheduler.rules.yaml",
    "content": "{{- /*\nGenerated from 'kube-scheduler.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetes-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.kubeScheduler.enabled .Values.defaultRules.rules.kubeScheduler }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"kube-scheduler.rules\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: kube-scheduler.rules\n    rules:\n    - expr: histogram_quantile(0.99, sum(rate(scheduler_e2e_scheduling_duration_seconds_bucket{job=\"kube-scheduler\"}[5m])) without(instance, pod))\n      labels:\n        quantile: '0.99'\n      record: cluster_quantile:scheduler_e2e_scheduling_duration_seconds:histogram_quantile\n    - expr: histogram_quantile(0.99, sum(rate(scheduler_scheduling_algorithm_duration_seconds_bucket{job=\"kube-scheduler\"}[5m])) without(instance, pod))\n      labels:\n        quantile: '0.99'\n      record: cluster_quantile:scheduler_scheduling_algorithm_duration_seconds:histogram_quantile\n    - expr: histogram_quantile(0.99, sum(rate(scheduler_binding_duration_seconds_bucket{job=\"kube-scheduler\"}[5m])) without(instance, pod))\n      labels:\n        quantile: '0.99'\n      record: cluster_quantile:scheduler_binding_duration_seconds:histogram_quantile\n    - expr: histogram_quantile(0.9, sum(rate(scheduler_e2e_scheduling_duration_seconds_bucket{job=\"kube-scheduler\"}[5m])) without(instance, pod))\n      labels:\n        quantile: '0.9'\n      record: cluster_quantile:scheduler_e2e_scheduling_duration_seconds:histogram_quantile\n    - expr: histogram_quantile(0.9, sum(rate(scheduler_scheduling_algorithm_duration_seconds_bucket{job=\"kube-scheduler\"}[5m])) without(instance, pod))\n      labels:\n        quantile: '0.9'\n      record: cluster_quantile:scheduler_scheduling_algorithm_duration_seconds:histogram_quantile\n    - expr: histogram_quantile(0.9, sum(rate(scheduler_binding_duration_seconds_bucket{job=\"kube-scheduler\"}[5m])) without(instance, pod))\n      labels:\n        quantile: '0.9'\n      record: cluster_quantile:scheduler_binding_duration_seconds:histogram_quantile\n    - expr: histogram_quantile(0.5, sum(rate(scheduler_e2e_scheduling_duration_seconds_bucket{job=\"kube-scheduler\"}[5m])) without(instance, pod))\n      labels:\n        quantile: '0.5'\n      record: cluster_quantile:scheduler_e2e_scheduling_duration_seconds:histogram_quantile\n    - expr: histogram_quantile(0.5, sum(rate(scheduler_scheduling_algorithm_duration_seconds_bucket{job=\"kube-scheduler\"}[5m])) without(instance, pod))\n      labels:\n        quantile: '0.5'\n      record: cluster_quantile:scheduler_scheduling_algorithm_duration_seconds:histogram_quantile\n    - expr: histogram_quantile(0.5, sum(rate(scheduler_binding_duration_seconds_bucket{job=\"kube-scheduler\"}[5m])) without(instance, pod))\n      labels:\n        quantile: '0.5'\n      record: cluster_quantile:scheduler_binding_duration_seconds:histogram_quantile\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-state-metrics.yaml",
    "content": "{{- /*\nGenerated from 'kube-state-metrics' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kube-state-metrics-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubeStateMetrics }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"kube-state-metrics\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: kube-state-metrics\n    rules:\n    - alert: KubeStateMetricsListErrors\n      annotations:\n        description: kube-state-metrics is experiencing errors at an elevated rate in list operations. This is likely causing it to not be able to expose metrics about Kubernetes objects correctly or at all.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubestatemetricslisterrors\n        summary: kube-state-metrics is experiencing errors in list operations.\n      expr: |-\n        (sum(rate(kube_state_metrics_list_total{job=\"kube-state-metrics\",result=\"error\"}[5m]))\n          /\n        sum(rate(kube_state_metrics_list_total{job=\"kube-state-metrics\"}[5m])))\n        > 0.01\n      for: 15m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeStateMetricsWatchErrors\n      annotations:\n        description: kube-state-metrics is experiencing errors at an elevated rate in watch operations. This is likely causing it to not be able to expose metrics about Kubernetes objects correctly or at all.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubestatemetricswatcherrors\n        summary: kube-state-metrics is experiencing errors in watch operations.\n      expr: |-\n        (sum(rate(kube_state_metrics_watch_total{job=\"kube-state-metrics\",result=\"error\"}[5m]))\n          /\n        sum(rate(kube_state_metrics_watch_total{job=\"kube-state-metrics\"}[5m])))\n        > 0.01\n      for: 15m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeStateMetricsShardingMismatch\n      annotations:\n        description: kube-state-metrics pods are running with different --total-shards configuration, some Kubernetes objects may be exposed multiple times or not exposed at all.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubestatemetricsshardingmismatch\n        summary: kube-state-metrics sharding is misconfigured.\n      expr: stdvar (kube_state_metrics_total_shards{job=\"kube-state-metrics\"}) != 0\n      for: 15m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeStateMetricsShardsMissing\n      annotations:\n        description: kube-state-metrics shards are missing, some Kubernetes objects are not being exposed.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubestatemetricsshardsmissing\n        summary: kube-state-metrics shards are missing.\n      expr: |-\n        2^max(kube_state_metrics_total_shards{job=\"kube-state-metrics\"}) - 1\n          -\n        sum( 2 ^ max by (shard_ordinal) (kube_state_metrics_shard_ordinal{job=\"kube-state-metrics\"}) )\n        != 0\n      for: 15m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/kubelet.rules.yaml",
    "content": "{{- /*\nGenerated from 'kubelet.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetes-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.kubelet.enabled .Values.defaultRules.rules.kubelet }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"kubelet.rules\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: kubelet.rules\n    rules:\n    - expr: histogram_quantile(0.99, sum(rate(kubelet_pleg_relist_duration_seconds_bucket[5m])) by (instance, le) * on(instance) group_left(node) kubelet_node_name{job=\"kubelet\", metrics_path=\"/metrics\"})\n      labels:\n        quantile: '0.99'\n      record: node_quantile:kubelet_pleg_relist_duration_seconds:histogram_quantile\n    - expr: histogram_quantile(0.9, sum(rate(kubelet_pleg_relist_duration_seconds_bucket[5m])) by (instance, le) * on(instance) group_left(node) kubelet_node_name{job=\"kubelet\", metrics_path=\"/metrics\"})\n      labels:\n        quantile: '0.9'\n      record: node_quantile:kubelet_pleg_relist_duration_seconds:histogram_quantile\n    - expr: histogram_quantile(0.5, sum(rate(kubelet_pleg_relist_duration_seconds_bucket[5m])) by (instance, le) * on(instance) group_left(node) kubelet_node_name{job=\"kubelet\", metrics_path=\"/metrics\"})\n      labels:\n        quantile: '0.5'\n      record: node_quantile:kubelet_pleg_relist_duration_seconds:histogram_quantile\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-apps.yaml",
    "content": "{{- /*\nGenerated from 'kubernetes-apps' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetes-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesApps }}\n{{- $targetNamespace := .Values.defaultRules.appNamespacesTarget }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"kubernetes-apps\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: kubernetes-apps\n    rules:\n    - alert: KubePodCrashLooping\n      annotations:\n        description: Pod {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}} ({{`{{`}} $labels.container {{`}}`}}) is restarting {{`{{`}} printf \"%.2f\" $value {{`}}`}} times / 10 minutes.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubepodcrashlooping\n        summary: Pod is crash looping.\n      expr: |-\n        increase(kube_pod_container_status_restarts_total{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}[10m]) > 0\n        and\n        kube_pod_container_status_waiting{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"} == 1\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubePodNotReady\n      annotations:\n        description: Pod {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}} has been in a non-ready state for longer than 15 minutes.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubepodnotready\n        summary: Pod has been in a non-ready state for more than 15 minutes.\n      expr: |-\n        sum by (namespace, pod) (\n          max by(namespace, pod) (\n            kube_pod_status_phase{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\", phase=~\"Pending|Unknown\"}\n          ) * on(namespace, pod) group_left(owner_kind) topk by(namespace, pod) (\n            1, max by(namespace, pod, owner_kind) (kube_pod_owner{owner_kind!=\"Job\"})\n          )\n        ) > 0\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeDeploymentGenerationMismatch\n      annotations:\n        description: Deployment generation for {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.deployment {{`}}`}} does not match, this indicates that the Deployment has failed but has not been rolled back.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubedeploymentgenerationmismatch\n        summary: Deployment generation mismatch due to possible roll-back\n      expr: |-\n        kube_deployment_status_observed_generation{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n          !=\n        kube_deployment_metadata_generation{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeDeploymentReplicasMismatch\n      annotations:\n        description: Deployment {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.deployment {{`}}`}} has not matched the expected number of replicas for longer than 15 minutes.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubedeploymentreplicasmismatch\n        summary: Deployment has not matched the expected number of replicas.\n      expr: |-\n        (\n          kube_deployment_spec_replicas{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n            >\n          kube_deployment_status_replicas_available{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n        ) and (\n          changes(kube_deployment_status_replicas_updated{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}[10m])\n            ==\n          0\n        )\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeStatefulSetReplicasMismatch\n      annotations:\n        description: StatefulSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.statefulset {{`}}`}} has not matched the expected number of replicas for longer than 15 minutes.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubestatefulsetreplicasmismatch\n        summary: Deployment has not matched the expected number of replicas.\n      expr: |-\n        (\n          kube_statefulset_status_replicas_ready{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n            !=\n          kube_statefulset_status_replicas{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n        ) and (\n          changes(kube_statefulset_status_replicas_updated{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}[10m])\n            ==\n          0\n        )\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeStatefulSetGenerationMismatch\n      annotations:\n        description: StatefulSet generation for {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.statefulset {{`}}`}} does not match, this indicates that the StatefulSet has failed but has not been rolled back.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubestatefulsetgenerationmismatch\n        summary: StatefulSet generation mismatch due to possible roll-back\n      expr: |-\n        kube_statefulset_status_observed_generation{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n          !=\n        kube_statefulset_metadata_generation{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeStatefulSetUpdateNotRolledOut\n      annotations:\n        description: StatefulSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.statefulset {{`}}`}} update has not been rolled out.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubestatefulsetupdatenotrolledout\n        summary: StatefulSet update has not been rolled out.\n      expr: |-\n        (\n          max without (revision) (\n            kube_statefulset_status_current_revision{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n              unless\n            kube_statefulset_status_update_revision{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n          )\n            *\n          (\n            kube_statefulset_replicas{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n              !=\n            kube_statefulset_status_replicas_updated{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n          )\n        )  and (\n          changes(kube_statefulset_status_replicas_updated{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}[5m])\n            ==\n          0\n        )\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeDaemonSetRolloutStuck\n      annotations:\n        description: DaemonSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.daemonset {{`}}`}} has not finished or progressed for at least 15 minutes.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubedaemonsetrolloutstuck\n        summary: DaemonSet rollout is stuck.\n      expr: |-\n        (\n          (\n            kube_daemonset_status_current_number_scheduled{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n             !=\n            kube_daemonset_status_desired_number_scheduled{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n          ) or (\n            kube_daemonset_status_number_misscheduled{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n             !=\n            0\n          ) or (\n            kube_daemonset_updated_number_scheduled{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n             !=\n            kube_daemonset_status_desired_number_scheduled{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n          ) or (\n            kube_daemonset_status_number_available{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n             !=\n            kube_daemonset_status_desired_number_scheduled{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n          )\n        ) and (\n          changes(kube_daemonset_updated_number_scheduled{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}[5m])\n            ==\n          0\n        )\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeContainerWaiting\n      annotations:\n        description: Pod {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}} container {{`{{`}} $labels.container{{`}}`}} has been in waiting state for longer than 1 hour.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubecontainerwaiting\n        summary: Pod container waiting longer than 1 hour\n      expr: sum by (namespace, pod, container) (kube_pod_container_status_waiting_reason{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}) > 0\n      for: 1h\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeDaemonSetNotScheduled\n      annotations:\n        description: '{{`{{`}} $value {{`}}`}} Pods of DaemonSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.daemonset {{`}}`}} are not scheduled.'\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubedaemonsetnotscheduled\n        summary: DaemonSet pods are not scheduled.\n      expr: |-\n        kube_daemonset_status_desired_number_scheduled{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n          -\n        kube_daemonset_status_current_number_scheduled{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"} > 0\n      for: 10m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeDaemonSetMisScheduled\n      annotations:\n        description: '{{`{{`}} $value {{`}}`}} Pods of DaemonSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.daemonset {{`}}`}} are running where they are not supposed to run.'\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubedaemonsetmisscheduled\n        summary: DaemonSet pods are misscheduled.\n      expr: kube_daemonset_status_number_misscheduled{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"} > 0\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeJobCompletion\n      annotations:\n        description: Job {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.job_name {{`}}`}} is taking more than 12 hours to complete.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubejobcompletion\n        summary: Job did not complete in time\n      expr: kube_job_spec_completions{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"} - kube_job_status_succeeded{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}  > 0\n      for: 12h\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeJobFailed\n      annotations:\n        description: Job {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.job_name {{`}}`}} failed to complete. Removing failed job after investigation should clear this alert.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubejobfailed\n        summary: Job failed to complete.\n      expr: kube_job_failed{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}  > 0\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeHpaReplicasMismatch\n      annotations:\n        description: HPA {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.horizontalpodautoscaler  {{`}}`}} has not matched the desired number of replicas for longer than 15 minutes.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubehpareplicasmismatch\n        summary: HPA has not matched descired number of replicas.\n      expr: |-\n        (kube_horizontalpodautoscaler_status_desired_replicas{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n          !=\n        kube_horizontalpodautoscaler_status_current_replicas{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"})\n          and\n        (kube_horizontalpodautoscaler_status_current_replicas{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n          >\n        kube_horizontalpodautoscaler_spec_min_replicas{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"})\n          and\n        (kube_horizontalpodautoscaler_status_current_replicas{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n          <\n        kube_horizontalpodautoscaler_spec_max_replicas{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"})\n          and\n        changes(kube_horizontalpodautoscaler_status_current_replicas{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}[15m]) == 0\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeHpaMaxedOut\n      annotations:\n        description: HPA {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.horizontalpodautoscaler  {{`}}`}} has been running at max replicas for longer than 15 minutes.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubehpamaxedout\n        summary: HPA is running at max replicas\n      expr: |-\n        kube_horizontalpodautoscaler_status_current_replicas{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n          ==\n        kube_horizontalpodautoscaler_spec_max_replicas{job=\"kube-state-metrics\", namespace=~\"{{ $targetNamespace }}\"}\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-resources.yaml",
    "content": "{{- /*\nGenerated from 'kubernetes-resources' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetes-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesResources }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"kubernetes-resources\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: kubernetes-resources\n    rules:\n    - alert: KubeCPUOvercommit\n      annotations:\n        description: Cluster has overcommitted CPU resource requests for Pods and cannot tolerate node failure.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubecpuovercommit\n        summary: Cluster has overcommitted CPU resource requests.\n      expr: |-\n        sum(namespace_cpu:kube_pod_container_resource_requests:sum{})\n          /\n        sum(kube_node_status_allocatable{resource=\"cpu\"})\n          >\n        ((count(kube_node_status_allocatable{resource=\"cpu\"}) > 1) - 1) / count(kube_node_status_allocatable{resource=\"cpu\"})\n      for: 5m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeMemoryOvercommit\n      annotations:\n        description: Cluster has overcommitted memory resource requests for Pods and cannot tolerate node failure.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubememoryovercommit\n        summary: Cluster has overcommitted memory resource requests.\n      expr: |-\n        sum(namespace_memory:kube_pod_container_resource_requests:sum{})\n          /\n        sum(kube_node_status_allocatable{resource=\"memory\"})\n          >\n        ((count(kube_node_status_allocatable{resource=\"memory\"}) > 1) - 1)\n          /\n        count(kube_node_status_allocatable{resource=\"memory\"})\n      for: 5m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeCPUQuotaOvercommit\n      annotations:\n        description: Cluster has overcommitted CPU resource requests for Namespaces.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubecpuquotaovercommit\n        summary: Cluster has overcommitted CPU resource requests.\n      expr: |-\n        sum(kube_resourcequota{job=\"kube-state-metrics\", type=\"hard\", resource=\"cpu\"})\n          /\n        sum(kube_node_status_allocatable{resource=\"cpu\"})\n          > 1.5\n      for: 5m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeMemoryQuotaOvercommit\n      annotations:\n        description: Cluster has overcommitted memory resource requests for Namespaces.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubememoryquotaovercommit\n        summary: Cluster has overcommitted memory resource requests.\n      expr: |-\n        sum(kube_resourcequota{job=\"kube-state-metrics\", type=\"hard\", resource=\"memory\"})\n          /\n        sum(kube_node_status_allocatable{resource=\"memory\",job=\"kube-state-metrics\"})\n          > 1.5\n      for: 5m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeQuotaAlmostFull\n      annotations:\n        description: Namespace {{`{{`}} $labels.namespace {{`}}`}} is using {{`{{`}} $value | humanizePercentage {{`}}`}} of its {{`{{`}} $labels.resource {{`}}`}} quota.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubequotaalmostfull\n        summary: Namespace quota is going to be full.\n      expr: |-\n        kube_resourcequota{job=\"kube-state-metrics\", type=\"used\"}\n          / ignoring(instance, job, type)\n        (kube_resourcequota{job=\"kube-state-metrics\", type=\"hard\"} > 0)\n          > 0.9 < 1\n      for: 15m\n      labels:\n        severity: info\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeQuotaFullyUsed\n      annotations:\n        description: Namespace {{`{{`}} $labels.namespace {{`}}`}} is using {{`{{`}} $value | humanizePercentage {{`}}`}} of its {{`{{`}} $labels.resource {{`}}`}} quota.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubequotafullyused\n        summary: Namespace quota is fully used.\n      expr: |-\n        kube_resourcequota{job=\"kube-state-metrics\", type=\"used\"}\n          / ignoring(instance, job, type)\n        (kube_resourcequota{job=\"kube-state-metrics\", type=\"hard\"} > 0)\n          == 1\n      for: 15m\n      labels:\n        severity: info\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeQuotaExceeded\n      annotations:\n        description: Namespace {{`{{`}} $labels.namespace {{`}}`}} is using {{`{{`}} $value | humanizePercentage {{`}}`}} of its {{`{{`}} $labels.resource {{`}}`}} quota.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubequotaexceeded\n        summary: Namespace quota has exceeded the limits.\n      expr: |-\n        kube_resourcequota{job=\"kube-state-metrics\", type=\"used\"}\n          / ignoring(instance, job, type)\n        (kube_resourcequota{job=\"kube-state-metrics\", type=\"hard\"} > 0)\n          > 1\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: CPUThrottlingHigh\n      annotations:\n        description: '{{`{{`}} $value | humanizePercentage {{`}}`}} throttling of CPU in namespace {{`{{`}} $labels.namespace {{`}}`}} for container {{`{{`}} $labels.container {{`}}`}} in pod {{`{{`}} $labels.pod {{`}}`}}.'\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-cputhrottlinghigh\n        summary: Processes experience elevated CPU throttling.\n      expr: |-\n        sum(increase(container_cpu_cfs_throttled_periods_total{container!=\"\", }[5m])) by (container, pod, namespace)\n          /\n        sum(increase(container_cpu_cfs_periods_total{}[5m])) by (container, pod, namespace)\n          > ( 25 / 100 )\n      for: 15m\n      labels:\n        severity: info\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-storage.yaml",
    "content": "{{- /*\nGenerated from 'kubernetes-storage' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetes-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesStorage }}\n{{- $targetNamespace := .Values.defaultRules.appNamespacesTarget }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"kubernetes-storage\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: kubernetes-storage\n    rules:\n    - alert: KubePersistentVolumeFillingUp\n      annotations:\n        description: The PersistentVolume claimed by {{`{{`}} $labels.persistentvolumeclaim {{`}}`}} in Namespace {{`{{`}} $labels.namespace {{`}}`}} is only {{`{{`}} $value | humanizePercentage {{`}}`}} free.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubepersistentvolumefillingup\n        summary: PersistentVolume is filling up.\n      expr: |-\n        (\n          kubelet_volume_stats_available_bytes{job=\"kubelet\", namespace=~\"{{ $targetNamespace }}\", metrics_path=\"/metrics\"}\n            /\n          kubelet_volume_stats_capacity_bytes{job=\"kubelet\", namespace=~\"{{ $targetNamespace }}\", metrics_path=\"/metrics\"}\n        ) < 0.03\n        and\n        kubelet_volume_stats_used_bytes{job=\"kubelet\", namespace=~\"{{ $targetNamespace }}\", metrics_path=\"/metrics\"} > 0\n      for: 1m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubePersistentVolumeFillingUp\n      annotations:\n        description: Based on recent sampling, the PersistentVolume claimed by {{`{{`}} $labels.persistentvolumeclaim {{`}}`}} in Namespace {{`{{`}} $labels.namespace {{`}}`}} is expected to fill up within four days. Currently {{`{{`}} $value | humanizePercentage {{`}}`}} is available.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubepersistentvolumefillingup\n        summary: PersistentVolume is filling up.\n      expr: |-\n        (\n          kubelet_volume_stats_available_bytes{job=\"kubelet\", namespace=~\"{{ $targetNamespace }}\", metrics_path=\"/metrics\"}\n            /\n          kubelet_volume_stats_capacity_bytes{job=\"kubelet\", namespace=~\"{{ $targetNamespace }}\", metrics_path=\"/metrics\"}\n        ) < 0.15\n        and\n        kubelet_volume_stats_used_bytes{job=\"kubelet\", namespace=~\"{{ $targetNamespace }}\", metrics_path=\"/metrics\"} > 0\n        and\n        predict_linear(kubelet_volume_stats_available_bytes{job=\"kubelet\", namespace=~\"{{ $targetNamespace }}\", metrics_path=\"/metrics\"}[6h], 4 * 24 * 3600) < 0\n      for: 1h\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubePersistentVolumeErrors\n      annotations:\n        description: The persistent volume {{`{{`}} $labels.persistentvolume {{`}}`}} has status {{`{{`}} $labels.phase {{`}}`}}.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubepersistentvolumeerrors\n        summary: PersistentVolume is having issues with provisioning.\n      expr: kube_persistentvolume_status_phase{phase=~\"Failed|Pending\",job=\"kube-state-metrics\"} > 0\n      for: 5m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-system-apiserver.yaml",
    "content": "{{- /*\nGenerated from 'kubernetes-system-apiserver' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetes-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesSystem }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"kubernetes-system-apiserver\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: kubernetes-system-apiserver\n    rules:\n    - alert: KubeClientCertificateExpiration\n      annotations:\n        description: A client certificate used to authenticate to the apiserver is expiring in less than 7.0 days.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeclientcertificateexpiration\n        summary: Client certificate is about to expire.\n      expr: apiserver_client_certificate_expiration_seconds_count{job=\"apiserver\"} > 0 and on(job) histogram_quantile(0.01, sum by (job, le) (rate(apiserver_client_certificate_expiration_seconds_bucket{job=\"apiserver\"}[5m]))) < 604800\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeClientCertificateExpiration\n      annotations:\n        description: A client certificate used to authenticate to the apiserver is expiring in less than 24.0 hours.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeclientcertificateexpiration\n        summary: Client certificate is about to expire.\n      expr: apiserver_client_certificate_expiration_seconds_count{job=\"apiserver\"} > 0 and on(job) histogram_quantile(0.01, sum by (job, le) (rate(apiserver_client_certificate_expiration_seconds_bucket{job=\"apiserver\"}[5m]))) < 86400\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: AggregatedAPIErrors\n      annotations:\n        description: An aggregated API {{`{{`}} $labels.name {{`}}`}}/{{`{{`}} $labels.namespace {{`}}`}} has reported errors. It has appeared unavailable {{`{{`}} $value | humanize {{`}}`}} times averaged over the past 10m.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-aggregatedapierrors\n        summary: An aggregated API has reported errors.\n      expr: sum by(name, namespace)(increase(aggregator_unavailable_apiservice_total[10m])) > 4\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- if semverCompare \">=1.18.0-0\" $kubeTargetVersion }}\n    - alert: AggregatedAPIDown\n      annotations:\n        description: An aggregated API {{`{{`}} $labels.name {{`}}`}}/{{`{{`}} $labels.namespace {{`}}`}} has been only {{`{{`}} $value | humanize {{`}}`}}% available over the last 10m.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-aggregatedapidown\n        summary: An aggregated API is down.\n      expr: (1 - max by(name, namespace)(avg_over_time(aggregator_unavailable_apiservice[10m]))) * 100 < 85\n      for: 5m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- end }}\n{{- if .Values.kubeApiServer.enabled }}\n    - alert: KubeAPIDown\n      annotations:\n        description: KubeAPI has disappeared from Prometheus target discovery.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeapidown\n        summary: Target disappeared from Prometheus target discovery.\n      expr: absent(up{job=\"apiserver\"} == 1)\n      for: 15m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- end }}\n    - alert: KubeAPITerminatedRequests\n      annotations:\n        description: The apiserver has terminated {{`{{`}} $value | humanizePercentage {{`}}`}} of its incoming requests.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeapiterminatedrequests\n        summary: The apiserver has terminated {{`{{`}} $value | humanizePercentage {{`}}`}} of its incoming requests.\n      expr: sum(rate(apiserver_request_terminations_total{job=\"apiserver\"}[10m]))  / (  sum(rate(apiserver_request_total{job=\"apiserver\"}[10m])) + sum(rate(apiserver_request_terminations_total{job=\"apiserver\"}[10m])) ) > 0.20\n      for: 5m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-system-controller-manager.yaml",
    "content": "{{- /*\nGenerated from 'kubernetes-system-controller-manager' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetes-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.kubeControllerManager.enabled }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"kubernetes-system-controller-manager\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: kubernetes-system-controller-manager\n    rules:\n{{- if .Values.kubeControllerManager.enabled }}\n    - alert: KubeControllerManagerDown\n      annotations:\n        description: KubeControllerManager has disappeared from Prometheus target discovery.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubecontrollermanagerdown\n        summary: Target disappeared from Prometheus target discovery.\n      expr: absent(up{job=\"kube-controller-manager\"} == 1)\n      for: 15m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- end }}\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-system-kubelet.yaml",
    "content": "{{- /*\nGenerated from 'kubernetes-system-kubelet' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetes-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesSystem }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"kubernetes-system-kubelet\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: kubernetes-system-kubelet\n    rules:\n    - alert: KubeNodeNotReady\n      annotations:\n        description: '{{`{{`}} $labels.node {{`}}`}} has been unready for more than 15 minutes.'\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubenodenotready\n        summary: Node is not ready.\n      expr: kube_node_status_condition{job=\"kube-state-metrics\",condition=\"Ready\",status=\"true\"} == 0\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeNodeUnreachable\n      annotations:\n        description: '{{`{{`}} $labels.node {{`}}`}} is unreachable and some workloads may be rescheduled.'\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubenodeunreachable\n        summary: Node is unreachable.\n      expr: (kube_node_spec_taint{job=\"kube-state-metrics\",key=\"node.kubernetes.io/unreachable\",effect=\"NoSchedule\"} unless ignoring(key,value) kube_node_spec_taint{job=\"kube-state-metrics\",key=~\"ToBeDeletedByClusterAutoscaler|cloud.google.com/impending-node-termination|aws-node-termination-handler/spot-itn\"}) == 1\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeletTooManyPods\n      annotations:\n        description: Kubelet '{{`{{`}} $labels.node {{`}}`}}' is running at {{`{{`}} $value | humanizePercentage {{`}}`}} of its Pod capacity.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubelettoomanypods\n        summary: Kubelet is running at capacity.\n      expr: |-\n        count by(node) (\n          (kube_pod_status_phase{job=\"kube-state-metrics\",phase=\"Running\"} == 1) * on(instance,pod,namespace,cluster) group_left(node) topk by(instance,pod,namespace,cluster) (1, kube_pod_info{job=\"kube-state-metrics\"})\n        )\n        /\n        max by(node) (\n          kube_node_status_capacity{job=\"kube-state-metrics\",resource=\"pods\"} != 1\n        ) > 0.95\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeNodeReadinessFlapping\n      annotations:\n        description: The readiness status of node {{`{{`}} $labels.node {{`}}`}} has changed {{`{{`}} $value {{`}}`}} times in the last 15 minutes.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubenodereadinessflapping\n        summary: Node readiness status is flapping.\n      expr: sum(changes(kube_node_status_condition{status=\"true\",condition=\"Ready\"}[15m])) by (node) > 2\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeletPlegDurationHigh\n      annotations:\n        description: The Kubelet Pod Lifecycle Event Generator has a 99th percentile duration of {{`{{`}} $value {{`}}`}} seconds on node {{`{{`}} $labels.node {{`}}`}}.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeletplegdurationhigh\n        summary: Kubelet Pod Lifecycle Event Generator is taking too long to relist.\n      expr: node_quantile:kubelet_pleg_relist_duration_seconds:histogram_quantile{quantile=\"0.99\"} >= 10\n      for: 5m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeletPodStartUpLatencyHigh\n      annotations:\n        description: Kubelet Pod startup 99th percentile latency is {{`{{`}} $value {{`}}`}} seconds on node {{`{{`}} $labels.node {{`}}`}}.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeletpodstartuplatencyhigh\n        summary: Kubelet Pod startup latency is too high.\n      expr: histogram_quantile(0.99, sum(rate(kubelet_pod_worker_duration_seconds_bucket{job=\"kubelet\", metrics_path=\"/metrics\"}[5m])) by (instance, le)) * on(instance) group_left(node) kubelet_node_name{job=\"kubelet\", metrics_path=\"/metrics\"} > 60\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeletClientCertificateExpiration\n      annotations:\n        description: Client certificate for Kubelet on node {{`{{`}} $labels.node {{`}}`}} expires in {{`{{`}} $value | humanizeDuration {{`}}`}}.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeletclientcertificateexpiration\n        summary: Kubelet client certificate is about to expire.\n      expr: kubelet_certificate_manager_client_ttl_seconds < 604800\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeletClientCertificateExpiration\n      annotations:\n        description: Client certificate for Kubelet on node {{`{{`}} $labels.node {{`}}`}} expires in {{`{{`}} $value | humanizeDuration {{`}}`}}.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeletclientcertificateexpiration\n        summary: Kubelet client certificate is about to expire.\n      expr: kubelet_certificate_manager_client_ttl_seconds < 86400\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeletServerCertificateExpiration\n      annotations:\n        description: Server certificate for Kubelet on node {{`{{`}} $labels.node {{`}}`}} expires in {{`{{`}} $value | humanizeDuration {{`}}`}}.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeletservercertificateexpiration\n        summary: Kubelet server certificate is about to expire.\n      expr: kubelet_certificate_manager_server_ttl_seconds < 604800\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeletServerCertificateExpiration\n      annotations:\n        description: Server certificate for Kubelet on node {{`{{`}} $labels.node {{`}}`}} expires in {{`{{`}} $value | humanizeDuration {{`}}`}}.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeletservercertificateexpiration\n        summary: Kubelet server certificate is about to expire.\n      expr: kubelet_certificate_manager_server_ttl_seconds < 86400\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeletClientCertificateRenewalErrors\n      annotations:\n        description: Kubelet on node {{`{{`}} $labels.node {{`}}`}} has failed to renew its client certificate ({{`{{`}} $value | humanize {{`}}`}} errors in the last 5 minutes).\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeletclientcertificaterenewalerrors\n        summary: Kubelet has failed to renew its client certificate.\n      expr: increase(kubelet_certificate_manager_client_expiration_renew_errors[5m]) > 0\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeletServerCertificateRenewalErrors\n      annotations:\n        description: Kubelet on node {{`{{`}} $labels.node {{`}}`}} has failed to renew its server certificate ({{`{{`}} $value | humanize {{`}}`}} errors in the last 5 minutes).\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeletservercertificaterenewalerrors\n        summary: Kubelet has failed to renew its server certificate.\n      expr: increase(kubelet_server_expiration_renew_errors[5m]) > 0\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- if .Values.prometheusOperator.kubeletService.enabled }}\n    - alert: KubeletDown\n      annotations:\n        description: Kubelet has disappeared from Prometheus target discovery.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeletdown\n        summary: Target disappeared from Prometheus target discovery.\n      expr: absent(up{job=\"kubelet\", metrics_path=\"/metrics\"} == 1)\n      for: 15m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- end }}\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-system-scheduler.yaml",
    "content": "{{- /*\nGenerated from 'kubernetes-system-scheduler' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetes-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.kubeScheduler.enabled .Values.defaultRules.rules.kubeScheduler }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"kubernetes-system-scheduler\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: kubernetes-system-scheduler\n    rules:\n{{- if .Values.kubeScheduler.enabled }}\n    - alert: KubeSchedulerDown\n      annotations:\n        description: KubeScheduler has disappeared from Prometheus target discovery.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeschedulerdown\n        summary: Target disappeared from Prometheus target discovery.\n      expr: absent(up{job=\"kube-scheduler\"} == 1)\n      for: 15m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- end }}\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-system.yaml",
    "content": "{{- /*\nGenerated from 'kubernetes-system' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetes-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesSystem }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"kubernetes-system\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: kubernetes-system\n    rules:\n    - alert: KubeVersionMismatch\n      annotations:\n        description: There are {{`{{`}} $value {{`}}`}} different semantic versions of Kubernetes components running.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeversionmismatch\n        summary: Different semantic versions of Kubernetes components running.\n      expr: count(count by (git_version) (label_replace(kubernetes_build_info{job!~\"kube-dns|coredns\"},\"git_version\",\"$1\",\"git_version\",\"(v[0-9]*.[0-9]*).*\"))) > 1\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: KubeClientErrors\n      annotations:\n        description: Kubernetes API server client '{{`{{`}} $labels.job {{`}}`}}/{{`{{`}} $labels.instance {{`}}`}}' is experiencing {{`{{`}} $value | humanizePercentage {{`}}`}} errors.'\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeclienterrors\n        summary: Kubernetes API server client is experiencing errors.\n      expr: |-\n        (sum(rate(rest_client_requests_total{code=~\"5..\"}[5m])) by (instance, job)\n          /\n        sum(rate(rest_client_requests_total[5m])) by (instance, job))\n        > 0.01\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/node-exporter.rules.yaml",
    "content": "{{- /*\nGenerated from 'node-exporter.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/node-exporter-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.node }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"node-exporter.rules\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: node-exporter.rules\n    rules:\n    - expr: |-\n        count without (cpu) (\n          count without (mode) (\n            node_cpu_seconds_total{job=\"node-exporter\"}\n          )\n        )\n      record: instance:node_num_cpu:sum\n    - expr: |-\n        1 - avg without (cpu, mode) (\n          rate(node_cpu_seconds_total{job=\"node-exporter\", mode=\"idle\"}[5m])\n        )\n      record: instance:node_cpu_utilisation:rate5m\n    - expr: |-\n        (\n          node_load1{job=\"node-exporter\"}\n        /\n          instance:node_num_cpu:sum{job=\"node-exporter\"}\n        )\n      record: instance:node_load1_per_cpu:ratio\n    - expr: |-\n        1 - (\n          node_memory_MemAvailable_bytes{job=\"node-exporter\"}\n        /\n          node_memory_MemTotal_bytes{job=\"node-exporter\"}\n        )\n      record: instance:node_memory_utilisation:ratio\n    - expr: rate(node_vmstat_pgmajfault{job=\"node-exporter\"}[5m])\n      record: instance:node_vmstat_pgmajfault:rate5m\n    - expr: rate(node_disk_io_time_seconds_total{job=\"node-exporter\", device=~\"mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+\"}[5m])\n      record: instance_device:node_disk_io_time_seconds:rate5m\n    - expr: rate(node_disk_io_time_weighted_seconds_total{job=\"node-exporter\", device=~\"mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+\"}[5m])\n      record: instance_device:node_disk_io_time_weighted_seconds:rate5m\n    - expr: |-\n        sum without (device) (\n          rate(node_network_receive_bytes_total{job=\"node-exporter\", device!=\"lo\"}[5m])\n        )\n      record: instance:node_network_receive_bytes_excluding_lo:rate5m\n    - expr: |-\n        sum without (device) (\n          rate(node_network_transmit_bytes_total{job=\"node-exporter\", device!=\"lo\"}[5m])\n        )\n      record: instance:node_network_transmit_bytes_excluding_lo:rate5m\n    - expr: |-\n        sum without (device) (\n          rate(node_network_receive_drop_total{job=\"node-exporter\", device!=\"lo\"}[5m])\n        )\n      record: instance:node_network_receive_drop_excluding_lo:rate5m\n    - expr: |-\n        sum without (device) (\n          rate(node_network_transmit_drop_total{job=\"node-exporter\", device!=\"lo\"}[5m])\n        )\n      record: instance:node_network_transmit_drop_excluding_lo:rate5m\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/node-exporter.yaml",
    "content": "{{- /*\nGenerated from 'node-exporter' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/node-exporter-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.node }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"node-exporter\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: node-exporter\n    rules:\n    - alert: NodeFilesystemSpaceFillingUp\n      annotations:\n        description: Filesystem on {{`{{`}} $labels.device {{`}}`}} at {{`{{`}} $labels.instance {{`}}`}} has only {{`{{`}} printf \"%.2f\" $value {{`}}`}}% available space left and is filling up.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodefilesystemspacefillingup\n        summary: Filesystem is predicted to run out of space within the next 24 hours.\n      expr: |-\n        (\n          node_filesystem_avail_bytes{job=\"node-exporter\",fstype!=\"\"} / node_filesystem_size_bytes{job=\"node-exporter\",fstype!=\"\"} * 100 < 40\n        and\n          predict_linear(node_filesystem_avail_bytes{job=\"node-exporter\",fstype!=\"\"}[6h], 24*60*60) < 0\n        and\n          node_filesystem_readonly{job=\"node-exporter\",fstype!=\"\"} == 0\n        )\n      for: 1h\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: NodeFilesystemSpaceFillingUp\n      annotations:\n        description: Filesystem on {{`{{`}} $labels.device {{`}}`}} at {{`{{`}} $labels.instance {{`}}`}} has only {{`{{`}} printf \"%.2f\" $value {{`}}`}}% available space left and is filling up fast.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodefilesystemspacefillingup\n        summary: Filesystem is predicted to run out of space within the next 4 hours.\n      expr: |-\n        (\n          node_filesystem_avail_bytes{job=\"node-exporter\",fstype!=\"\"} / node_filesystem_size_bytes{job=\"node-exporter\",fstype!=\"\"} * 100 < 15\n        and\n          predict_linear(node_filesystem_avail_bytes{job=\"node-exporter\",fstype!=\"\"}[6h], 4*60*60) < 0\n        and\n          node_filesystem_readonly{job=\"node-exporter\",fstype!=\"\"} == 0\n        )\n      for: 1h\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: NodeFilesystemAlmostOutOfSpace\n      annotations:\n        description: Filesystem on {{`{{`}} $labels.device {{`}}`}} at {{`{{`}} $labels.instance {{`}}`}} has only {{`{{`}} printf \"%.2f\" $value {{`}}`}}% available space left.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodefilesystemalmostoutofspace\n        summary: Filesystem has less than 5% space left.\n      expr: |-\n        (\n          node_filesystem_avail_bytes{job=\"node-exporter\",fstype!=\"\"} / node_filesystem_size_bytes{job=\"node-exporter\",fstype!=\"\"} * 100 < 5\n        and\n          node_filesystem_readonly{job=\"node-exporter\",fstype!=\"\"} == 0\n        )\n      for: 1h\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: NodeFilesystemAlmostOutOfSpace\n      annotations:\n        description: Filesystem on {{`{{`}} $labels.device {{`}}`}} at {{`{{`}} $labels.instance {{`}}`}} has only {{`{{`}} printf \"%.2f\" $value {{`}}`}}% available space left.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodefilesystemalmostoutofspace\n        summary: Filesystem has less than 3% space left.\n      expr: |-\n        (\n          node_filesystem_avail_bytes{job=\"node-exporter\",fstype!=\"\"} / node_filesystem_size_bytes{job=\"node-exporter\",fstype!=\"\"} * 100 < 3\n        and\n          node_filesystem_readonly{job=\"node-exporter\",fstype!=\"\"} == 0\n        )\n      for: 1h\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: NodeFilesystemFilesFillingUp\n      annotations:\n        description: Filesystem on {{`{{`}} $labels.device {{`}}`}} at {{`{{`}} $labels.instance {{`}}`}} has only {{`{{`}} printf \"%.2f\" $value {{`}}`}}% available inodes left and is filling up.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodefilesystemfilesfillingup\n        summary: Filesystem is predicted to run out of inodes within the next 24 hours.\n      expr: |-\n        (\n          node_filesystem_files_free{job=\"node-exporter\",fstype!=\"\"} / node_filesystem_files{job=\"node-exporter\",fstype!=\"\"} * 100 < 40\n        and\n          predict_linear(node_filesystem_files_free{job=\"node-exporter\",fstype!=\"\"}[6h], 24*60*60) < 0\n        and\n          node_filesystem_readonly{job=\"node-exporter\",fstype!=\"\"} == 0\n        )\n      for: 1h\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: NodeFilesystemFilesFillingUp\n      annotations:\n        description: Filesystem on {{`{{`}} $labels.device {{`}}`}} at {{`{{`}} $labels.instance {{`}}`}} has only {{`{{`}} printf \"%.2f\" $value {{`}}`}}% available inodes left and is filling up fast.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodefilesystemfilesfillingup\n        summary: Filesystem is predicted to run out of inodes within the next 4 hours.\n      expr: |-\n        (\n          node_filesystem_files_free{job=\"node-exporter\",fstype!=\"\"} / node_filesystem_files{job=\"node-exporter\",fstype!=\"\"} * 100 < 20\n        and\n          predict_linear(node_filesystem_files_free{job=\"node-exporter\",fstype!=\"\"}[6h], 4*60*60) < 0\n        and\n          node_filesystem_readonly{job=\"node-exporter\",fstype!=\"\"} == 0\n        )\n      for: 1h\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: NodeFilesystemAlmostOutOfFiles\n      annotations:\n        description: Filesystem on {{`{{`}} $labels.device {{`}}`}} at {{`{{`}} $labels.instance {{`}}`}} has only {{`{{`}} printf \"%.2f\" $value {{`}}`}}% available inodes left.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodefilesystemalmostoutoffiles\n        summary: Filesystem has less than 5% inodes left.\n      expr: |-\n        (\n          node_filesystem_files_free{job=\"node-exporter\",fstype!=\"\"} / node_filesystem_files{job=\"node-exporter\",fstype!=\"\"} * 100 < 5\n        and\n          node_filesystem_readonly{job=\"node-exporter\",fstype!=\"\"} == 0\n        )\n      for: 1h\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: NodeFilesystemAlmostOutOfFiles\n      annotations:\n        description: Filesystem on {{`{{`}} $labels.device {{`}}`}} at {{`{{`}} $labels.instance {{`}}`}} has only {{`{{`}} printf \"%.2f\" $value {{`}}`}}% available inodes left.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodefilesystemalmostoutoffiles\n        summary: Filesystem has less than 3% inodes left.\n      expr: |-\n        (\n          node_filesystem_files_free{job=\"node-exporter\",fstype!=\"\"} / node_filesystem_files{job=\"node-exporter\",fstype!=\"\"} * 100 < 3\n        and\n          node_filesystem_readonly{job=\"node-exporter\",fstype!=\"\"} == 0\n        )\n      for: 1h\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: NodeNetworkReceiveErrs\n      annotations:\n        description: '{{`{{`}} $labels.instance {{`}}`}} interface {{`{{`}} $labels.device {{`}}`}} has encountered {{`{{`}} printf \"%.0f\" $value {{`}}`}} receive errors in the last two minutes.'\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodenetworkreceiveerrs\n        summary: Network interface is reporting many receive errors.\n      expr: rate(node_network_receive_errs_total[2m]) / rate(node_network_receive_packets_total[2m]) > 0.01\n      for: 1h\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: NodeNetworkTransmitErrs\n      annotations:\n        description: '{{`{{`}} $labels.instance {{`}}`}} interface {{`{{`}} $labels.device {{`}}`}} has encountered {{`{{`}} printf \"%.0f\" $value {{`}}`}} transmit errors in the last two minutes.'\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodenetworktransmiterrs\n        summary: Network interface is reporting many transmit errors.\n      expr: rate(node_network_transmit_errs_total[2m]) / rate(node_network_transmit_packets_total[2m]) > 0.01\n      for: 1h\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: NodeHighNumberConntrackEntriesUsed\n      annotations:\n        description: '{{`{{`}} $value | humanizePercentage {{`}}`}} of conntrack entries are used.'\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodehighnumberconntrackentriesused\n        summary: Number of conntrack are getting close to the limit.\n      expr: (node_nf_conntrack_entries / node_nf_conntrack_entries_limit) > 0.75\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: NodeTextFileCollectorScrapeError\n      annotations:\n        description: Node Exporter text file collector failed to scrape.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodetextfilecollectorscrapeerror\n        summary: Node Exporter text file collector failed to scrape.\n      expr: node_textfile_scrape_error{job=\"node-exporter\"} == 1\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: NodeClockSkewDetected\n      annotations:\n        description: Clock on {{`{{`}} $labels.instance {{`}}`}} is out of sync by more than 300s. Ensure NTP is configured correctly on this host.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodeclockskewdetected\n        summary: Clock skew detected.\n      expr: |-\n        (\n          node_timex_offset_seconds > 0.05\n        and\n          deriv(node_timex_offset_seconds[5m]) >= 0\n        )\n        or\n        (\n          node_timex_offset_seconds < -0.05\n        and\n          deriv(node_timex_offset_seconds[5m]) <= 0\n        )\n      for: 10m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: NodeClockNotSynchronising\n      annotations:\n        description: Clock on {{`{{`}} $labels.instance {{`}}`}} is not synchronising. Ensure NTP is configured on this host.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodeclocknotsynchronising\n        summary: Clock not synchronising.\n      expr: |-\n        min_over_time(node_timex_sync_status[5m]) == 0\n        and\n        node_timex_maxerror_seconds >= 16\n      for: 10m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: NodeRAIDDegraded\n      annotations:\n        description: RAID array '{{`{{`}} $labels.device {{`}}`}}' on {{`{{`}} $labels.instance {{`}}`}} is in degraded state due to one or more disks failures. Number of spare drives is insufficient to fix issue automatically.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-noderaiddegraded\n        summary: RAID Array is degraded\n      expr: node_md_disks_required - ignoring (state) (node_md_disks{state=\"active\"}) > 0\n      for: 15m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: NodeRAIDDiskFailure\n      annotations:\n        description: At least one device in RAID array on {{`{{`}} $labels.instance {{`}}`}} failed. Array '{{`{{`}} $labels.device {{`}}`}}' needs attention and possibly a disk swap.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-noderaiddiskfailure\n        summary: Failed device in RAID array\n      expr: node_md_disks{state=\"failed\"} > 0\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: NodeFileDescriptorLimit\n      annotations:\n        description: File descriptors limit at {{`{{`}} $labels.instance {{`}}`}} is currently at {{`{{`}} printf \"%.2f\" $value {{`}}`}}%.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodefiledescriptorlimit\n        summary: Kernel is predicted to exhaust file descriptors limit soon.\n      expr: |-\n        (\n          node_filefd_allocated{job=\"node-exporter\"} * 100 / node_filefd_maximum{job=\"node-exporter\"} > 70\n        )\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: NodeFileDescriptorLimit\n      annotations:\n        description: File descriptors limit at {{`{{`}} $labels.instance {{`}}`}} is currently at {{`{{`}} printf \"%.2f\" $value {{`}}`}}%.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodefiledescriptorlimit\n        summary: Kernel is predicted to exhaust file descriptors limit soon.\n      expr: |-\n        (\n          node_filefd_allocated{job=\"node-exporter\"} * 100 / node_filefd_maximum{job=\"node-exporter\"} > 90\n        )\n      for: 15m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/node-network.yaml",
    "content": "{{- /*\nGenerated from 'node-network' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kube-prometheus-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.network }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"node-network\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: node-network\n    rules:\n    - alert: NodeNetworkInterfaceFlapping\n      annotations:\n        description: Network interface \"{{`{{`}} $labels.device {{`}}`}}\" changing it's up status often on node-exporter {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}}\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodenetworkinterfaceflapping\n        summary: Network interface is often changin it's status\n      expr: changes(node_network_up{job=\"node-exporter\",device!~\"veth.+\"}[2m]) > 2\n      for: 2m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/node.rules.yaml",
    "content": "{{- /*\nGenerated from 'node.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetes-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.node }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"node.rules\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: node.rules\n    rules:\n    - expr: |-\n        topk by(namespace, pod) (1,\n          max by (node, namespace, pod) (\n            label_replace(kube_pod_info{job=\"kube-state-metrics\",node!=\"\"}, \"pod\", \"$1\", \"pod\", \"(.*)\")\n        ))\n      record: 'node_namespace_pod:kube_pod_info:'\n    - expr: |-\n        count by (cluster, node) (sum by (node, cpu) (\n          node_cpu_seconds_total{job=\"node-exporter\"}\n        * on (namespace, pod) group_left(node)\n          topk by(namespace, pod) (1, node_namespace_pod:kube_pod_info:)\n        ))\n      record: node:node_num_cpu:sum\n    - expr: |-\n        sum(\n          node_memory_MemAvailable_bytes{job=\"node-exporter\"} or\n          (\n            node_memory_Buffers_bytes{job=\"node-exporter\"} +\n            node_memory_Cached_bytes{job=\"node-exporter\"} +\n            node_memory_MemFree_bytes{job=\"node-exporter\"} +\n            node_memory_Slab_bytes{job=\"node-exporter\"}\n          )\n        ) by (cluster)\n      record: :node_memory_MemAvailable_bytes:sum\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/prometheus-operator.yaml",
    "content": "{{- /*\nGenerated from 'prometheus-operator' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/prometheus-operator-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.prometheusOperator }}\n{{- $operatorJob := printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"operator\" }}\n{{- $namespace := printf \"%s\" (include \"kube-prometheus-stack.namespace\" .) }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"prometheus-operator\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: prometheus-operator\n    rules:\n    - alert: PrometheusOperatorListErrors\n      annotations:\n        description: Errors while performing List operations in controller {{`{{`}}$labels.controller{{`}}`}} in {{`{{`}}$labels.namespace{{`}}`}} namespace.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusoperatorlisterrors\n        summary: Errors while performing list operations in controller.\n      expr: (sum by (controller,namespace) (rate(prometheus_operator_list_operations_failed_total{job=\"{{ $operatorJob }}\",namespace=\"{{ $namespace }}\"}[10m])) / sum by (controller,namespace) (rate(prometheus_operator_list_operations_total{job=\"{{ $operatorJob }}\",namespace=\"{{ $namespace }}\"}[10m]))) > 0.4\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusOperatorWatchErrors\n      annotations:\n        description: Errors while performing watch operations in controller {{`{{`}}$labels.controller{{`}}`}} in {{`{{`}}$labels.namespace{{`}}`}} namespace.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusoperatorwatcherrors\n        summary: Errors while performing watch operations in controller.\n      expr: (sum by (controller,namespace) (rate(prometheus_operator_watch_operations_failed_total{job=\"{{ $operatorJob }}\",namespace=\"{{ $namespace }}\"}[10m])) / sum by (controller,namespace) (rate(prometheus_operator_watch_operations_total{job=\"{{ $operatorJob }}\",namespace=\"{{ $namespace }}\"}[10m]))) > 0.4\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusOperatorSyncFailed\n      annotations:\n        description: Controller {{`{{`}} $labels.controller {{`}}`}} in {{`{{`}} $labels.namespace {{`}}`}} namespace fails to reconcile {{`{{`}} $value {{`}}`}} objects.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusoperatorsyncfailed\n        summary: Last controller reconciliation failed\n      expr: min_over_time(prometheus_operator_syncs{status=\"failed\",job=\"{{ $operatorJob }}\",namespace=\"{{ $namespace }}\"}[5m]) > 0\n      for: 10m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusOperatorReconcileErrors\n      annotations:\n        description: '{{`{{`}} $value | humanizePercentage {{`}}`}} of reconciling operations failed for {{`{{`}} $labels.controller {{`}}`}} controller in {{`{{`}} $labels.namespace {{`}}`}} namespace.'\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusoperatorreconcileerrors\n        summary: Errors while reconciling controller.\n      expr: (sum by (controller,namespace) (rate(prometheus_operator_reconcile_errors_total{job=\"{{ $operatorJob }}\",namespace=\"{{ $namespace }}\"}[5m]))) / (sum by (controller,namespace) (rate(prometheus_operator_reconcile_operations_total{job=\"{{ $operatorJob }}\",namespace=\"{{ $namespace }}\"}[5m]))) > 0.1\n      for: 10m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusOperatorNodeLookupErrors\n      annotations:\n        description: Errors while reconciling Prometheus in {{`{{`}} $labels.namespace {{`}}`}} Namespace.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusoperatornodelookuperrors\n        summary: Errors while reconciling Prometheus.\n      expr: rate(prometheus_operator_node_address_lookup_errors_total{job=\"{{ $operatorJob }}\",namespace=\"{{ $namespace }}\"}[5m]) > 0.1\n      for: 10m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusOperatorNotReady\n      annotations:\n        description: Prometheus operator in {{`{{`}} $labels.namespace {{`}}`}} namespace isn't ready to reconcile {{`{{`}} $labels.controller {{`}}`}} resources.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusoperatornotready\n        summary: Prometheus operator not ready\n      expr: min by(namespace, controller) (max_over_time(prometheus_operator_ready{job=\"{{ $operatorJob }}\",namespace=\"{{ $namespace }}\"}[5m]) == 0)\n      for: 5m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusOperatorRejectedResources\n      annotations:\n        description: Prometheus operator in {{`{{`}} $labels.namespace {{`}}`}} namespace rejected {{`{{`}} printf \"%0.0f\" $value {{`}}`}} {{`{{`}} $labels.controller {{`}}`}}/{{`{{`}} $labels.resource {{`}}`}} resources.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusoperatorrejectedresources\n        summary: Resources rejected by Prometheus operator\n      expr: min_over_time(prometheus_operator_managed_resources{state=\"rejected\",job=\"{{ $operatorJob }}\",namespace=\"{{ $namespace }}\"}[5m]) > 0\n      for: 5m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/rules-1.14/prometheus.yaml",
    "content": "{{- /*\nGenerated from 'prometheus' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/prometheus-prometheusRule.yaml\nDo not change in-place! In order to change this file first read following link:\nhttps://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack\n*/ -}}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if and (semverCompare \">=1.14.0-0\" $kubeTargetVersion) (semverCompare \"<9.9.9-9\" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.prometheus }}\n{{- $prometheusJob := printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"prometheus\" }}\n{{- $namespace := printf \"%s\" (include \"kube-prometheus-stack.namespace\" .) }}\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n  name: {{ printf \"%s-%s\" (include \"kube-prometheus-stack.fullname\" .) \"prometheus\" | trunc 63 | trimSuffix \"-\" }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.defaultRules.labels }}\n{{ toYaml .Values.defaultRules.labels | indent 4 }}\n{{- end }}\n{{- if .Values.defaultRules.annotations }}\n  annotations:\n{{ toYaml .Values.defaultRules.annotations | indent 4 }}\n{{- end }}\nspec:\n  groups:\n  - name: prometheus\n    rules:\n    - alert: PrometheusBadConfig\n      annotations:\n        description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has failed to reload its configuration.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusbadconfig\n        summary: Failed Prometheus configuration reload.\n      expr: |-\n        # Without max_over_time, failed scrapes could create false negatives, see\n        # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details.\n        max_over_time(prometheus_config_last_reload_successful{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m]) == 0\n      for: 10m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusNotificationQueueRunningFull\n      annotations:\n        description: Alert notification queue of Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is running full.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusnotificationqueuerunningfull\n        summary: Prometheus alert notification queue predicted to run full in less than 30m.\n      expr: |-\n        # Without min_over_time, failed scrapes could create false negatives, see\n        # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details.\n        (\n          predict_linear(prometheus_notifications_queue_length{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m], 60 * 30)\n        >\n          min_over_time(prometheus_notifications_queue_capacity{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m])\n        )\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusErrorSendingAlertsToSomeAlertmanagers\n      annotations:\n        description: '{{`{{`}} printf \"%.1f\" $value {{`}}`}}% errors while sending alerts from Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} to Alertmanager {{`{{`}}$labels.alertmanager{{`}}`}}.'\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheuserrorsendingalertstosomealertmanagers\n        summary: Prometheus has encountered more than 1% errors sending alerts to a specific Alertmanager.\n      expr: |-\n        (\n          rate(prometheus_notifications_errors_total{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m])\n        /\n          rate(prometheus_notifications_sent_total{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m])\n        )\n        * 100\n        > 1\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusNotConnectedToAlertmanagers\n      annotations:\n        description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is not connected to any Alertmanagers.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusnotconnectedtoalertmanagers\n        summary: Prometheus is not connected to any Alertmanagers.\n      expr: |-\n        # Without max_over_time, failed scrapes could create false negatives, see\n        # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details.\n        max_over_time(prometheus_notifications_alertmanagers_discovered{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m]) < 1\n      for: 10m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusTSDBReloadsFailing\n      annotations:\n        description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has detected {{`{{`}}$value | humanize{{`}}`}} reload failures over the last 3h.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheustsdbreloadsfailing\n        summary: Prometheus has issues reloading blocks from disk.\n      expr: increase(prometheus_tsdb_reloads_failures_total{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[3h]) > 0\n      for: 4h\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusTSDBCompactionsFailing\n      annotations:\n        description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has detected {{`{{`}}$value | humanize{{`}}`}} compaction failures over the last 3h.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheustsdbcompactionsfailing\n        summary: Prometheus has issues compacting blocks.\n      expr: increase(prometheus_tsdb_compactions_failed_total{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[3h]) > 0\n      for: 4h\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusNotIngestingSamples\n      annotations:\n        description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is not ingesting samples.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusnotingestingsamples\n        summary: Prometheus is not ingesting samples.\n      expr: |-\n        (\n          rate(prometheus_tsdb_head_samples_appended_total{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m]) <= 0\n        and\n          (\n            sum without(scrape_job) (prometheus_target_metadata_cache_entries{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}) > 0\n          or\n            sum without(rule_group) (prometheus_rule_group_rules{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}) > 0\n          )\n        )\n      for: 10m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusDuplicateTimestamps\n      annotations:\n        description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is dropping {{`{{`}} printf \"%.4g\" $value  {{`}}`}} samples/s with different values but duplicated timestamp.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusduplicatetimestamps\n        summary: Prometheus is dropping samples with duplicate timestamps.\n      expr: rate(prometheus_target_scrapes_sample_duplicate_timestamp_total{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m]) > 0\n      for: 10m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusOutOfOrderTimestamps\n      annotations:\n        description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is dropping {{`{{`}} printf \"%.4g\" $value  {{`}}`}} samples/s with timestamps arriving out of order.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusoutofordertimestamps\n        summary: Prometheus drops samples with out-of-order timestamps.\n      expr: rate(prometheus_target_scrapes_sample_out_of_order_total{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m]) > 0\n      for: 10m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusRemoteStorageFailures\n      annotations:\n        description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} failed to send {{`{{`}} printf \"%.1f\" $value {{`}}`}}% of the samples to {{`{{`}} $labels.remote_name{{`}}`}}:{{`{{`}} $labels.url {{`}}`}}\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusremotestoragefailures\n        summary: Prometheus fails to send samples to remote storage.\n      expr: |-\n        (\n          (rate(prometheus_remote_storage_failed_samples_total{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m]) or rate(prometheus_remote_storage_samples_failed_total{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m]))\n        /\n          (\n            (rate(prometheus_remote_storage_failed_samples_total{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m]) or rate(prometheus_remote_storage_samples_failed_total{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m]))\n          +\n            (rate(prometheus_remote_storage_succeeded_samples_total{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m]) or rate(prometheus_remote_storage_samples_total{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m]))\n          )\n        )\n        * 100\n        > 1\n      for: 15m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusRemoteWriteBehind\n      annotations:\n        description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} remote write is {{`{{`}} printf \"%.1f\" $value {{`}}`}}s behind for {{`{{`}} $labels.remote_name{{`}}`}}:{{`{{`}} $labels.url {{`}}`}}.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusremotewritebehind\n        summary: Prometheus remote write is behind.\n      expr: |-\n        # Without max_over_time, failed scrapes could create false negatives, see\n        # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details.\n        (\n          max_over_time(prometheus_remote_storage_highest_timestamp_in_seconds{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m])\n        - ignoring(remote_name, url) group_right\n          max_over_time(prometheus_remote_storage_queue_highest_sent_timestamp_seconds{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m])\n        )\n        > 120\n      for: 15m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusRemoteWriteDesiredShards\n      annotations:\n        description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} remote write desired shards calculation wants to run {{`{{`}} $value {{`}}`}} shards for queue {{`{{`}} $labels.remote_name{{`}}`}}:{{`{{`}} $labels.url {{`}}`}}, which is more than the max of {{`{{`}} printf `prometheus_remote_storage_shards_max{instance=\"%s\",job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}` $labels.instance | query | first | value {{`}}`}}.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusremotewritedesiredshards\n        summary: Prometheus remote write desired shards calculation wants to run more than configured max shards.\n      expr: |-\n        # Without max_over_time, failed scrapes could create false negatives, see\n        # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details.\n        (\n          max_over_time(prometheus_remote_storage_shards_desired{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m])\n        >\n          max_over_time(prometheus_remote_storage_shards_max{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m])\n        )\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusRuleFailures\n      annotations:\n        description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has failed to evaluate {{`{{`}} printf \"%.0f\" $value {{`}}`}} rules in the last 5m.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusrulefailures\n        summary: Prometheus is failing rule evaluations.\n      expr: increase(prometheus_rule_evaluation_failures_total{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m]) > 0\n      for: 15m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusMissingRuleEvaluations\n      annotations:\n        description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has missed {{`{{`}} printf \"%.0f\" $value {{`}}`}} rule group evaluations in the last 5m.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusmissingruleevaluations\n        summary: Prometheus is missing rule evaluations due to slow rule group evaluation.\n      expr: increase(prometheus_rule_group_iterations_missed_total{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m]) > 0\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusTargetLimitHit\n      annotations:\n        description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has dropped {{`{{`}} printf \"%.0f\" $value {{`}}`}} targets because the number of targets exceeded the configured target_limit.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheustargetlimithit\n        summary: Prometheus has dropped targets because some scrape configs have exceeded the targets limit.\n      expr: increase(prometheus_target_scrape_pool_exceeded_target_limit_total{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m]) > 0\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusLabelLimitHit\n      annotations:\n        description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has dropped {{`{{`}} printf \"%.0f\" $value {{`}}`}} targets because some samples exceeded the configured label_limit, label_name_length_limit or label_value_length_limit.\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheuslabellimithit\n        summary: Prometheus has dropped targets because some scrape configs have exceeded the labels limit.\n      expr: increase(prometheus_target_scrape_pool_exceeded_label_limits_total{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[5m]) > 0\n      for: 15m\n      labels:\n        severity: warning\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusTargetSyncFailure\n      annotations:\n        description: '{{`{{`}} printf \"%.0f\" $value {{`}}`}} targets in Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} have failed to sync because invalid configuration was supplied.'\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheustargetsyncfailure\n        summary: Prometheus has failed to sync targets.\n      expr: increase(prometheus_target_sync_failed_total{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\"}[30m]) > 0\n      for: 5m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n    - alert: PrometheusErrorSendingAlertsToAnyAlertmanager\n      annotations:\n        description: '{{`{{`}} printf \"%.1f\" $value {{`}}`}}% minimum errors while sending alerts from Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} to any Alertmanager.'\n        runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheuserrorsendingalertstoanyalertmanager\n        summary: Prometheus encounters more than 3% errors sending alerts to any Alertmanager.\n      expr: |-\n        min without (alertmanager) (\n          rate(prometheus_notifications_errors_total{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\",alertmanager!~``}[5m])\n        /\n          rate(prometheus_notifications_sent_total{job=\"{{ $prometheusJob }}\",namespace=\"{{ $namespace }}\",alertmanager!~``}[5m])\n        )\n        * 100\n        > 3\n      for: 15m\n      labels:\n        severity: critical\n{{- if .Values.defaultRules.additionalRuleLabels }}\n{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }}\n{{- end }}\n{{- end }}"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/service.yaml",
    "content": "{{- if .Values.prometheus.enabled }}\napiVersion: v1\nkind: Service\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-prometheus\n    self-monitor: {{ .Values.prometheus.serviceMonitor.selfMonitor | quote }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.prometheus.service.labels }}\n{{ toYaml .Values.prometheus.service.labels | indent 4 }}\n{{- end }}\n{{- if .Values.prometheus.service.annotations }}\n  annotations:\n{{ toYaml .Values.prometheus.service.annotations | indent 4 }}\n{{- end }}\nspec:\n{{- if .Values.prometheus.service.clusterIP }}\n  clusterIP: {{ .Values.prometheus.service.clusterIP }}\n{{- end }}\n{{- if .Values.prometheus.service.externalIPs }}\n  externalIPs:\n{{ toYaml .Values.prometheus.service.externalIPs | indent 4 }}\n{{- end }}\n{{- if .Values.prometheus.service.loadBalancerIP }}\n  loadBalancerIP: {{ .Values.prometheus.service.loadBalancerIP }}\n{{- end }}\n{{- if .Values.prometheus.service.loadBalancerSourceRanges }}\n  loadBalancerSourceRanges:\n  {{- range $cidr := .Values.prometheus.service.loadBalancerSourceRanges }}\n    - {{ $cidr }}\n  {{- end }}\n{{- end }}\n  ports:\n  - name: {{ .Values.prometheus.prometheusSpec.portName }}\n    {{- if eq .Values.prometheus.service.type \"NodePort\" }}\n    nodePort: {{ .Values.prometheus.service.nodePort }}\n    {{- end }}\n    port: {{ .Values.prometheus.service.port }}\n    targetPort: {{ .Values.prometheus.service.targetPort }}\n  {{- if .Values.prometheus.thanosIngress.enabled }}\n  - name: grpc\n    {{- if eq .Values.prometheus.service.type \"NodePort\" }}\n    nodePort: {{ .Values.prometheus.thanosIngress.nodePort }}\n    {{- end }}\n    port: {{ .Values.prometheus.thanosIngress.servicePort }}\n    targetPort: {{ .Values.prometheus.thanosIngress.servicePort }}\n  {{- end }}\n{{- if .Values.prometheus.service.additionalPorts }}\n{{ toYaml .Values.prometheus.service.additionalPorts | indent 2 }}\n{{- end }}\n  selector:\n    app.kubernetes.io/name: prometheus\n    prometheus: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus\n{{- if .Values.prometheus.service.sessionAffinity }}\n  sessionAffinity: {{ .Values.prometheus.service.sessionAffinity }}\n{{- end }}\n  type: \"{{ .Values.prometheus.service.type }}\"\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/serviceThanosSidecar.yaml",
    "content": "{{- if and .Values.prometheus.enabled .Values.prometheus.thanosService.enabled }}\napiVersion: v1\nkind: Service\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-thanos-discovery\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-thanos-discovery\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.prometheus.thanosService.labels }}\n{{ toYaml .Values.prometheus.thanosService.labels | indent 4 }}\n{{- end }}\n{{- if .Values.prometheus.thanosService.annotations }}\n  annotations:\n{{ toYaml .Values.prometheus.thanosService.annotations | indent 4 }}\n{{- end }}\nspec:\n  type: {{ .Values.prometheus.thanosService.type }}\n  clusterIP: {{ .Values.prometheus.thanosService.clusterIP }}\n  ports:\n  - name: {{ .Values.prometheus.thanosService.portName }}\n    port: {{ .Values.prometheus.thanosService.port }}\n    targetPort: {{ .Values.prometheus.thanosService.targetPort }}\n    {{- if eq .Values.prometheus.thanosService.type \"NodePort\" }}\n    nodePort: {{ .Values.prometheus.thanosService.nodePort }}\n    {{- end }}\n  selector:\n    app.kubernetes.io/name: prometheus\n    prometheus: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/serviceThanosSidecarExternal.yaml",
    "content": "{{- if and .Values.prometheus.enabled .Values.prometheus.thanosServiceExternal.enabled }}\napiVersion: v1\nkind: Service\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-thanos-external\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.prometheus.thanosServiceExternal.labels }}\n{{ toYaml .Values.prometheus.thanosServiceExternal.labels | indent 4 }}\n{{- end }}\n{{- if .Values.prometheus.thanosServiceExternal.annotations }}\n  annotations:\n{{ toYaml .Values.prometheus.thanosServiceExternal.annotations | indent 4 }}\n{{- end }}\nspec:\n  type: {{ .Values.prometheus.thanosServiceExternal.type }}\n{{- if .Values.prometheus.thanosServiceExternal.loadBalancerIP }}\n  loadBalancerIP: {{ .Values.prometheus.thanosServiceExternal.loadBalancerIP }}\n{{- end }}\n{{- if .Values.prometheus.thanosServiceExternal.loadBalancerSourceRanges }}\n  loadBalancerSourceRanges:\n  {{- range $cidr := .Values.prometheus.thanosServiceExternal.loadBalancerSourceRanges }}\n    - {{ $cidr }}\n  {{- end }}\n{{- end }}\n  ports:\n  - name: {{ .Values.prometheus.thanosServiceExternal.portName }}\n    port: {{ .Values.prometheus.thanosServiceExternal.port }}\n    targetPort: {{ .Values.prometheus.thanosServiceExternal.targetPort }}\n    {{- if eq .Values.prometheus.thanosServiceExternal.type \"NodePort\" }}\n    nodePort: {{ .Values.prometheus.thanosServiceExternal.nodePort }}\n    {{- end }}\n  selector:\n    app.kubernetes.io/name: prometheus\n    prometheus: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/serviceaccount.yaml",
    "content": "{{- if and .Values.prometheus.enabled .Values.prometheus.serviceAccount.create }}\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: {{ template \"kube-prometheus-stack.prometheus.serviceAccountName\" . }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-prometheus\n    app.kubernetes.io/name: {{ template \"kube-prometheus-stack.name\" . }}-prometheus\n    app.kubernetes.io/component: prometheus\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.prometheus.serviceAccount.annotations }}\n  annotations:\n{{ toYaml .Values.prometheus.serviceAccount.annotations | indent 4 }}\n{{- end }}\n{{- if .Values.global.imagePullSecrets }}\nimagePullSecrets:\n{{ toYaml .Values.global.imagePullSecrets | indent 2 }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/servicemonitor.yaml",
    "content": "{{- if and .Values.prometheus.enabled .Values.prometheus.serviceMonitor.selfMonitor }}\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-prometheus\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-prometheus\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  selector:\n    matchLabels:\n      app: {{ template \"kube-prometheus-stack.name\" . }}-prometheus\n      release: {{ $.Release.Name | quote }}\n      self-monitor: \"true\"\n  namespaceSelector:\n    matchNames:\n      - {{ printf \"%s\" (include \"kube-prometheus-stack.namespace\" .) | quote }}\n  endpoints:\n  - port: {{ .Values.prometheus.prometheusSpec.portName }}\n    {{- if .Values.prometheus.serviceMonitor.interval }}\n    interval: {{ .Values.prometheus.serviceMonitor.interval }}\n    {{- end }}\n    {{- if .Values.prometheus.serviceMonitor.scheme }}\n    scheme: {{ .Values.prometheus.serviceMonitor.scheme }}\n    {{- end }}\n    {{- if .Values.prometheus.serviceMonitor.tlsConfig }}\n    tlsConfig: {{ toYaml .Values.prometheus.serviceMonitor.tlsConfig | nindent 6 }}\n    {{- end }}\n    {{- if .Values.prometheus.serviceMonitor.bearerTokenFile }}\n    bearerTokenFile: {{ .Values.prometheus.serviceMonitor.bearerTokenFile }}\n    {{- end }}\n    path: \"{{ trimSuffix \"/\" .Values.prometheus.prometheusSpec.routePrefix }}/metrics\"\n{{- if .Values.prometheus.serviceMonitor.metricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.prometheus.serviceMonitor.metricRelabelings | indent 6) . }}\n{{- end }}\n{{- if .Values.prometheus.serviceMonitor.relabelings }}\n    relabelings:\n{{ toYaml .Values.prometheus.serviceMonitor.relabelings | indent 6 }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/servicemonitors.yaml",
    "content": "{{- if and .Values.prometheus.enabled .Values.prometheus.additionalServiceMonitors }}\napiVersion: v1\nkind: List\nitems:\n{{- range .Values.prometheus.additionalServiceMonitors }}\n  - apiVersion: monitoring.coreos.com/v1\n    kind: ServiceMonitor\n    metadata:\n      name: {{ .name }}\n      namespace: {{ template \"kube-prometheus-stack.namespace\" $ }}\n      labels:\n        app: {{ template \"kube-prometheus-stack.name\" $ }}-prometheus\n{{ include \"kube-prometheus-stack.labels\" $ | indent 8 }}\n        {{- if .additionalLabels }}\n{{ toYaml .additionalLabels | indent 8 }}\n        {{- end }}\n    spec:\n      endpoints:\n{{ toYaml .endpoints | indent 8 }}\n    {{- if .jobLabel }}\n      jobLabel: {{ .jobLabel }}\n    {{- end }}\n    {{- if .namespaceSelector }}\n      namespaceSelector:\n{{ toYaml .namespaceSelector | indent 8 }}\n    {{- end }}\n      selector:\n{{ toYaml .selector | indent 8 }}\n    {{- if .targetLabels }}\n      targetLabels:\n{{ toYaml .targetLabels | indent 8 }}\n    {{- end }}\n    {{- if .podTargetLabels }}\n      podTargetLabels:\n{{ toYaml .podTargetLabels | indent 8 }}\n    {{- end }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus/serviceperreplica.yaml",
    "content": "{{- if and .Values.prometheus.enabled .Values.prometheus.servicePerReplica.enabled }}\n{{- $count := .Values.prometheus.prometheusSpec.replicas | int -}}\n{{- $serviceValues := .Values.prometheus.servicePerReplica -}} \napiVersion: v1\nkind: List\nmetadata:\n  name: {{ include \"kube-prometheus-stack.fullname\" $ }}-prometheus-serviceperreplica\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\nitems:\n{{- range $i, $e := until $count }}\n  - apiVersion: v1\n    kind: Service\n    metadata:\n      name: {{ include \"kube-prometheus-stack.fullname\" $ }}-prometheus-{{ $i }}\n      namespace: {{ template \"kube-prometheus-stack.namespace\" $ }}\n      labels:\n        app: {{ include \"kube-prometheus-stack.name\" $ }}-prometheus\n{{ include \"kube-prometheus-stack.labels\" $ | indent 8 }}\n      {{- if $serviceValues.annotations }}\n      annotations:\n{{ toYaml $serviceValues.annotations | indent 8 }}\n      {{- end }}\n    spec:\n      {{- if $serviceValues.clusterIP }}\n      clusterIP: {{ $serviceValues.clusterIP }}\n      {{- end }}\n      {{- if $serviceValues.loadBalancerSourceRanges }}\n      loadBalancerSourceRanges:\n      {{- range $cidr := $serviceValues.loadBalancerSourceRanges }}\n        - {{ $cidr }}\n      {{- end }}\n      {{- end }}\n      ports:\n        - name: {{ $.Values.prometheus.prometheusSpec.portName }}\n          {{- if eq $serviceValues.type \"NodePort\" }}\n          nodePort: {{ $serviceValues.nodePort }}\n          {{- end }}\n          port: {{ $serviceValues.port }}\n          targetPort: {{ $serviceValues.targetPort }}\n      selector:\n        app.kubernetes.io/name: prometheus\n        prometheus: {{ include \"kube-prometheus-stack.fullname\" $ }}-prometheus\n        statefulset.kubernetes.io/pod-name: prometheus-{{ include \"kube-prometheus-stack.fullname\" $ }}-prometheus-{{ $i }}\n      type: \"{{ $serviceValues.type }}\"\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/clusterrole.yaml",
    "content": "{{- if and .Values.prometheusOperator.enabled .Values.prometheusOperator.admissionWebhooks.enabled .Values.prometheusOperator.admissionWebhooks.patch.enabled .Values.global.rbac.create (not .Values.prometheusOperator.admissionWebhooks.certManager.enabled) }}\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name:  {{ template \"kube-prometheus-stack.fullname\" . }}-admission\n  annotations:\n    \"helm.sh/hook\": pre-install,pre-upgrade,post-install,post-upgrade\n    \"helm.sh/hook-delete-policy\": before-hook-creation,hook-succeeded\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-admission\n{{- include \"kube-prometheus-stack.labels\" $ | indent 4 }}\nrules:\n  - apiGroups:\n      - admissionregistration.k8s.io\n    resources:\n      - validatingwebhookconfigurations\n      - mutatingwebhookconfigurations\n    verbs:\n      - get\n      - update\n{{- if .Values.global.rbac.pspEnabled }}\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if semverCompare \"> 1.15.0-0\" $kubeTargetVersion }}\n  - apiGroups: ['policy']\n{{- else }}\n  - apiGroups: ['extensions']\n{{- end }}\n    resources: ['podsecuritypolicies']\n    verbs:     ['use']\n    resourceNames:\n    - {{ template \"kube-prometheus-stack.fullname\" . }}-admission\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/clusterrolebinding.yaml",
    "content": "{{- if and .Values.prometheusOperator.enabled .Values.prometheusOperator.admissionWebhooks.enabled .Values.prometheusOperator.admissionWebhooks.patch.enabled .Values.global.rbac.create (not .Values.prometheusOperator.admissionWebhooks.certManager.enabled) }}\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  name:  {{ template \"kube-prometheus-stack.fullname\" . }}-admission\n  annotations:\n    \"helm.sh/hook\": pre-install,pre-upgrade,post-install,post-upgrade\n    \"helm.sh/hook-delete-policy\": before-hook-creation,hook-succeeded\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-admission\n{{- include \"kube-prometheus-stack.labels\" $ | indent 4 }}\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-admission\nsubjects:\n  - kind: ServiceAccount\n    name: {{ template \"kube-prometheus-stack.fullname\" . }}-admission\n    namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/job-createSecret.yaml",
    "content": "{{- if and .Values.prometheusOperator.enabled .Values.prometheusOperator.admissionWebhooks.enabled .Values.prometheusOperator.admissionWebhooks.patch.enabled (not .Values.prometheusOperator.admissionWebhooks.certManager.enabled) }}\napiVersion: batch/v1\nkind: Job\nmetadata:\n  name:  {{ template \"kube-prometheus-stack.fullname\" . }}-admission-create\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  annotations:\n    \"helm.sh/hook\": pre-install,pre-upgrade\n    \"helm.sh/hook-delete-policy\": before-hook-creation,hook-succeeded\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-admission-create\n{{- include \"kube-prometheus-stack.labels\" $ | indent 4 }}\nspec:\n  {{- if .Capabilities.APIVersions.Has \"batch/v1alpha1\" }}\n  # Alpha feature since k8s 1.12\n  ttlSecondsAfterFinished: 0\n  {{- end }}\n  template:\n    metadata:\n      name:  {{ template \"kube-prometheus-stack.fullname\" . }}-admission-create\n{{- with .Values.prometheusOperator.admissionWebhooks.patch.podAnnotations }}\n      annotations:\n{{ toYaml .  | indent 8 }}\n{{- end }}\n      labels:\n        app: {{ template \"kube-prometheus-stack.name\" $ }}-admission-create\n{{- include \"kube-prometheus-stack.labels\" $ | indent 8 }}\n    spec:\n      {{- if .Values.prometheusOperator.admissionWebhooks.patch.priorityClassName }}\n      priorityClassName: {{ .Values.prometheusOperator.admissionWebhooks.patch.priorityClassName }}\n      {{- end }}\n      containers:\n        - name: create\n          {{- if .Values.prometheusOperator.admissionWebhooks.patch.image.sha }}\n          image: {{ .Values.prometheusOperator.admissionWebhooks.patch.image.repository }}:{{ .Values.prometheusOperator.admissionWebhooks.patch.image.tag }}@sha256:{{ .Values.prometheusOperator.admissionWebhooks.patch.image.sha }}\n          {{- else }}\n          image: {{ .Values.prometheusOperator.admissionWebhooks.patch.image.repository }}:{{ .Values.prometheusOperator.admissionWebhooks.patch.image.tag }}\n          {{- end }}\n          imagePullPolicy: {{ .Values.prometheusOperator.admissionWebhooks.patch.image.pullPolicy }}\n          args:\n            - create\n            - --host={{ template \"kube-prometheus-stack.operator.fullname\" . }},{{ template \"kube-prometheus-stack.operator.fullname\" . }}.{{ template \"kube-prometheus-stack.namespace\" . }}.svc\n            - --namespace={{ template \"kube-prometheus-stack.namespace\" . }}\n            - --secret-name={{ template \"kube-prometheus-stack.fullname\" . }}-admission\n          resources:\n{{ toYaml .Values.prometheusOperator.admissionWebhooks.patch.resources | indent 12 }}\n      restartPolicy: OnFailure\n      serviceAccountName: {{ template \"kube-prometheus-stack.fullname\" . }}-admission\n      {{- with .Values.prometheusOperator.admissionWebhooks.patch.nodeSelector }}\n      nodeSelector:\n{{ toYaml . | indent 8 }}\n      {{- end }}\n      {{- with .Values.prometheusOperator.admissionWebhooks.patch.affinity }}\n      affinity:\n{{ toYaml . | indent 8 }}\n      {{- end }}\n      {{- with .Values.prometheusOperator.admissionWebhooks.patch.tolerations }}\n      tolerations:\n{{ toYaml . | indent 8 }}\n      {{- end }}\n{{- if .Values.prometheusOperator.admissionWebhooks.patch.securityContext }}\n      securityContext:\n{{ toYaml .Values.prometheusOperator.admissionWebhooks.patch.securityContext | indent 8 }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/job-patchWebhook.yaml",
    "content": "{{- if and .Values.prometheusOperator.enabled .Values.prometheusOperator.admissionWebhooks.enabled .Values.prometheusOperator.admissionWebhooks.patch.enabled (not .Values.prometheusOperator.admissionWebhooks.certManager.enabled) }}\napiVersion: batch/v1\nkind: Job\nmetadata:\n  name:  {{ template \"kube-prometheus-stack.fullname\" . }}-admission-patch\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  annotations:\n    \"helm.sh/hook\": post-install,post-upgrade\n    \"helm.sh/hook-delete-policy\": before-hook-creation,hook-succeeded\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-admission-patch\n{{- include \"kube-prometheus-stack.labels\" $ | indent 4 }}\nspec:\n  {{- if .Capabilities.APIVersions.Has \"batch/v1alpha1\" }}\n  # Alpha feature since k8s 1.12\n  ttlSecondsAfterFinished: 0\n  {{- end }}\n  template:\n    metadata:\n      name:  {{ template \"kube-prometheus-stack.fullname\" . }}-admission-patch\n{{- with .Values.prometheusOperator.admissionWebhooks.patch.podAnnotations }}\n      annotations:\n{{ toYaml .  | indent 8 }}\n{{- end }}\n      labels:\n        app: {{ template \"kube-prometheus-stack.name\" $ }}-admission-patch\n{{- include \"kube-prometheus-stack.labels\" $ | indent 8 }}\n    spec:\n      {{- if .Values.prometheusOperator.admissionWebhooks.patch.priorityClassName }}\n      priorityClassName: {{ .Values.prometheusOperator.admissionWebhooks.patch.priorityClassName }}\n      {{- end }}\n      containers:\n        - name: patch\n          {{- if .Values.prometheusOperator.admissionWebhooks.patch.image.sha }}\n          image: {{ .Values.prometheusOperator.admissionWebhooks.patch.image.repository }}:{{ .Values.prometheusOperator.admissionWebhooks.patch.image.tag }}@sha256:{{ .Values.prometheusOperator.admissionWebhooks.patch.image.sha }}\n          {{- else }}\n          image: {{ .Values.prometheusOperator.admissionWebhooks.patch.image.repository }}:{{ .Values.prometheusOperator.admissionWebhooks.patch.image.tag }}\n          {{- end }}\n          imagePullPolicy: {{ .Values.prometheusOperator.admissionWebhooks.patch.image.pullPolicy }}\n          args:\n            - patch\n            - --webhook-name={{ template \"kube-prometheus-stack.fullname\" . }}-admission\n            - --namespace={{ template \"kube-prometheus-stack.namespace\" . }}\n            - --secret-name={{ template \"kube-prometheus-stack.fullname\" . }}-admission\n            - --patch-failure-policy={{ .Values.prometheusOperator.admissionWebhooks.failurePolicy }}\n          resources:\n{{ toYaml .Values.prometheusOperator.admissionWebhooks.patch.resources | indent 12 }}\n      restartPolicy: OnFailure\n      serviceAccountName: {{ template \"kube-prometheus-stack.fullname\" . }}-admission\n      {{- with .Values.prometheusOperator.admissionWebhooks.patch.nodeSelector }}\n      nodeSelector:\n{{ toYaml . | indent 8 }}\n      {{- end }}\n      {{- with .Values.prometheusOperator.admissionWebhooks.patch.affinity }}\n      affinity:\n{{ toYaml . | indent 8 }}\n      {{- end }}\n      {{- with .Values.prometheusOperator.admissionWebhooks.patch.tolerations }}\n      tolerations:\n{{ toYaml . | indent 8 }}\n      {{- end }}\n{{- if .Values.prometheusOperator.admissionWebhooks.patch.securityContext }}\n      securityContext:\n{{ toYaml .Values.prometheusOperator.admissionWebhooks.patch.securityContext | indent 8 }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/psp.yaml",
    "content": "{{- if and .Values.prometheusOperator.enabled .Values.prometheusOperator.admissionWebhooks.enabled .Values.prometheusOperator.admissionWebhooks.patch.enabled .Values.global.rbac.create .Values.global.rbac.pspEnabled (not .Values.prometheusOperator.admissionWebhooks.certManager.enabled) }}\napiVersion: policy/v1beta1\nkind: PodSecurityPolicy\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-admission\n  annotations:\n    \"helm.sh/hook\": pre-install,pre-upgrade,post-install,post-upgrade\n    \"helm.sh/hook-delete-policy\": before-hook-creation,hook-succeeded\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-admission\n{{- if .Values.global.rbac.pspAnnotations }}\n  annotations:\n{{ toYaml .Values.global.rbac.pspAnnotations | indent 4 }}\n{{- end }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  privileged: false\n  # Required to prevent escalations to root.\n  # allowPrivilegeEscalation: false\n  # This is redundant with non-root + disallow privilege escalation,\n  # but we can provide it for defense in depth.\n  #requiredDropCapabilities:\n  #  - ALL\n  # Allow core volume types.\n  volumes:\n    - 'configMap'\n    - 'emptyDir'\n    - 'projected'\n    - 'secret'\n    - 'downwardAPI'\n    - 'persistentVolumeClaim'\n  hostNetwork: false\n  hostIPC: false\n  hostPID: false\n  runAsUser:\n    # Permits the container to run with root privileges as well.\n    rule: 'RunAsAny'\n  seLinux:\n    # This policy assumes the nodes are using AppArmor rather than SELinux.\n    rule: 'RunAsAny'\n  supplementalGroups:\n    rule: 'MustRunAs'\n    ranges:\n      # Forbid adding the root group.\n      - min: 0\n        max: 65535\n  fsGroup:\n    rule: 'MustRunAs'\n    ranges:\n      # Forbid adding the root group.\n      - min: 0\n        max: 65535\n  readOnlyRootFilesystem: false\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/role.yaml",
    "content": "{{- if and .Values.prometheusOperator.enabled .Values.prometheusOperator.admissionWebhooks.enabled .Values.prometheusOperator.admissionWebhooks.patch.enabled .Values.global.rbac.create (not .Values.prometheusOperator.admissionWebhooks.certManager.enabled) }}\napiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n  name:  {{ template \"kube-prometheus-stack.fullname\" . }}-admission\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  annotations:\n    \"helm.sh/hook\": pre-install,pre-upgrade,post-install,post-upgrade\n    \"helm.sh/hook-delete-policy\": before-hook-creation,hook-succeeded\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-admission\n{{- include \"kube-prometheus-stack.labels\" $ | indent 4 }}\nrules:\n  - apiGroups:\n      - \"\"\n    resources:\n      - secrets\n    verbs:\n      - get\n      - create\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/rolebinding.yaml",
    "content": "{{- if and .Values.prometheusOperator.enabled .Values.prometheusOperator.admissionWebhooks.enabled .Values.prometheusOperator.admissionWebhooks.patch.enabled .Values.global.rbac.create (not .Values.prometheusOperator.admissionWebhooks.certManager.enabled) }}\napiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  name:  {{ template \"kube-prometheus-stack.fullname\" . }}-admission\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  annotations:\n    \"helm.sh/hook\": pre-install,pre-upgrade,post-install,post-upgrade\n    \"helm.sh/hook-delete-policy\": before-hook-creation,hook-succeeded\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-admission\n{{- include \"kube-prometheus-stack.labels\" $ | indent 4 }}\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: Role\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-admission\nsubjects:\n  - kind: ServiceAccount\n    name: {{ template \"kube-prometheus-stack.fullname\" . }}-admission\n    namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/serviceaccount.yaml",
    "content": "{{- if and .Values.prometheusOperator.enabled .Values.prometheusOperator.admissionWebhooks.enabled .Values.prometheusOperator.admissionWebhooks.patch.enabled .Values.global.rbac.create (not .Values.prometheusOperator.admissionWebhooks.certManager.enabled) }}\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name:  {{ template \"kube-prometheus-stack.fullname\" . }}-admission\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  annotations:\n    \"helm.sh/hook\": pre-install,pre-upgrade,post-install,post-upgrade\n    \"helm.sh/hook-delete-policy\": before-hook-creation,hook-succeeded\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-admission\n{{- include \"kube-prometheus-stack.labels\" $ | indent 4 }}\n{{- if .Values.global.imagePullSecrets }}\nimagePullSecrets:\n{{ toYaml .Values.global.imagePullSecrets | indent 2 }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/mutatingWebhookConfiguration.yaml",
    "content": "{{- if and .Values.prometheusOperator.enabled .Values.prometheusOperator.admissionWebhooks.enabled }}\napiVersion: admissionregistration.k8s.io/v1\nkind: MutatingWebhookConfiguration\nmetadata:\n  name:  {{ template \"kube-prometheus-stack.fullname\" . }}-admission\n{{- if .Values.prometheusOperator.admissionWebhooks.certManager.enabled }}\n  annotations:\n    certmanager.k8s.io/inject-ca-from: {{ printf \"%s/%s-admission\" .Release.Namespace (include \"kube-prometheus-stack.fullname\" .) | quote }}\n    cert-manager.io/inject-ca-from: {{ printf \"%s/%s-admission\" .Release.Namespace (include \"kube-prometheus-stack.fullname\" .) | quote }}\n{{- end }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-admission\n{{- include \"kube-prometheus-stack.labels\" $ | indent 4 }}\nwebhooks:\n  - name: prometheusrulemutate.monitoring.coreos.com\n    {{- if .Values.prometheusOperator.admissionWebhooks.patch.enabled  }}\n    failurePolicy: Ignore\n    {{- else }}\n    failurePolicy: {{ .Values.prometheusOperator.admissionWebhooks.failurePolicy }}\n    {{- end }}\n    rules:\n      - apiGroups:\n          - monitoring.coreos.com\n        apiVersions:\n          - \"*\"\n        resources:\n          - prometheusrules\n        operations:\n          - CREATE\n          - UPDATE\n    clientConfig:\n      service:\n        namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n        name: {{ template \"kube-prometheus-stack.operator.fullname\" $ }}\n        path: /admission-prometheusrules/mutate\n      {{- if and .Values.prometheusOperator.admissionWebhooks.caBundle (not .Values.prometheusOperator.admissionWebhooks.patch.enabled) (not .Values.prometheusOperator.admissionWebhooks.certManager.enabled) }}\n      caBundle: {{ .Values.prometheusOperator.admissionWebhooks.caBundle }}\n      {{- end }}\n    admissionReviewVersions: [\"v1\", \"v1beta1\"]\n    sideEffects: None\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/validatingWebhookConfiguration.yaml",
    "content": "{{- if and .Values.prometheusOperator.enabled .Values.prometheusOperator.admissionWebhooks.enabled }}\napiVersion: admissionregistration.k8s.io/v1\nkind: ValidatingWebhookConfiguration\nmetadata:\n  name:  {{ template \"kube-prometheus-stack.fullname\" . }}-admission\n{{- if .Values.prometheusOperator.admissionWebhooks.certManager.enabled }}\n  annotations:\n    certmanager.k8s.io/inject-ca-from: {{ printf \"%s/%s-admission\" .Release.Namespace (include \"kube-prometheus-stack.fullname\" .) | quote }}\n    cert-manager.io/inject-ca-from: {{ printf \"%s/%s-admission\" .Release.Namespace (include \"kube-prometheus-stack.fullname\" .) | quote }}\n{{- end }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" $ }}-admission\n{{- include \"kube-prometheus-stack.labels\" $ | indent 4 }}\nwebhooks:\n  - name: prometheusrulemutate.monitoring.coreos.com\n    {{- if .Values.prometheusOperator.admissionWebhooks.patch.enabled  }}\n    failurePolicy: Ignore\n    {{- else }}\n    failurePolicy: {{ .Values.prometheusOperator.admissionWebhooks.failurePolicy }}\n    {{- end }}\n    rules:\n      - apiGroups:\n          - monitoring.coreos.com\n        apiVersions:\n          - \"*\"\n        resources:\n          - prometheusrules\n        operations:\n          - CREATE\n          - UPDATE\n    clientConfig:\n      service:\n        namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n        name: {{ template \"kube-prometheus-stack.operator.fullname\" $ }}\n        path: /admission-prometheusrules/validate\n      {{- if and .Values.prometheusOperator.admissionWebhooks.caBundle (not .Values.prometheusOperator.admissionWebhooks.patch.enabled) (not .Values.prometheusOperator.admissionWebhooks.certManager.enabled) }}\n      caBundle: {{ .Values.prometheusOperator.admissionWebhooks.caBundle }}\n      {{- end }}\n    admissionReviewVersions: [\"v1\", \"v1beta1\"]\n    sideEffects: None\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus-operator/certmanager.yaml",
    "content": "{{- if .Values.prometheusOperator.admissionWebhooks.certManager.enabled -}}\n{{- if not .Values.prometheusOperator.admissionWebhooks.certManager.issuerRef -}}\n# Create a selfsigned Issuer, in order to create a root CA certificate for\n# signing webhook serving certificates\napiVersion: cert-manager.io/v1\nkind: Issuer\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-self-signed-issuer\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\nspec:\n  selfSigned: {}\n---\n# Generate a CA Certificate used to sign certificates for the webhook\napiVersion: cert-manager.io/v1\nkind: Certificate\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-root-cert\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\nspec:\n  secretName: {{ template \"kube-prometheus-stack.fullname\" . }}-root-cert\n  duration: 43800h0m0s # 5y\n  issuerRef:\n    name: {{ template \"kube-prometheus-stack.fullname\" . }}-self-signed-issuer\n  commonName: \"ca.webhook.kube-prometheus-stack\"\n  isCA: true\n---\n# Create an Issuer that uses the above generated CA certificate to issue certs\napiVersion: cert-manager.io/v1\nkind: Issuer\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-root-issuer\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\nspec:\n  ca:\n    secretName: {{ template \"kube-prometheus-stack.fullname\" . }}-root-cert\n{{- end }}\n---\n# generate a serving certificate for the apiservices to use\napiVersion: cert-manager.io/v1\nkind: Certificate\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-admission\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\nspec:\n  secretName: {{ template \"kube-prometheus-stack.fullname\" . }}-admission\n  duration: 8760h0m0s # 1y\n  issuerRef:\n    {{- if .Values.prometheusOperator.admissionWebhooks.certManager.issuerRef }}\n    {{- toYaml .Values.prometheusOperator.admissionWebhooks.certManager.issuerRef | nindent 4 }}\n    {{- else }}\n    name: {{ template \"kube-prometheus-stack.fullname\" . }}-root-issuer\n    {{- end }}\n  dnsNames:\n  - {{ template \"kube-prometheus-stack.operator.fullname\" . }}\n  - {{ template \"kube-prometheus-stack.operator.fullname\" . }}.{{ template \"kube-prometheus-stack.namespace\" . }}\n  - {{ template \"kube-prometheus-stack.operator.fullname\" . }}.{{ template \"kube-prometheus-stack.namespace\" . }}.svc\n{{- end -}}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus-operator/clusterrole.yaml",
    "content": "{{- if and .Values.prometheusOperator.enabled .Values.global.rbac.create }}\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-operator\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-operator\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nrules:\n- apiGroups:\n  - monitoring.coreos.com\n  resources:\n  - alertmanagers\n  - alertmanagers/finalizers\n  - alertmanagerconfigs\n  - prometheuses\n  - prometheuses/finalizers\n  - thanosrulers\n  - thanosrulers/finalizers\n  - servicemonitors\n  - podmonitors\n  - probes\n  - prometheusrules\n  verbs:\n  - '*'\n- apiGroups:\n  - apps\n  resources:\n  - statefulsets\n  verbs:\n  - '*'\n- apiGroups:\n  - \"\"\n  resources:\n  - configmaps\n  - secrets\n  verbs:\n  - '*'\n- apiGroups:\n  - \"\"\n  resources:\n  - pods\n  verbs:\n  - list\n  - delete\n- apiGroups:\n  - \"\"\n  resources:\n  - services\n  - services/finalizers\n  - endpoints\n  verbs:\n  - get\n  - create\n  - update\n  - delete\n- apiGroups:\n  - \"\"\n  resources:\n  - nodes\n  verbs:\n  - list\n  - watch\n- apiGroups:\n  - \"\"\n  resources:\n  - namespaces\n  verbs:\n  - get\n  - list\n  - watch\n- apiGroups:\n  - networking.k8s.io\n  resources:\n  - ingresses\n  verbs:\n  - get\n  - list\n  - watch\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus-operator/clusterrolebinding.yaml",
    "content": "{{- if and .Values.prometheusOperator.enabled .Values.global.rbac.create }}\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-operator\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-operator\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-operator\nsubjects:\n- kind: ServiceAccount\n  name: {{ template \"kube-prometheus-stack.operator.serviceAccountName\" . }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus-operator/deployment.yaml",
    "content": "{{- $namespace := printf \"%s\" (include \"kube-prometheus-stack.namespace\" .) }}\n{{- if .Values.prometheusOperator.enabled }}\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-operator\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-operator\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: {{ template \"kube-prometheus-stack.name\" . }}-operator\n      release: {{ $.Release.Name | quote }}\n  template:\n    metadata:\n      labels:\n        app: {{ template \"kube-prometheus-stack.name\" . }}-operator\n{{ include \"kube-prometheus-stack.labels\" . | indent 8 }}\n{{- if .Values.prometheusOperator.podLabels }}\n{{ toYaml .Values.prometheusOperator.podLabels | indent 8 }}\n{{- end }}\n{{- if .Values.prometheusOperator.podAnnotations }}\n      annotations:\n{{ toYaml .Values.prometheusOperator.podAnnotations | indent 8 }}\n{{- end }}\n    spec:\n    {{- if .Values.prometheusOperator.priorityClassName }}\n      priorityClassName: {{ .Values.prometheusOperator.priorityClassName }}\n    {{- end }}\n      containers:\n        - name: {{ template \"kube-prometheus-stack.name\" . }}\n          {{- if .Values.prometheusOperator.image.sha }}\n          image: \"{{ .Values.prometheusOperator.image.repository }}:{{ .Values.prometheusOperator.image.tag }}@sha256:{{ .Values.prometheusOperator.image.sha }}\"\n          {{- else }}\n          image: \"{{ .Values.prometheusOperator.image.repository }}:{{ .Values.prometheusOperator.image.tag }}\"\n          {{- end }}\n          imagePullPolicy: \"{{ .Values.prometheusOperator.image.pullPolicy }}\"\n          args:\n            {{- if .Values.prometheusOperator.kubeletService.enabled }}\n            - --kubelet-service={{ .Values.prometheusOperator.kubeletService.namespace }}/{{ template \"kube-prometheus-stack.fullname\" . }}-kubelet\n            {{- end }}\n            {{- if .Values.prometheusOperator.logFormat }}\n            - --log-format={{ .Values.prometheusOperator.logFormat }}\n            {{- end }}\n            {{- if .Values.prometheusOperator.logLevel }}\n            - --log-level={{ .Values.prometheusOperator.logLevel }}\n            {{- end }}\n            {{- if .Values.prometheusOperator.denyNamespaces }}\n            - --deny-namespaces={{ .Values.prometheusOperator.denyNamespaces | join \",\" }}\n            {{- end }}\n            {{- with $.Values.prometheusOperator.namespaces }}\n            {{ $ns := .additional }}\n            {{- if .releaseNamespace }}\n            {{- $ns = append $ns $namespace }}\n            {{- end }}\n            - --namespaces={{ $ns | join \",\" }}\n            {{- end }}\n            - --localhost=127.0.0.1\n            {{- if .Values.prometheusOperator.prometheusDefaultBaseImage }}\n            - --prometheus-default-base-image={{ .Values.prometheusOperator.prometheusDefaultBaseImage }}\n            {{- end }}\n            {{- if .Values.prometheusOperator.alertmanagerDefaultBaseImage }}\n            - --alertmanager-default-base-image={{ .Values.prometheusOperator.alertmanagerDefaultBaseImage }}\n            {{- end }}\n            {{- if .Values.prometheusOperator.prometheusConfigReloaderImage.sha }}\n            - --prometheus-config-reloader={{ .Values.prometheusOperator.prometheusConfigReloaderImage.repository }}:{{ .Values.prometheusOperator.prometheusConfigReloaderImage.tag }}@sha256:{{ .Values.prometheusOperator.prometheusConfigReloaderImage.sha }}\n            {{- else }}\n            - --prometheus-config-reloader={{ .Values.prometheusOperator.prometheusConfigReloaderImage.repository }}:{{ .Values.prometheusOperator.prometheusConfigReloaderImage.tag }}\n            {{- end }}\n            - --config-reloader-cpu={{ .Values.prometheusOperator.configReloaderCpu }}\n            - --config-reloader-memory={{ .Values.prometheusOperator.configReloaderMemory }}\n            {{- if .Values.prometheusOperator.alertmanagerInstanceNamespaces }}\n            - --alertmanager-instance-namespaces={{ .Values.prometheusOperator.alertmanagerInstanceNamespaces | join \",\" }}\n            {{- end }}\n            {{- if .Values.prometheusOperator.prometheusInstanceNamespaces }}\n            - --prometheus-instance-namespaces={{ .Values.prometheusOperator.prometheusInstanceNamespaces | join \",\" }}\n            {{- end }}\n            {{- if .Values.prometheusOperator.thanosImage.sha }}\n            - --thanos-default-base-image={{ .Values.prometheusOperator.thanosImage.repository }}:{{ .Values.prometheusOperator.thanosImage.tag }}@sha256:{{ .Values.prometheusOperator.thanosImage.sha }}\n            {{- else }}\n            - --thanos-default-base-image={{ .Values.prometheusOperator.thanosImage.repository }}:{{ .Values.prometheusOperator.thanosImage.tag }}\n            {{- end }} \n            {{- if .Values.prometheusOperator.thanosRulerInstanceNamespaces }}\n            - --thanos-ruler-instance-namespaces={{ .Values.prometheusOperator.thanosRulerInstanceNamespaces | join \",\" }}\n            {{- end }}\n            {{- if .Values.prometheusOperator.secretFieldSelector }}\n            - --secret-field-selector={{ .Values.prometheusOperator.secretFieldSelector }}\n            {{- end }}\n            {{- if .Values.prometheusOperator.clusterDomain }}\n            - --cluster-domain={{ .Values.prometheusOperator.clusterDomain }}\n            {{- end }}\n            {{- if .Values.prometheusOperator.tls.enabled }}\n            - --web.enable-tls=true\n            - --web.cert-file=/cert/{{ if .Values.prometheusOperator.admissionWebhooks.certManager.enabled }}tls.crt{{ else }}cert{{ end }}\n            - --web.key-file=/cert/{{ if .Values.prometheusOperator.admissionWebhooks.certManager.enabled }}tls.key{{ else }}key{{ end }}\n            - --web.listen-address=:{{ .Values.prometheusOperator.tls.internalPort }}\n            - --web.tls-min-version={{ .Values.prometheusOperator.tls.tlsMinVersion }}\n          ports:\n            - containerPort: {{ .Values.prometheusOperator.tls.internalPort }}\n              name: https\n          {{- else }}\n          ports:\n            - containerPort: 8080\n              name: http\n          {{- end }}\n          resources:\n{{ toYaml .Values.prometheusOperator.resources | indent 12 }}\n          securityContext:\n            allowPrivilegeEscalation: false\n            readOnlyRootFilesystem: true\n{{- if .Values.prometheusOperator.tls.enabled }}\n          volumeMounts:\n            - name: tls-secret\n              mountPath: /cert\n              readOnly: true\n      volumes:\n        - name: tls-secret\n          secret:\n            defaultMode: 420\n            secretName: {{ template \"kube-prometheus-stack.fullname\" . }}-admission\n{{- end }}\n    {{- with .Values.prometheusOperator.dnsConfig }}\n      dnsConfig:\n{{ toYaml . | indent 8 }}\n    {{- end }}\n{{- if .Values.prometheusOperator.securityContext }}\n      securityContext:\n{{ toYaml .Values.prometheusOperator.securityContext | indent 8 }}\n{{- end }}\n      serviceAccountName: {{ template \"kube-prometheus-stack.operator.serviceAccountName\" . }}\n{{- if .Values.prometheusOperator.hostNetwork }}\n      hostNetwork: true\n      dnsPolicy: ClusterFirstWithHostNet\n{{- end }}\n    {{- with .Values.prometheusOperator.nodeSelector }}\n      nodeSelector:\n{{ toYaml . | indent 8 }}\n    {{- end }}\n    {{- with .Values.prometheusOperator.affinity }}\n      affinity:\n{{ toYaml . | indent 8 }}\n    {{- end }}\n    {{- with .Values.prometheusOperator.tolerations }}\n      tolerations:\n{{ toYaml . | indent 8 }}\n    {{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus-operator/psp-clusterrole.yaml",
    "content": "{{- if and .Values.prometheusOperator.enabled .Values.global.rbac.create .Values.global.rbac.pspEnabled }}\nkind: ClusterRole\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-operator-psp\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-operator\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nrules:\n{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}\n{{- if semverCompare \"> 1.15.0-0\" $kubeTargetVersion }}\n- apiGroups: ['policy']\n{{- else }}\n- apiGroups: ['extensions']\n{{- end }}\n  resources: ['podsecuritypolicies']\n  verbs:     ['use']\n  resourceNames:\n  - {{ template \"kube-prometheus-stack.fullname\" . }}-operator\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus-operator/psp-clusterrolebinding.yaml",
    "content": "{{- if and .Values.prometheusOperator.enabled .Values.global.rbac.create .Values.global.rbac.pspEnabled }}\nkind: ClusterRoleBinding\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-operator-psp\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-operator\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-operator-psp\nsubjects:\n  - kind: ServiceAccount\n    name: {{ template \"kube-prometheus-stack.operator.serviceAccountName\" . }}\n    namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus-operator/psp.yaml",
    "content": "{{- if and .Values.prometheusOperator.enabled .Values.global.rbac.create .Values.global.rbac.pspEnabled }}\napiVersion: policy/v1beta1\nkind: PodSecurityPolicy\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-operator\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-operator\n{{- if .Values.global.rbac.pspAnnotations }}\n  annotations:\n{{ toYaml .Values.global.rbac.pspAnnotations | indent 4 }}\n{{- end }}\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  privileged: false\n  # Required to prevent escalations to root.\n  # allowPrivilegeEscalation: false\n  # This is redundant with non-root + disallow privilege escalation,\n  # but we can provide it for defense in depth.\n  #requiredDropCapabilities:\n  #  - ALL\n  # Allow core volume types.\n  volumes:\n    - 'configMap'\n    - 'emptyDir'\n    - 'projected'\n    - 'secret'\n    - 'downwardAPI'\n    - 'persistentVolumeClaim'\n  hostNetwork: {{ .Values.prometheusOperator.hostNetwork }}\n  hostIPC: false\n  hostPID: false\n  runAsUser:\n    # Permits the container to run with root privileges as well.\n    rule: 'RunAsAny'\n  seLinux:\n    # This policy assumes the nodes are using AppArmor rather than SELinux.\n    rule: 'RunAsAny'\n  supplementalGroups:\n    rule: 'MustRunAs'\n    ranges:\n      # Forbid adding the root group.\n      - min: 0\n        max: 65535\n  fsGroup:\n    rule: 'MustRunAs'\n    ranges:\n      # Forbid adding the root group.\n      - min: 0\n        max: 65535\n  readOnlyRootFilesystem: false\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus-operator/service.yaml",
    "content": "{{- if .Values.prometheusOperator.enabled }}\napiVersion: v1\nkind: Service\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-operator\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-operator\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.prometheusOperator.service.labels }}\n{{ toYaml .Values.prometheusOperator.service.labels | indent 4 }}\n{{- end }}\n{{- if .Values.prometheusOperator.service.annotations }}\n  annotations:\n{{ toYaml .Values.prometheusOperator.service.annotations | indent 4 }}\n{{- end }}\nspec:\n{{- if .Values.prometheusOperator.service.clusterIP }}\n  clusterIP: {{ .Values.prometheusOperator.service.clusterIP }}\n{{- end }}\n{{- if .Values.prometheusOperator.service.externalIPs }}\n  externalIPs:\n{{ toYaml .Values.prometheusOperator.service.externalIPs | indent 4 }}\n{{- end }}\n{{- if .Values.prometheusOperator.service.loadBalancerIP }}\n  loadBalancerIP: {{ .Values.prometheusOperator.service.loadBalancerIP }}\n{{- end }}\n{{- if .Values.prometheusOperator.service.loadBalancerSourceRanges }}\n  loadBalancerSourceRanges:\n  {{- range $cidr := .Values.prometheusOperator.service.loadBalancerSourceRanges }}\n    - {{ $cidr }}\n  {{- end }}\n{{- end }}\n  ports:\n  {{- if not .Values.prometheusOperator.tls.enabled }}\n  - name: http\n    {{- if eq .Values.prometheusOperator.service.type \"NodePort\" }}\n    nodePort: {{ .Values.prometheusOperator.service.nodePort }}\n    {{- end }}\n    port: 8080\n    targetPort: http\n  {{- end }}\n  {{- if .Values.prometheusOperator.tls.enabled }}\n  - name: https\n    {{- if eq .Values.prometheusOperator.service.type \"NodePort\"}}\n    nodePort: {{ .Values.prometheusOperator.service.nodePortTls }}\n    {{- end }}\n    port: 443\n    targetPort: https\n  {{- end }}\n  selector:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-operator\n    release: {{ $.Release.Name | quote }}\n  type: \"{{ .Values.prometheusOperator.service.type }}\"\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus-operator/serviceaccount.yaml",
    "content": "{{- if and .Values.prometheusOperator.enabled .Values.prometheusOperator.serviceAccount.create }}\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: {{ template \"kube-prometheus-stack.operator.serviceAccountName\" . }}\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-operator\n    app.kubernetes.io/name: {{ template \"kube-prometheus-stack.name\" . }}-prometheus-operator\n    app.kubernetes.io/component: prometheus-operator\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\n{{- if .Values.global.imagePullSecrets }}\nimagePullSecrets:\n{{ toYaml .Values.global.imagePullSecrets | indent 2 }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/templates/prometheus-operator/servicemonitor.yaml",
    "content": "{{- if and .Values.prometheusOperator.enabled .Values.prometheusOperator.serviceMonitor.selfMonitor }}\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  name: {{ template \"kube-prometheus-stack.fullname\" . }}-operator\n  namespace: {{ template \"kube-prometheus-stack.namespace\" . }}\n  labels:\n    app: {{ template \"kube-prometheus-stack.name\" . }}-operator\n{{ include \"kube-prometheus-stack.labels\" . | indent 4 }}\nspec:\n  endpoints:\n  {{- if .Values.prometheusOperator.tls.enabled }}\n  - port: https\n    scheme: https\n    tlsConfig:\n      serverName: {{ template \"kube-prometheus-stack.operator.fullname\" . }}\n      ca:\n        secret:\n          name: {{ template \"kube-prometheus-stack.fullname\" . }}-admission\n          key: {{ if .Values.prometheusOperator.admissionWebhooks.certManager.enabled }}ca.crt{{ else }}ca{{ end }}\n          optional: false\n  {{- else }}\n  - port: http\n  {{- end }}\n    honorLabels: true\n    {{- if .Values.prometheusOperator.serviceMonitor.interval }}\n    interval: {{ .Values.prometheusOperator.serviceMonitor.interval }}\n    {{- end }}\n{{- if .Values.prometheusOperator.serviceMonitor.metricRelabelings }}\n    metricRelabelings:\n{{ tpl (toYaml .Values.prometheusOperator.serviceMonitor.metricRelabelings | indent 6) . }}\n{{- end }}\n{{- if .Values.prometheusOperator.serviceMonitor.relabelings }}\n    relabelings:\n{{ toYaml .Values.prometheusOperator.serviceMonitor.relabelings | indent 6 }}\n{{- end }}\n  selector:\n    matchLabels:\n      app: {{ template \"kube-prometheus-stack.name\" . }}-operator\n      release: {{ $.Release.Name | quote }}\n  namespaceSelector:\n    matchNames:\n      - {{ printf \"%s\" (include \"kube-prometheus-stack.namespace\" .) | quote }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/kube-prometheus-stack/values.yaml",
    "content": "# Default values for kube-prometheus-stack.\n# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\n\n## Provide a name in place of kube-prometheus-stack for `app:` labels\n##\nnameOverride: \"\"\n\n## Override the deployment namespace\n##\nnamespaceOverride: \"\"\n\n## Provide a k8s version to auto dashboard import script example: kubeTargetVersionOverride: 1.16.6\n##\nkubeTargetVersionOverride: \"\"\n\n## Allow kubeVersion to be overridden while creating the ingress\n##\nkubeVersionOverride: \"\"\n\n## Provide a name to substitute for the full names of resources\n##\nfullnameOverride: \"\"\n\n## Labels to apply to all resources\n##\ncommonLabels: {}\n# scmhash: abc123\n# myLabel: aakkmd\n\n## Create default rules for monitoring the cluster\n##\ndefaultRules:\n  create: false\n  rules:\n    alertmanager: true\n    etcd: true\n    general: true\n    k8s: true\n    kubeApiserver: true\n    kubeApiserverAvailability: true\n    kubeApiserverError: true\n    kubeApiserverSlos: true\n    kubelet: true\n    kubePrometheusGeneral: true\n    kubePrometheusNodeAlerting: true\n    kubePrometheusNodeRecording: true\n    kubernetesAbsent: true\n    kubernetesApps: true\n    kubernetesResources: true\n    kubernetesStorage: true\n    kubernetesSystem: true\n    kubeScheduler: true\n    kubeStateMetrics: true\n    network: true\n    node: true\n    prometheus: true\n    prometheusOperator: true\n    time: true\n\n  ## Runbook url prefix for default rules\n  runbookUrl: https://github.com/kubernetes-monitoring/kubernetes-mixin/tree/master/runbook.md#\n  ## Reduce app namespace alert scope\n  appNamespacesTarget: \".*\"\n\n  ## Labels for default rules\n  labels: {}\n  ## Annotations for default rules\n  annotations: {}\n\n  ## Additional labels for PrometheusRule alerts\n  additionalRuleLabels: {}\n\n## Deprecated way to provide custom recording or alerting rules to be deployed into the cluster.\n##\n# additionalPrometheusRules: []\n#  - name: my-rule-file\n#    groups:\n#      - name: my_group\n#        rules:\n#        - record: my_record\n#          expr: 100 * my_record\n\n## Provide custom recording or alerting rules to be deployed into the cluster.\n##\nadditionalPrometheusRulesMap: {}\n#  rule-name:\n#    groups:\n#    - name: my_group\n#      rules:\n#      - record: my_record\n#        expr: 100 * my_record\n\n##\nglobal:\n  rbac:\n    create: true\n    pspEnabled: true\n    pspAnnotations: {}\n      ## Specify pod annotations\n      ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor\n      ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp\n      ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl\n      ##\n      # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*'\n      # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default'\n      # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default'\n\n  ## Reference to one or more secrets to be used when pulling images\n  ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/\n  ##\n  imagePullSecrets: []\n  # - name: \"image-pull-secret\"\n\n## Configuration for alertmanager\n## ref: https://prometheus.io/docs/alerting/alertmanager/\n##\nalertmanager:\n\n  ## Deploy alertmanager\n  ##\n  enabled: false\n\n  ## Annotations for Alertmanager\n  ##\n  annotations: {}\n\n  ## Api that prometheus will use to communicate with alertmanager. Possible values are v1, v2\n  ##\n  apiVersion: v2\n\n  ## Service account for Alertmanager to use.\n  ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/\n  ##\n  serviceAccount:\n    create: true\n    name: \"\"\n    annotations: {}\n\n  ## Configure pod disruption budgets for Alertmanager\n  ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget\n  ## This configuration is immutable once created and will require the PDB to be deleted to be changed\n  ## https://github.com/kubernetes/kubernetes/issues/45398\n  ##\n  podDisruptionBudget:\n    enabled: false\n    minAvailable: 1\n    maxUnavailable: \"\"\n\n  ## Alertmanager configuration directives\n  ## ref: https://prometheus.io/docs/alerting/configuration/#configuration-file\n  ##      https://prometheus.io/webtools/alerting/routing-tree-editor/\n  ##\n  config:\n    global:\n      resolve_timeout: 5m\n    route:\n      group_by: ['job']\n      group_wait: 30s\n      group_interval: 5m\n      repeat_interval: 12h\n      receiver: 'null'\n      routes:\n      - match:\n          alertname: Watchdog\n        receiver: 'null'\n    receivers:\n    - name: 'null'\n    templates:\n    - '/etc/alertmanager/config/*.tmpl'\n\n  ## Pass the Alertmanager configuration directives through Helm's templating\n  ## engine. If the Alertmanager configuration contains Alertmanager templates,\n  ## they'll need to be properly escaped so that they are not interpreted by\n  ## Helm\n  ## ref: https://helm.sh/docs/developing_charts/#using-the-tpl-function\n  ##      https://prometheus.io/docs/alerting/configuration/#tmpl_string\n  ##      https://prometheus.io/docs/alerting/notifications/\n  ##      https://prometheus.io/docs/alerting/notification_examples/\n  tplConfig: false\n\n  ## Alertmanager template files to format alerts\n  ## By default, templateFiles are placed in /etc/alertmanager/config/ and if\n  ## they have a .tmpl file suffix will be loaded. See config.templates above\n  ## to change, add other suffixes. If adding other suffixes, be sure to update\n  ## config.templates above to include those suffixes.\n  ## ref: https://prometheus.io/docs/alerting/notifications/\n  ##      https://prometheus.io/docs/alerting/notification_examples/\n  ##\n  templateFiles: {}\n  #\n  ## An example template:\n  #   template_1.tmpl: |-\n  #       {{ define \"cluster\" }}{{ .ExternalURL | reReplaceAll \".*alertmanager\\\\.(.*)\" \"$1\" }}{{ end }}\n  #\n  #       {{ define \"slack.myorg.text\" }}\n  #       {{- $root := . -}}\n  #       {{ range .Alerts }}\n  #         *Alert:* {{ .Annotations.summary }} - `{{ .Labels.severity }}`\n  #         *Cluster:*  {{ template \"cluster\" $root }}\n  #         *Description:* {{ .Annotations.description }}\n  #         *Graph:* <{{ .GeneratorURL }}|:chart_with_upwards_trend:>\n  #         *Runbook:* <{{ .Annotations.runbook }}|:spiral_note_pad:>\n  #         *Details:*\n  #           {{ range .Labels.SortedPairs }} - *{{ .Name }}:* `{{ .Value }}`\n  #           {{ end }}\n  #       {{ end }}\n  #       {{ end }}\n\n  ingress:\n    enabled: false\n\n    # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName\n    # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress\n    # ingressClassName: nginx\n\n    annotations: {}\n\n    labels: {}\n\n    ## Hosts must be provided if Ingress is enabled.\n    ##\n    hosts: []\n      # - alertmanager.domain.com\n\n    ## Paths to use for ingress rules - one path should match the alertmanagerSpec.routePrefix\n    ##\n    paths: []\n    # - /\n\n    ## For Kubernetes >= 1.18 you should specify the pathType (determines how Ingress paths should be matched)\n    ## See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#better-path-matching-with-path-types\n    # pathType: ImplementationSpecific\n\n    ## TLS configuration for Alertmanager Ingress\n    ## Secret must be manually created in the namespace\n    ##\n    tls: []\n    # - secretName: alertmanager-general-tls\n    #   hosts:\n    #   - alertmanager.example.com\n\n  ## Configuration for Alertmanager secret\n  ##\n  secret:\n    annotations: {}\n\n  ## Configuration for creating an Ingress that will map to each Alertmanager replica service\n  ## alertmanager.servicePerReplica must be enabled\n  ##\n  ingressPerReplica:\n    enabled: false\n\n    # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName\n    # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress\n    # ingressClassName: nginx\n\n    annotations: {}\n    labels: {}\n\n    ## Final form of the hostname for each per replica ingress is\n    ## {{ ingressPerReplica.hostPrefix }}-{{ $replicaNumber }}.{{ ingressPerReplica.hostDomain }}\n    ##\n    ## Prefix for the per replica ingress that will have `-$replicaNumber`\n    ## appended to the end\n    hostPrefix: \"\"\n    ## Domain that will be used for the per replica ingress\n    hostDomain: \"\"\n\n    ## Paths to use for ingress rules\n    ##\n    paths: []\n    # - /\n\n    ## For Kubernetes >= 1.18 you should specify the pathType (determines how Ingress paths should be matched)\n    ## See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#better-path-matching-with-path-types\n    # pathType: ImplementationSpecific\n\n    ## Secret name containing the TLS certificate for alertmanager per replica ingress\n    ## Secret must be manually created in the namespace\n    tlsSecretName: \"\"\n\n    ## Separated secret for each per replica Ingress. Can be used together with cert-manager\n    ##\n    tlsSecretPerReplica:\n      enabled: false\n      ## Final form of the secret for each per replica ingress is\n      ## {{ tlsSecretPerReplica.prefix }}-{{ $replicaNumber }}\n      ##\n      prefix: \"alertmanager\"\n\n  ## Configuration for Alertmanager service\n  ##\n  service:\n    annotations: {}\n    labels: {}\n    clusterIP: \"\"\n\n    ## Port for Alertmanager Service to listen on\n    ##\n    port: 9093\n    ## To be used with a proxy extraContainer port\n    ##\n    targetPort: 9093\n    ## Port to expose on each node\n    ## Only used if service.type is 'NodePort'\n    ##\n    nodePort: 30903\n    ## List of IP addresses at which the Prometheus server service is available\n    ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips\n    ##\n\n    ## Additional ports to open for Alertmanager service\n    additionalPorts: []\n\n    externalIPs: []\n    loadBalancerIP: \"\"\n    loadBalancerSourceRanges: []\n    ## Service type\n    ##\n    type: ClusterIP\n\n  ## Configuration for creating a separate Service for each statefulset Alertmanager replica\n  ##\n  servicePerReplica:\n    enabled: false\n    annotations: {}\n\n    ## Port for Alertmanager Service per replica to listen on\n    ##\n    port: 9093\n\n    ## To be used with a proxy extraContainer port\n    targetPort: 9093\n\n    ## Port to expose on each node\n    ## Only used if servicePerReplica.type is 'NodePort'\n    ##\n    nodePort: 30904\n\n    ## Loadbalancer source IP ranges\n    ## Only used if servicePerReplica.type is \"LoadBalancer\"\n    loadBalancerSourceRanges: []\n    ## Service type\n    ##\n    type: ClusterIP\n\n  ## If true, create a serviceMonitor for alertmanager\n  ##\n  serviceMonitor:\n    ## Scrape interval. If not set, the Prometheus default scrape interval is used.\n    ##\n    interval: \"\"\n    selfMonitor: true\n\n    ## proxyUrl: URL of a proxy that should be used for scraping.\n    ##\n    proxyUrl: \"\"\n\n    ## scheme: HTTP scheme to use for scraping. Can be used with `tlsConfig` for example if using istio mTLS.\n    scheme: \"\"\n\n    ## tlsConfig: TLS configuration to use when scraping the endpoint. For example if using istio mTLS.\n    ## Of type: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#tlsconfig\n    tlsConfig: {}\n\n    bearerTokenFile:\n\n    ## \tmetric relabel configs to apply to samples before ingestion.\n    ##\n    metricRelabelings: []\n    # - action: keep\n    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'\n    #   sourceLabels: [__name__]\n\n    # \trelabel configs to apply to samples before ingestion.\n    ##\n    relabelings: []\n    # - sourceLabels: [__meta_kubernetes_pod_node_name]\n    #   separator: ;\n    #   regex: ^(.*)$\n    #   targetLabel: nodename\n    #   replacement: $1\n    #   action: replace\n\n  ## Settings affecting alertmanagerSpec\n  ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#alertmanagerspec\n  ##\n  alertmanagerSpec:\n    ## Standard object's metadata. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#metadata\n    ## Metadata Labels and Annotations gets propagated to the Alertmanager pods.\n    ##\n    podMetadata: {}\n\n    ## Image of Alertmanager\n    ##\n    image:\n      repository: quay.io/prometheus/alertmanager\n      tag: v0.22.2\n      sha: \"\"\n\n    ## If true then the user will be responsible to provide a secret with alertmanager configuration\n    ## So when true the config part will be ignored (including templateFiles) and the one in the secret will be used\n    ##\n    useExistingSecret: false\n\n    ## Secrets is a list of Secrets in the same namespace as the Alertmanager object, which shall be mounted into the\n    ## Alertmanager Pods. The Secrets are mounted into /etc/alertmanager/secrets/.\n    ##\n    secrets: []\n\n    ## ConfigMaps is a list of ConfigMaps in the same namespace as the Alertmanager object, which shall be mounted into the Alertmanager Pods.\n    ## The ConfigMaps are mounted into /etc/alertmanager/configmaps/.\n    ##\n    configMaps: []\n\n    ## ConfigSecret is the name of a Kubernetes Secret in the same namespace as the Alertmanager object, which contains configuration for\n    ## this Alertmanager instance. Defaults to 'alertmanager-' The secret is mounted into /etc/alertmanager/config.\n    ##\n    # configSecret:\n\n    ## AlertmanagerConfigs to be selected to merge and configure Alertmanager with.\n    ##\n    alertmanagerConfigSelector: {}\n    ## Example which selects all alertmanagerConfig resources\n    ## with label \"alertconfig\" with values any of \"example-config\" or \"example-config-2\"\n    # alertmanagerConfigSelector:\n    #   matchExpressions:\n    #     - key: alertconfig\n    #       operator: In\n    #       values:\n    #         - example-config\n    #         - example-config-2\n    #\n    ## Example which selects all alertmanagerConfig resources with label \"role\" set to \"example-config\"\n    # alertmanagerConfigSelector:\n    #   matchLabels:\n    #     role: example-config\n\n    ## Namespaces to be selected for AlertmanagerConfig discovery. If nil, only check own namespace.\n    ##\n    alertmanagerConfigNamespaceSelector: {}\n    ## Example which selects all namespaces\n    ## with label \"alertmanagerconfig\" with values any of \"example-namespace\" or \"example-namespace-2\"\n    # alertmanagerConfigNamespaceSelector:\n    #   matchExpressions:\n    #     - key: alertmanagerconfig\n    #       operator: In\n    #       values:\n    #         - example-namespace\n    #         - example-namespace-2\n\n    ## Example which selects all namespaces with label \"alertmanagerconfig\" set to \"enabled\"\n    # alertmanagerConfigNamespaceSelector:\n    #   matchLabels:\n    #     alertmanagerconfig: enabled\n\n    ## Define Log Format\n    # Use logfmt (default) or json logging\n    logFormat: logfmt\n\n    ## Log level for Alertmanager to be configured with.\n    ##\n    logLevel: info\n\n    ## Size is the expected size of the alertmanager cluster. The controller will eventually make the size of the\n    ## running cluster equal to the expected size.\n    replicas: 1\n\n    ## Time duration Alertmanager shall retain data for. Default is '120h', and must match the regular expression\n    ## [0-9]+(ms|s|m|h) (milliseconds seconds minutes hours).\n    ##\n    retention: 120h\n\n    ## Storage is the definition of how storage will be used by the Alertmanager instances.\n    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/user-guides/storage.md\n    ##\n    storage: {}\n    # volumeClaimTemplate:\n    #   spec:\n    #     storageClassName: gluster\n    #     accessModes: [\"ReadWriteOnce\"]\n    #     resources:\n    #       requests:\n    #         storage: 50Gi\n    #   selector: {}\n\n\n    ## \tThe external URL the Alertmanager instances will be available under. This is necessary to generate correct URLs. This is necessary if Alertmanager is not served from root of a DNS name.\tstring\tfalse\n    ##\n    externalUrl:\n\n    ## \tThe route prefix Alertmanager registers HTTP handlers for. This is useful, if using ExternalURL and a proxy is rewriting HTTP routes of a request, and the actual ExternalURL is still true,\n    ## but the server serves requests under a different route prefix. For example for use with kubectl proxy.\n    ##\n    routePrefix: /\n\n    ## If set to true all actions on the underlying managed objects are not going to be performed, except for delete actions.\n    ##\n    paused: false\n\n    ## Define which Nodes the Pods are scheduled on.\n    ## ref: https://kubernetes.io/docs/user-guide/node-selection/\n    ##\n    nodeSelector: {}\n\n    ## Define resources requests and limits for single Pods.\n    ## ref: https://kubernetes.io/docs/user-guide/compute-resources/\n    ##\n    resources: {}\n    # requests:\n    #   memory: 400Mi\n\n    ## Pod anti-affinity can prevent the scheduler from placing Prometheus replicas on the same node.\n    ## The default value \"soft\" means that the scheduler should *prefer* to not schedule two replica pods onto the same node but no guarantee is provided.\n    ## The value \"hard\" means that the scheduler is *required* to not schedule two replica pods onto the same node.\n    ## The value \"\" will disable pod anti-affinity so that no anti-affinity rules will be configured.\n    ##\n    podAntiAffinity: \"\"\n\n    ## If anti-affinity is enabled sets the topologyKey to use for anti-affinity.\n    ## This can be changed to, for example, failure-domain.beta.kubernetes.io/zone\n    ##\n    podAntiAffinityTopologyKey: kubernetes.io/hostname\n\n    ## Assign custom affinity rules to the alertmanager instance\n    ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/\n    ##\n    affinity: {}\n    # nodeAffinity:\n    #   requiredDuringSchedulingIgnoredDuringExecution:\n    #     nodeSelectorTerms:\n    #     - matchExpressions:\n    #       - key: kubernetes.io/e2e-az-name\n    #         operator: In\n    #         values:\n    #         - e2e-az1\n    #         - e2e-az2\n\n    ## If specified, the pod's tolerations.\n    ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/\n    ##\n    tolerations: []\n    # - key: \"key\"\n    #   operator: \"Equal\"\n    #   value: \"value\"\n    #   effect: \"NoSchedule\"\n\n    ## If specified, the pod's topology spread constraints.\n    ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/\n    ##\n    topologySpreadConstraints: []\n    # - maxSkew: 1\n    #   topologyKey: topology.kubernetes.io/zone\n    #   whenUnsatisfiable: DoNotSchedule\n    #   labelSelector:\n    #     matchLabels:\n    #       app: alertmanager\n\n    ## SecurityContext holds pod-level security attributes and common container settings.\n    ## This defaults to non root user with uid 1000 and gid 2000.\t*v1.PodSecurityContext\tfalse\n    ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/\n    ##\n    securityContext:\n      runAsGroup: 2000\n      runAsNonRoot: true\n      runAsUser: 1000\n      fsGroup: 2000\n\n    ## ListenLocal makes the Alertmanager server listen on loopback, so that it does not bind against the Pod IP.\n    ## Note this is only for the Alertmanager UI, not the gossip communication.\n    ##\n    listenLocal: false\n\n    ## Containers allows injecting additional containers. This is meant to allow adding an authentication proxy to an Alertmanager pod.\n    ##\n    containers: []\n\n    # Additional volumes on the output StatefulSet definition.\n    volumes: []\n\n    # Additional VolumeMounts on the output StatefulSet definition.\n    volumeMounts: []\n\n    ## InitContainers allows injecting additional initContainers. This is meant to allow doing some changes\n    ## (permissions, dir tree) on mounted volumes before starting prometheus\n    initContainers: []\n\n    ## Priority class assigned to the Pods\n    ##\n    priorityClassName: \"\"\n\n    ## AdditionalPeers allows injecting a set of additional Alertmanagers to peer with to form a highly available cluster.\n    ##\n    additionalPeers: []\n\n    ## PortName to use for Alert Manager.\n    ##\n    portName: \"web\"\n\n    ## ClusterAdvertiseAddress is the explicit address to advertise in cluster. Needs to be provided for non RFC1918 [1] (public) addresses. [1] RFC1918: https://tools.ietf.org/html/rfc1918\n    ##\n    clusterAdvertiseAddress: false\n\n    ## ForceEnableClusterMode ensures Alertmanager does not deactivate the cluster mode when running with a single replica.\n    ## Use case is e.g. spanning an Alertmanager cluster across Kubernetes clusters with a single replica in each.\n    forceEnableClusterMode: false\n\n\n## Using default values from https://github.com/grafana/helm-charts/blob/main/charts/grafana/values.yaml\n##\ngrafana:\n  enabled: false\n  namespaceOverride: \"\"\n\n  ## ForceDeployDatasources Create datasource configmap even if grafana deployment has been disabled\n  ##\n  forceDeployDatasources: false\n\n  ## ForceDeployDashboard Create dashboard configmap even if grafana deployment has been disabled\n  ##\n  forceDeployDashboards: false\n\n  ## Deploy default dashboards.\n  ##\n  defaultDashboardsEnabled: true\n\n  adminPassword: prom-operator\n\n  ingress:\n    ## If true, Grafana Ingress will be created\n    ##\n    enabled: false\n\n    ## Annotations for Grafana Ingress\n    ##\n    annotations: {}\n      # kubernetes.io/ingress.class: nginx\n      # kubernetes.io/tls-acme: \"true\"\n\n    ## Labels to be added to the Ingress\n    ##\n    labels: {}\n\n    ## Hostnames.\n    ## Must be provided if Ingress is enable.\n    ##\n    # hosts:\n    #   - grafana.domain.com\n    hosts: []\n\n    ## Path for grafana ingress\n    path: /\n\n    ## TLS configuration for grafana Ingress\n    ## Secret must be manually created in the namespace\n    ##\n    tls: []\n    # - secretName: grafana-general-tls\n    #   hosts:\n    #   - grafana.example.com\n\n  sidecar:\n    dashboards:\n      enabled: true\n      label: grafana_dashboard\n\n      ## Annotations for Grafana dashboard configmaps\n      ##\n      annotations: {}\n      multicluster: false\n    datasources:\n      enabled: true\n      defaultDatasourceEnabled: true\n\n      ## URL of prometheus datasource\n      ##\n      # url: http://prometheus-stack-prometheus:9090/\n\n      # If not defined, will use prometheus.prometheusSpec.scrapeInterval or its default\n      # defaultDatasourceScrapeInterval: 15s\n\n      ## Annotations for Grafana datasource configmaps\n      ##\n      annotations: {}\n\n      ## Create datasource for each Pod of Prometheus StatefulSet;\n      ## this uses headless service `prometheus-operated` which is\n      ## created by Prometheus Operator\n      ## ref: https://git.io/fjaBS\n      createPrometheusReplicasDatasources: false\n      label: grafana_datasource\n\n  extraConfigmapMounts: []\n  # - name: certs-configmap\n  #   mountPath: /etc/grafana/ssl/\n  #   configMap: certs-configmap\n  #   readOnly: true\n\n  ## Configure additional grafana datasources (passed through tpl)\n  ## ref: http://docs.grafana.org/administration/provisioning/#datasources\n  additionalDataSources: []\n  # - name: prometheus-sample\n  #   access: proxy\n  #   basicAuth: true\n  #   basicAuthPassword: pass\n  #   basicAuthUser: daco\n  #   editable: false\n  #   jsonData:\n  #       tlsSkipVerify: true\n  #   orgId: 1\n  #   type: prometheus\n  #   url: https://{{ printf \"%s-prometheus.svc\" .Release.Name }}:9090\n  #   version: 1\n\n  ## Passed to grafana subchart and used by servicemonitor below\n  ##\n  service:\n    portName: service\n\n  ## If true, create a serviceMonitor for grafana\n  ##\n  serviceMonitor:\n    ## Scrape interval. If not set, the Prometheus default scrape interval is used.\n    ##\n    interval: \"\"\n    selfMonitor: true\n\n    # Path to use for scraping metrics. Might be different if server.root_url is set\n    # in grafana.ini\n    path: \"/metrics\"\n\n    ## \tmetric relabel configs to apply to samples before ingestion.\n    ##\n    metricRelabelings: []\n    # - action: keep\n    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'\n    #   sourceLabels: [__name__]\n\n    # \trelabel configs to apply to samples before ingestion.\n    ##\n    relabelings: []\n    # - sourceLabels: [__meta_kubernetes_pod_node_name]\n    #   separator: ;\n    #   regex: ^(.*)$\n    #   targetLabel: nodename\n    #   replacement: $1\n    #   action: replace\n\n## Component scraping the kube api server\n##\nkubeApiServer:\n  enabled: false\n  tlsConfig:\n    serverName: kubernetes\n    insecureSkipVerify: false\n  serviceMonitor:\n    ## Scrape interval. If not set, the Prometheus default scrape interval is used.\n    ##\n    interval: \"\"\n    ## proxyUrl: URL of a proxy that should be used for scraping.\n    ##\n    proxyUrl: \"\"\n\n    jobLabel: component\n    selector:\n      matchLabels:\n        component: apiserver\n        provider: kubernetes\n\n    ## \tmetric relabel configs to apply to samples before ingestion.\n    ##\n    metricRelabelings: []\n    # - action: keep\n    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'\n    #   sourceLabels: [__name__]\n    relabelings: []\n    # - sourceLabels:\n    #     - __meta_kubernetes_namespace\n    #     - __meta_kubernetes_service_name\n    #     - __meta_kubernetes_endpoint_port_name\n    #   action: keep\n    #   regex: default;kubernetes;https\n    # - targetLabel: __address__\n    #   replacement: kubernetes.default.svc:443\n\n## Component scraping the kubelet and kubelet-hosted cAdvisor\n##\nkubelet:\n  enabled: false\n  namespace: kube-system\n\n  serviceMonitor:\n    ## Scrape interval. If not set, the Prometheus default scrape interval is used.\n    ##\n    interval: \"\"\n\n    ## proxyUrl: URL of a proxy that should be used for scraping.\n    ##\n    proxyUrl: \"\"\n\n    ## Enable scraping the kubelet over https. For requirements to enable this see\n    ## https://github.com/prometheus-operator/prometheus-operator/issues/926\n    ##\n    https: true\n\n    ## Enable scraping /metrics/cadvisor from kubelet's service\n    ##\n    cAdvisor: true\n\n    ## Enable scraping /metrics/probes from kubelet's service\n    ##\n    probes: true\n\n    ## Enable scraping /metrics/resource from kubelet's service\n    ## This is disabled by default because container metrics are already exposed by cAdvisor\n    ##\n    resource: false\n    # From kubernetes 1.18, /metrics/resource/v1alpha1 renamed to /metrics/resource\n    resourcePath: \"/metrics/resource/v1alpha1\"\n    ## Metric relabellings to apply to samples before ingestion\n    ##\n    cAdvisorMetricRelabelings: []\n    # - sourceLabels: [__name__, image]\n    #   separator: ;\n    #   regex: container_([a-z_]+);\n    #   replacement: $1\n    #   action: drop\n    # - sourceLabels: [__name__]\n    #   separator: ;\n    #   regex: container_(network_tcp_usage_total|network_udp_usage_total|tasks_state|cpu_load_average_10s)\n    #   replacement: $1\n    #   action: drop\n\n    ## Metric relabellings to apply to samples before ingestion\n    ##\n    probesMetricRelabelings: []\n    # - sourceLabels: [__name__, image]\n    #   separator: ;\n    #   regex: container_([a-z_]+);\n    #   replacement: $1\n    #   action: drop\n    # - sourceLabels: [__name__]\n    #   separator: ;\n    #   regex: container_(network_tcp_usage_total|network_udp_usage_total|tasks_state|cpu_load_average_10s)\n    #   replacement: $1\n    #   action: drop\n\n    # \trelabel configs to apply to samples before ingestion.\n    #   metrics_path is required to match upstream rules and charts\n    ##\n    cAdvisorRelabelings:\n      - sourceLabels: [__metrics_path__]\n        targetLabel: metrics_path\n    # - sourceLabels: [__meta_kubernetes_pod_node_name]\n    #   separator: ;\n    #   regex: ^(.*)$\n    #   targetLabel: nodename\n    #   replacement: $1\n    #   action: replace\n\n    probesRelabelings:\n      - sourceLabels: [__metrics_path__]\n        targetLabel: metrics_path\n    # - sourceLabels: [__meta_kubernetes_pod_node_name]\n    #   separator: ;\n    #   regex: ^(.*)$\n    #   targetLabel: nodename\n    #   replacement: $1\n    #   action: replace\n\n    resourceRelabelings:\n      - sourceLabels: [__metrics_path__]\n        targetLabel: metrics_path\n    # - sourceLabels: [__meta_kubernetes_pod_node_name]\n    #   separator: ;\n    #   regex: ^(.*)$\n    #   targetLabel: nodename\n    #   replacement: $1\n    #   action: replace\n\n    metricRelabelings: []\n    # - sourceLabels: [__name__, image]\n    #   separator: ;\n    #   regex: container_([a-z_]+);\n    #   replacement: $1\n    #   action: drop\n    # - sourceLabels: [__name__]\n    #   separator: ;\n    #   regex: container_(network_tcp_usage_total|network_udp_usage_total|tasks_state|cpu_load_average_10s)\n    #   replacement: $1\n    #   action: drop\n\n    # \trelabel configs to apply to samples before ingestion.\n    #   metrics_path is required to match upstream rules and charts\n    ##\n    relabelings:\n      - sourceLabels: [__metrics_path__]\n        targetLabel: metrics_path\n    # - sourceLabels: [__meta_kubernetes_pod_node_name]\n    #   separator: ;\n    #   regex: ^(.*)$\n    #   targetLabel: nodename\n    #   replacement: $1\n    #   action: replace\n\n## Component scraping the kube controller manager\n##\nkubeControllerManager:\n  enabled: false\n\n  ## If your kube controller manager is not deployed as a pod, specify IPs it can be found on\n  ##\n  endpoints: []\n\n  ## If using kubeControllerManager.endpoints only the port and targetPort are used\n  ##\n  service:\n    enabled: true\n    port: 10252\n    targetPort: 10252\n    # selector:\n    #   component: kube-controller-manager\n\n  serviceMonitor:\n    enabled: true\n    ## Scrape interval. If not set, the Prometheus default scrape interval is used.\n    ##\n    interval: \"\"\n\n    ## proxyUrl: URL of a proxy that should be used for scraping.\n    ##\n    proxyUrl: \"\"\n\n    ## Enable scraping kube-controller-manager over https.\n    ## Requires proper certs (not self-signed) and delegated authentication/authorization checks\n    ##\n    https: false\n\n    # Skip TLS certificate validation when scraping\n    insecureSkipVerify: null\n\n    # Name of the server to use when validating TLS certificate\n    serverName: null\n\n    ## \tmetric relabel configs to apply to samples before ingestion.\n    ##\n    metricRelabelings: []\n    # - action: keep\n    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'\n    #   sourceLabels: [__name__]\n\n    # \trelabel configs to apply to samples before ingestion.\n    ##\n    relabelings: []\n    # - sourceLabels: [__meta_kubernetes_pod_node_name]\n    #   separator: ;\n    #   regex: ^(.*)$\n    #   targetLabel: nodename\n    #   replacement: $1\n    #   action: replace\n\n## Component scraping coreDns. Use either this or kubeDns\n##\ncoreDns:\n  enabled: false\n  service:\n    port: 9153\n    targetPort: 9153\n    # selector:\n    #   k8s-app: kube-dns\n  serviceMonitor:\n    ## Scrape interval. If not set, the Prometheus default scrape interval is used.\n    ##\n    interval: \"\"\n\n    ## proxyUrl: URL of a proxy that should be used for scraping.\n    ##\n    proxyUrl: \"\"\n\n    ## \tmetric relabel configs to apply to samples before ingestion.\n    ##\n    metricRelabelings: []\n    # - action: keep\n    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'\n    #   sourceLabels: [__name__]\n\n    # \trelabel configs to apply to samples before ingestion.\n    ##\n    relabelings: []\n    # - sourceLabels: [__meta_kubernetes_pod_node_name]\n    #   separator: ;\n    #   regex: ^(.*)$\n    #   targetLabel: nodename\n    #   replacement: $1\n    #   action: replace\n\n## Component scraping kubeDns. Use either this or coreDns\n##\nkubeDns:\n  enabled: false\n  service:\n    dnsmasq:\n      port: 10054\n      targetPort: 10054\n    skydns:\n      port: 10055\n      targetPort: 10055\n    # selector:\n    #   k8s-app: kube-dns\n  serviceMonitor:\n    ## Scrape interval. If not set, the Prometheus default scrape interval is used.\n    ##\n    interval: \"\"\n\n    ## proxyUrl: URL of a proxy that should be used for scraping.\n    ##\n    proxyUrl: \"\"\n\n    ## \tmetric relabel configs to apply to samples before ingestion.\n    ##\n    metricRelabelings: []\n    # - action: keep\n    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'\n    #   sourceLabels: [__name__]\n\n    # \trelabel configs to apply to samples before ingestion.\n    ##\n    relabelings: []\n    # - sourceLabels: [__meta_kubernetes_pod_node_name]\n    #   separator: ;\n    #   regex: ^(.*)$\n    #   targetLabel: nodename\n    #   replacement: $1\n    #   action: replace\n    dnsmasqMetricRelabelings: []\n    # - action: keep\n    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'\n    #   sourceLabels: [__name__]\n\n    # \trelabel configs to apply to samples before ingestion.\n    ##\n    dnsmasqRelabelings: []\n    # - sourceLabels: [__meta_kubernetes_pod_node_name]\n    #   separator: ;\n    #   regex: ^(.*)$\n    #   targetLabel: nodename\n    #   replacement: $1\n    #   action: replace\n\n## Component scraping etcd\n##\nkubeEtcd:\n  enabled: false\n\n  ## If your etcd is not deployed as a pod, specify IPs it can be found on\n  ##\n  endpoints: []\n\n  ## Etcd service. If using kubeEtcd.endpoints only the port and targetPort are used\n  ##\n  service:\n    enabled: true\n    port: 2379\n    targetPort: 2379\n    # selector:\n    #   component: etcd\n\n  ## Configure secure access to the etcd cluster by loading a secret into prometheus and\n  ## specifying security configuration below. For example, with a secret named etcd-client-cert\n  ##\n  ## serviceMonitor:\n  ##   scheme: https\n  ##   insecureSkipVerify: false\n  ##   serverName: localhost\n  ##   caFile: /etc/prometheus/secrets/etcd-client-cert/etcd-ca\n  ##   certFile: /etc/prometheus/secrets/etcd-client-cert/etcd-client\n  ##   keyFile: /etc/prometheus/secrets/etcd-client-cert/etcd-client-key\n  ##\n  serviceMonitor:\n    enabled: true\n    ## Scrape interval. If not set, the Prometheus default scrape interval is used.\n    ##\n    interval: \"\"\n    ## proxyUrl: URL of a proxy that should be used for scraping.\n    ##\n    proxyUrl: \"\"\n    scheme: http\n    insecureSkipVerify: false\n    serverName: \"\"\n    caFile: \"\"\n    certFile: \"\"\n    keyFile: \"\"\n\n    ## \tmetric relabel configs to apply to samples before ingestion.\n    ##\n    metricRelabelings: []\n    # - action: keep\n    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'\n    #   sourceLabels: [__name__]\n\n    # \trelabel configs to apply to samples before ingestion.\n    ##\n    relabelings: []\n    # - sourceLabels: [__meta_kubernetes_pod_node_name]\n    #   separator: ;\n    #   regex: ^(.*)$\n    #   targetLabel: nodename\n    #   replacement: $1\n    #   action: replace\n\n\n## Component scraping kube scheduler\n##\nkubeScheduler:\n  enabled: false\n\n  ## If your kube scheduler is not deployed as a pod, specify IPs it can be found on\n  ##\n  endpoints: []\n\n  ## If using kubeScheduler.endpoints only the port and targetPort are used\n  ##\n  service:\n    enabled: true\n    port: 10251\n    targetPort: 10251\n    # selector:\n    #   component: kube-scheduler\n\n  serviceMonitor:\n    enabled: true\n    ## Scrape interval. If not set, the Prometheus default scrape interval is used.\n    ##\n    interval: \"\"\n    ## proxyUrl: URL of a proxy that should be used for scraping.\n    ##\n    proxyUrl: \"\"\n    ## Enable scraping kube-scheduler over https.\n    ## Requires proper certs (not self-signed) and delegated authentication/authorization checks\n    ##\n    https: false\n\n    ## Skip TLS certificate validation when scraping\n    insecureSkipVerify: null\n\n    ## Name of the server to use when validating TLS certificate\n    serverName: null\n\n    ## \tmetric relabel configs to apply to samples before ingestion.\n    ##\n    metricRelabelings: []\n    # - action: keep\n    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'\n    #   sourceLabels: [__name__]\n\n    # \trelabel configs to apply to samples before ingestion.\n    ##\n    relabelings: []\n    # - sourceLabels: [__meta_kubernetes_pod_node_name]\n    #   separator: ;\n    #   regex: ^(.*)$\n    #   targetLabel: nodename\n    #   replacement: $1\n    #   action: replace\n\n\n## Component scraping kube proxy\n##\nkubeProxy:\n  enabled: false\n\n  ## If your kube proxy is not deployed as a pod, specify IPs it can be found on\n  ##\n  endpoints: []\n\n  service:\n    enabled: false\n    port: 10249\n    targetPort: 10249\n    # selector:\n    #   k8s-app: kube-proxy\n\n  serviceMonitor:\n    enabled: false\n    ## Scrape interval. If not set, the Prometheus default scrape interval is used.\n    ##\n    interval: \"\"\n\n    ## proxyUrl: URL of a proxy that should be used for scraping.\n    ##\n    proxyUrl: \"\"\n\n    ## Enable scraping kube-proxy over https.\n    ## Requires proper certs (not self-signed) and delegated authentication/authorization checks\n    ##\n    https: false\n\n    ## \tmetric relabel configs to apply to samples before ingestion.\n    ##\n    metricRelabelings: []\n    # - action: keep\n    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'\n    #   sourceLabels: [__name__]\n\n    # \trelabel configs to apply to samples before ingestion.\n    ##\n    relabelings: []\n    # - action: keep\n    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'\n    #   sourceLabels: [__name__]\n\n\n## Component scraping kube state metrics\n##\nkubeStateMetrics:\n  enabled: false\n  serviceMonitor:\n    ## Scrape interval. If not set, the Prometheus default scrape interval is used.\n    ##\n    interval: \"\"\n    ## proxyUrl: URL of a proxy that should be used for scraping.\n    ##\n    proxyUrl: \"\"\n    ## Override serviceMonitor selector\n    ##\n    selectorOverride: {}\n    ## Override namespace selector\n    ##\n    namespaceOverride: \"\"\n\n    ## \tmetric relabel configs to apply to samples before ingestion.\n    ##\n    metricRelabelings: []\n    # - action: keep\n    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'\n    #   sourceLabels: [__name__]\n\n    # \trelabel configs to apply to samples before ingestion.\n    ##\n    relabelings: []\n    # - sourceLabels: [__meta_kubernetes_pod_node_name]\n    #   separator: ;\n    #   regex: ^(.*)$\n    #   targetLabel: nodename\n    #   replacement: $1\n    #   action: replace\n\n    # Enable self metrics configuration for Service Monitor\n    selfMonitor:\n      enabled: false\n\n## Configuration for kube-state-metrics subchart\n##\nkube-state-metrics:\n  namespaceOverride: \"\"\n  rbac:\n    create: false\n  podSecurityPolicy:\n    enabled: false\n\n## Deploy node exporter as a daemonset to all nodes\n##\nnodeExporter:\n  enabled: false\n\n  ## Use the value configured in prometheus-node-exporter.podLabels\n  ##\n  jobLabel: jobLabel\n\n  serviceMonitor:\n    ## Scrape interval. If not set, the Prometheus default scrape interval is used.\n    ##\n    interval: \"\"\n\n    ## proxyUrl: URL of a proxy that should be used for scraping.\n    ##\n    proxyUrl: \"\"\n\n    ## How long until a scrape request times out. If not set, the Prometheus default scape timeout is used.\n    ##\n    scrapeTimeout: \"\"\n\n    ## \tmetric relabel configs to apply to samples before ingestion.\n    ##\n    metricRelabelings: []\n    # - sourceLabels: [__name__]\n    #   separator: ;\n    #   regex: ^node_mountstats_nfs_(event|operations|transport)_.+\n    #   replacement: $1\n    #   action: drop\n\n    ## \trelabel configs to apply to samples before ingestion.\n    ##\n    relabelings: []\n    # - sourceLabels: [__meta_kubernetes_pod_node_name]\n    #   separator: ;\n    #   regex: ^(.*)$\n    #   targetLabel: nodename\n    #   replacement: $1\n    #   action: replace\n\n## Configuration for prometheus-node-exporter subchart\n##\nprometheus-node-exporter:\n  namespaceOverride: \"\"\n  podLabels:\n    ## Add the 'node-exporter' label to be used by serviceMonitor to match standard common usage in rules and grafana dashboards\n    ##\n    jobLabel: node-exporter\n  extraArgs:\n    - --collector.filesystem.ignored-mount-points=^/(dev|proc|sys|var/lib/docker/.+|var/lib/kubelet/.+)($|/)\n    - --collector.filesystem.ignored-fs-types=^(autofs|binfmt_misc|bpf|cgroup2?|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|iso9660|mqueue|nsfs|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|selinuxfs|squashfs|sysfs|tracefs)$\n\n## Manages Prometheus and Alertmanager components\n##\nprometheusOperator:\n  enabled: true\n\n  ## Prometheus-Operator v0.39.0 and later support TLS natively.\n  ##\n  tls:\n    enabled: true\n    # Value must match version names from https://golang.org/pkg/crypto/tls/#pkg-constants\n    tlsMinVersion: VersionTLS13\n    # The default webhook port is 10250 in order to work out-of-the-box in GKE private clusters and avoid adding firewall rules.\n    internalPort: 10250\n\n  ## Admission webhook support for PrometheusRules resources added in Prometheus Operator 0.30 can be enabled to prevent incorrectly formatted\n  ## rules from making their way into prometheus and potentially preventing the container from starting\n  admissionWebhooks:\n    failurePolicy: Fail\n    enabled: true\n    ## A PEM encoded CA bundle which will be used to validate the webhook's server certificate.\n    ## If unspecified, system trust roots on the apiserver are used.\n    caBundle: \"\"\n    ## If enabled, generate a self-signed certificate, then patch the webhook configurations with the generated data.\n    ## On chart upgrades (or if the secret exists) the cert will not be re-generated. You can use this to provide your own\n    ## certs ahead of time if you wish.\n    ##\n    patch:\n      enabled: true\n      image:\n        repository: jettech/kube-webhook-certgen\n        tag: v1.5.2\n        sha: \"\"\n        pullPolicy: IfNotPresent\n      resources: {}\n      ## Provide a priority class name to the webhook patching job\n      ##\n      priorityClassName: \"\"\n      podAnnotations: {}\n      nodeSelector: {}\n      affinity: {}\n      tolerations: []\n\n      ## SecurityContext holds pod-level security attributes and common container settings.\n      ## This defaults to non root user with uid 2000 and gid 2000.\t*v1.PodSecurityContext\tfalse\n      ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/\n      ##\n      securityContext:\n        runAsGroup: 2000\n        runAsNonRoot: true\n        runAsUser: 2000\n\n    # Use certmanager to generate webhook certs\n    certManager:\n      enabled: false\n      # issuerRef:\n      #   name: \"issuer\"\n      #   kind: \"ClusterIssuer\"\n\n  ## Namespaces to scope the interaction of the Prometheus Operator and the apiserver (allow list).\n  ## This is mutually exclusive with denyNamespaces. Setting this to an empty object will disable the configuration\n  ##\n  namespaces: {}\n    # releaseNamespace: true\n    # additional:\n    # - kube-system\n\n  ## Namespaces not to scope the interaction of the Prometheus Operator (deny list).\n  ##\n  denyNamespaces: []\n\n  ## Filter namespaces to look for prometheus-operator custom resources\n  ##\n  alertmanagerInstanceNamespaces: []\n  prometheusInstanceNamespaces: []\n  thanosRulerInstanceNamespaces: []\n\n  ## The clusterDomain value will be added to the cluster.peer option of the alertmanager.\n  ## Without this specified option cluster.peer will have value alertmanager-monitoring-alertmanager-0.alertmanager-operated:9094 (default value)\n  ## With this specified option cluster.peer will have value alertmanager-monitoring-alertmanager-0.alertmanager-operated.namespace.svc.cluster-domain:9094\n  ##\n  # clusterDomain: \"cluster.local\"\n\n  ## Service account for Alertmanager to use.\n  ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/\n  ##\n  serviceAccount:\n    create: true\n    name: \"\"\n\n  ## Configuration for Prometheus operator service\n  ##\n  service:\n    annotations: {}\n    labels: {}\n    clusterIP: \"\"\n\n  ## Port to expose on each node\n  ## Only used if service.type is 'NodePort'\n  ##\n    nodePort: 30080\n\n    nodePortTls: 30443\n\n  ## Additional ports to open for Prometheus service\n  ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#multi-port-services\n  ##\n    additionalPorts: []\n\n  ## Loadbalancer IP\n  ## Only use if service.type is \"LoadBalancer\"\n  ##\n    loadBalancerIP: \"\"\n    loadBalancerSourceRanges: []\n\n  ## Service type\n  ## NodePort, ClusterIP, LoadBalancer\n  ##\n    type: ClusterIP\n\n    ## List of IP addresses at which the Prometheus server service is available\n    ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips\n    ##\n    externalIPs: []\n\n  ## Labels to add to the operator pod\n  ##\n  podLabels: {}\n\n  ## Annotations to add to the operator pod\n  ##\n  podAnnotations: {}\n\n  ## Assign a PriorityClassName to pods if set\n  # priorityClassName: \"\"\n\n  ## Define Log Format\n  # Use logfmt (default) or json logging\n  # logFormat: logfmt\n\n  ## Decrease log verbosity to errors only\n  # logLevel: error\n\n  ## If true, the operator will create and maintain a service for scraping kubelets\n  ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/helm/prometheus-operator/README.md\n  ##\n  kubeletService:\n    enabled: true\n    namespace: kube-system\n\n  ## Create a servicemonitor for the operator\n  ##\n  serviceMonitor:\n    ## Scrape interval. If not set, the Prometheus default scrape interval is used.\n    ##\n    interval: \"\"\n    ## Scrape timeout. If not set, the Prometheus default scrape timeout is used.\n    scrapeTimeout: \"\"\n    selfMonitor: true\n\n    ## \tmetric relabel configs to apply to samples before ingestion.\n    ##\n    metricRelabelings: []\n    # - action: keep\n    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'\n    #   sourceLabels: [__name__]\n\n    # \trelabel configs to apply to samples before ingestion.\n    ##\n    relabelings: []\n    # - sourceLabels: [__meta_kubernetes_pod_node_name]\n    #   separator: ;\n    #   regex: ^(.*)$\n    #   targetLabel: nodename\n    #   replacement: $1\n    #   action: replace\n\n  ## Resource limits & requests\n  ##\n  resources: {}\n  # limits:\n  #   cpu: 200m\n  #   memory: 200Mi\n  # requests:\n  #   cpu: 100m\n  #   memory: 100Mi\n\n  # Required for use in managed kubernetes clusters (such as AWS EKS) with custom CNI (such as calico),\n  # because control-plane managed by AWS cannot communicate with pods' IP CIDR and admission webhooks are not working\n  ##\n  hostNetwork: false\n\n  ## Define which Nodes the Pods are scheduled on.\n  ## ref: https://kubernetes.io/docs/user-guide/node-selection/\n  ##\n  nodeSelector: {}\n\n  ## Tolerations for use with node taints\n  ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/\n  ##\n  tolerations: []\n  # - key: \"key\"\n  #   operator: \"Equal\"\n  #   value: \"value\"\n  #   effect: \"NoSchedule\"\n\n  ## Assign custom affinity rules to the prometheus operator\n  ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/\n  ##\n  affinity: {}\n    # nodeAffinity:\n    #   requiredDuringSchedulingIgnoredDuringExecution:\n    #     nodeSelectorTerms:\n    #     - matchExpressions:\n    #       - key: kubernetes.io/e2e-az-name\n    #         operator: In\n    #         values:\n    #         - e2e-az1\n    #         - e2e-az2\n  dnsConfig: {}\n    # nameservers:\n    #   - 1.2.3.4\n    # searches:\n    #   - ns1.svc.cluster-domain.example\n    #   - my.dns.search.suffix\n    # options:\n    #   - name: ndots\n    #     value: \"2\"\n  #   - name: edns0\n  securityContext:\n    fsGroup: 65534\n    runAsGroup: 65534\n    runAsNonRoot: true\n    runAsUser: 65534\n\n  ## Prometheus-operator image\n  ##\n  image:\n    repository: quay.io/prometheus-operator/prometheus-operator\n    tag: v0.49.0\n    sha: \"\"\n    pullPolicy: IfNotPresent\n\n  ## Prometheus image to use for prometheuses managed by the operator\n  ##\n  # prometheusDefaultBaseImage: quay.io/prometheus/prometheus\n\n  ## Alertmanager image to use for alertmanagers managed by the operator\n  ##\n  # alertmanagerDefaultBaseImage: quay.io/prometheus/alertmanager\n\n  ## Prometheus-config-reloader image to use for config and rule reloading\n  ##\n  prometheusConfigReloaderImage:\n    repository: quay.io/prometheus-operator/prometheus-config-reloader\n    tag: v0.49.0\n    sha: \"\"\n\n  ## Set the prometheus config reloader side-car CPU limit\n  ##\n  configReloaderCpu: 100m\n\n  ## Set the prometheus config reloader side-car memory limit\n  ##\n  configReloaderMemory: 50Mi\n\n  ## Thanos side-car image when configured\n  ##\n  thanosImage:\n    repository: quay.io/thanos/thanos\n    tag: v0.17.2\n    sha: \"\"\n\n  ## Set a Field Selector to filter watched secrets\n  ##\n  secretFieldSelector: \"\"\n\n## Deploy a Prometheus instance\n##\nprometheus:\n  enabled: true\n\n  ## Annotations for Prometheus\n  ##\n  annotations: {}\n\n  ## Service account for Prometheuses to use.\n  ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/\n  ##\n  serviceAccount:\n    create: true\n    name: \"\"\n    annotations: {}\n\n  # Service for thanos service discovery on sidecar\n  # Enable this can make Thanos Query can use\n  # `--store=dnssrv+_grpc._tcp.${kube-prometheus-stack.fullname}-thanos-discovery.${namespace}.svc.cluster.local` to discovery\n  # Thanos sidecar on prometheus nodes\n  # (Please remember to change ${kube-prometheus-stack.fullname} and ${namespace}. Not just copy and paste!)\n  thanosService:\n    enabled: false\n    annotations: {}\n    labels: {}\n    portName: grpc\n    port: 10901\n    targetPort: \"grpc\"\n    clusterIP: \"None\"\n\n    ## Service type\n    ##\n    type: ClusterIP\n\n    ## Port to expose on each node\n    ##\n    nodePort: 30901\n\n  # Service for external access to sidecar\n  # Enabling this creates a service to expose thanos-sidecar outside the cluster.\n  thanosServiceExternal:\n    enabled: false\n    annotations: {}\n    labels: {}\n    portName: grpc\n    port: 10901\n    targetPort: \"grpc\"\n    loadBalancerIP: \"\"\n    loadBalancerSourceRanges: []\n\n    ## Service type\n    ##\n    type: LoadBalancer\n\n    ## Port to expose on each node\n    ##\n    nodePort: 30901\n\n  ## Configuration for Prometheus service\n  ##\n  service:\n    annotations: {}\n    labels: {}\n    clusterIP: \"\"\n\n    ## Port for Prometheus Service to listen on\n    ##\n    port: 9090\n\n    ## To be used with a proxy extraContainer port\n    targetPort: 9090\n\n    ## List of IP addresses at which the Prometheus server service is available\n    ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips\n    ##\n    externalIPs: []\n\n    ## Port to expose on each node\n    ## Only used if service.type is 'NodePort'\n    ##\n    nodePort: 30090\n\n    ## Loadbalancer IP\n    ## Only use if service.type is \"LoadBalancer\"\n    loadBalancerIP: \"\"\n    loadBalancerSourceRanges: []\n    ## Service type\n    ##\n    type: ClusterIP\n\n    sessionAffinity: \"\"\n\n  ## Configuration for creating a separate Service for each statefulset Prometheus replica\n  ##\n  servicePerReplica:\n    enabled: false\n    annotations: {}\n\n    ## Port for Prometheus Service per replica to listen on\n    ##\n    port: 9090\n\n    ## To be used with a proxy extraContainer port\n    targetPort: 9090\n\n    ## Port to expose on each node\n    ## Only used if servicePerReplica.type is 'NodePort'\n    ##\n    nodePort: 30091\n\n    ## Loadbalancer source IP ranges\n    ## Only used if servicePerReplica.type is \"LoadBalancer\"\n    loadBalancerSourceRanges: []\n    ## Service type\n    ##\n    type: ClusterIP\n\n  ## Configure pod disruption budgets for Prometheus\n  ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget\n  ## This configuration is immutable once created and will require the PDB to be deleted to be changed\n  ## https://github.com/kubernetes/kubernetes/issues/45398\n  ##\n  podDisruptionBudget:\n    enabled: false\n    minAvailable: 1\n    maxUnavailable: \"\"\n\n  # Ingress exposes thanos sidecar outside the cluster\n  thanosIngress:\n    enabled: false\n\n    # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName\n    # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress\n    # ingressClassName: nginx\n\n    annotations: {}\n    labels: {}\n    servicePort: 10901\n\n    ## Port to expose on each node\n    ## Only used if service.type is 'NodePort'\n    ##\n    nodePort: 30901\n\n    ## Hosts must be provided if Ingress is enabled.\n    ##\n    hosts: []\n      # - thanos-gateway.domain.com\n\n    ## Paths to use for ingress rules\n    ##\n    paths: []\n    # - /\n\n    ## For Kubernetes >= 1.18 you should specify the pathType (determines how Ingress paths should be matched)\n    ## See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#better-path-matching-with-path-types\n    # pathType: ImplementationSpecific\n\n    ## TLS configuration for Thanos Ingress\n    ## Secret must be manually created in the namespace\n    ##\n    tls: []\n    # - secretName: thanos-gateway-tls\n    #   hosts:\n    #   - thanos-gateway.domain.com\n\n  ingress:\n    enabled: false\n\n    # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName\n    # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress\n    # ingressClassName: nginx\n\n    annotations: {}\n    labels: {}\n\n    ## Hostnames.\n    ## Must be provided if Ingress is enabled.\n    ##\n    # hosts:\n    #   - prometheus.domain.com\n    hosts: []\n\n    ## Paths to use for ingress rules - one path should match the prometheusSpec.routePrefix\n    ##\n    paths: []\n    # - /\n\n    ## For Kubernetes >= 1.18 you should specify the pathType (determines how Ingress paths should be matched)\n    ## See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#better-path-matching-with-path-types\n    # pathType: ImplementationSpecific\n\n    ## TLS configuration for Prometheus Ingress\n    ## Secret must be manually created in the namespace\n    ##\n    tls: []\n      # - secretName: prometheus-general-tls\n      #   hosts:\n      #     - prometheus.example.com\n\n  ## Configuration for creating an Ingress that will map to each Prometheus replica service\n  ## prometheus.servicePerReplica must be enabled\n  ##\n  ingressPerReplica:\n    enabled: false\n\n    # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName\n    # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress\n    # ingressClassName: nginx\n\n    annotations: {}\n    labels: {}\n\n    ## Final form of the hostname for each per replica ingress is\n    ## {{ ingressPerReplica.hostPrefix }}-{{ $replicaNumber }}.{{ ingressPerReplica.hostDomain }}\n    ##\n    ## Prefix for the per replica ingress that will have `-$replicaNumber`\n    ## appended to the end\n    hostPrefix: \"\"\n    ## Domain that will be used for the per replica ingress\n    hostDomain: \"\"\n\n    ## Paths to use for ingress rules\n    ##\n    paths: []\n    # - /\n\n    ## For Kubernetes >= 1.18 you should specify the pathType (determines how Ingress paths should be matched)\n    ## See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#better-path-matching-with-path-types\n    # pathType: ImplementationSpecific\n\n    ## Secret name containing the TLS certificate for Prometheus per replica ingress\n    ## Secret must be manually created in the namespace\n    tlsSecretName: \"\"\n\n    ## Separated secret for each per replica Ingress. Can be used together with cert-manager\n    ##\n    tlsSecretPerReplica:\n      enabled: false\n      ## Final form of the secret for each per replica ingress is\n      ## {{ tlsSecretPerReplica.prefix }}-{{ $replicaNumber }}\n      ##\n      prefix: \"prometheus\"\n\n  ## Configure additional options for default pod security policy for Prometheus\n  ## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/\n  podSecurityPolicy:\n    allowedCapabilities: []\n    allowedHostPaths: []\n    volumes: []\n\n  serviceMonitor:\n    ## Scrape interval. If not set, the Prometheus default scrape interval is used.\n    ##\n    interval: \"\"\n    selfMonitor: true\n\n    ## scheme: HTTP scheme to use for scraping. Can be used with `tlsConfig` for example if using istio mTLS.\n    scheme: \"\"\n\n    ## tlsConfig: TLS configuration to use when scraping the endpoint. For example if using istio mTLS.\n    ## Of type: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#tlsconfig\n    tlsConfig: {}\n\n    bearerTokenFile:\n\n    ## \tmetric relabel configs to apply to samples before ingestion.\n    ##\n    metricRelabelings: []\n    # - action: keep\n    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'\n    #   sourceLabels: [__name__]\n\n    # \trelabel configs to apply to samples before ingestion.\n    ##\n    relabelings: []\n    # - sourceLabels: [__meta_kubernetes_pod_node_name]\n    #   separator: ;\n    #   regex: ^(.*)$\n    #   targetLabel: nodename\n    #   replacement: $1\n    #   action: replace\n\n  ## Settings affecting prometheusSpec\n  ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#prometheusspec\n  ##\n  prometheusSpec:\n    ## If true, pass --storage.tsdb.max-block-duration=2h to prometheus. This is already done if using Thanos\n    ##\n    disableCompaction: false\n    ## APIServerConfig\n    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#apiserverconfig\n    ##\n    apiserverConfig: {}\n\n    ## Interval between consecutive scrapes.\n    ## Defaults to 30s.\n    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/release-0.44/pkg/prometheus/promcfg.go#L180-L183\n    ##\n    scrapeInterval: \"\"\n\n    ## Number of seconds to wait for target to respond before erroring\n    ##\n    scrapeTimeout: \"\"\n\n    ## Interval between consecutive evaluations.\n    ##\n    evaluationInterval: \"\"\n\n    ## ListenLocal makes the Prometheus server listen on loopback, so that it does not bind against the Pod IP.\n    ##\n    listenLocal: false\n\n    ## EnableAdminAPI enables Prometheus the administrative HTTP API which includes functionality such as deleting time series.\n    ## This is disabled by default.\n    ## ref: https://prometheus.io/docs/prometheus/latest/querying/api/#tsdb-admin-apis\n    ##\n    enableAdminAPI: false\n\n    # EnableFeatures API enables access to Prometheus disabled features.\n    # ref: https://prometheus.io/docs/prometheus/latest/disabled_features/\n    enableFeatures: []\n    # - exemplar-storage\n\n    ## Image of Prometheus.\n    ##\n    image:\n      repository: quay.io/prometheus/prometheus\n      tag: v2.28.1\n      sha: \"\"\n\n    ## Tolerations for use with node taints\n    ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/\n    ##\n    tolerations: []\n    #  - key: \"key\"\n    #    operator: \"Equal\"\n    #    value: \"value\"\n    #    effect: \"NoSchedule\"\n\n    ## If specified, the pod's topology spread constraints.\n    ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/\n    ##\n    topologySpreadConstraints: []\n    # - maxSkew: 1\n    #   topologyKey: topology.kubernetes.io/zone\n    #   whenUnsatisfiable: DoNotSchedule\n    #   labelSelector:\n    #     matchLabels:\n    #       app: prometheus\n\n    ## Alertmanagers to which alerts will be sent\n    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#alertmanagerendpoints\n    ##\n    ## Default configuration will connect to the alertmanager deployed as part of this release\n    ##\n    alertingEndpoints: []\n    # - name: \"\"\n    #   namespace: \"\"\n    #   port: http\n    #   scheme: http\n    #   pathPrefix: \"\"\n    #   tlsConfig: {}\n    #   bearerTokenFile: \"\"\n    #   apiVersion: v2\n\n    ## External labels to add to any time series or alerts when communicating with external systems\n    ##\n    externalLabels: {}\n\n    ## Name of the external label used to denote replica name\n    ##\n    replicaExternalLabelName: \"\"\n\n    ## If true, the Operator won't add the external label used to denote replica name\n    ##\n    replicaExternalLabelNameClear: false\n\n    ## Name of the external label used to denote Prometheus instance name\n    ##\n    prometheusExternalLabelName: \"\"\n\n    ## If true, the Operator won't add the external label used to denote Prometheus instance name\n    ##\n    prometheusExternalLabelNameClear: false\n\n    ## External URL at which Prometheus will be reachable.\n    ##\n    externalUrl: \"\"\n\n    ## Define which Nodes the Pods are scheduled on.\n    ## ref: https://kubernetes.io/docs/user-guide/node-selection/\n    ##\n    nodeSelector: {}\n\n    ## Secrets is a list of Secrets in the same namespace as the Prometheus object, which shall be mounted into the Prometheus Pods.\n    ## The Secrets are mounted into /etc/prometheus/secrets/. Secrets changes after initial creation of a Prometheus object are not\n    ## reflected in the running Pods. To change the secrets mounted into the Prometheus Pods, the object must be deleted and recreated\n    ## with the new list of secrets.\n    ##\n    secrets: []\n\n    ## ConfigMaps is a list of ConfigMaps in the same namespace as the Prometheus object, which shall be mounted into the Prometheus Pods.\n    ## The ConfigMaps are mounted into /etc/prometheus/configmaps/.\n    ##\n    configMaps: []\n\n    ## QuerySpec defines the query command line flags when starting Prometheus.\n    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#queryspec\n    ##\n    query: {}\n\n    ## Namespaces to be selected for PrometheusRules discovery.\n    ## If nil, select own namespace. Namespaces to be selected for ServiceMonitor discovery.\n    ## See https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#namespaceselector for usage\n    ##\n    ruleNamespaceSelector: {}\n\n    ## If true, a nil or {} value for prometheus.prometheusSpec.ruleSelector will cause the\n    ## prometheus resource to be created with selectors based on values in the helm deployment,\n    ## which will also match the PrometheusRule resources created\n    ##\n    ruleSelectorNilUsesHelmValues: true\n\n    ## PrometheusRules to be selected for target discovery.\n    ## If {}, select all PrometheusRules\n    ##\n    ruleSelector: {}\n    ## Example which select all PrometheusRules resources\n    ## with label \"prometheus\" with values any of \"example-rules\" or \"example-rules-2\"\n    # ruleSelector:\n    #   matchExpressions:\n    #     - key: prometheus\n    #       operator: In\n    #       values:\n    #         - example-rules\n    #         - example-rules-2\n    #\n    ## Example which select all PrometheusRules resources with label \"role\" set to \"example-rules\"\n    # ruleSelector:\n    #   matchLabels:\n    #     role: example-rules\n\n    ## If true, a nil or {} value for prometheus.prometheusSpec.serviceMonitorSelector will cause the\n    ## prometheus resource to be created with selectors based on values in the helm deployment,\n    ## which will also match the servicemonitors created\n    ##\n    serviceMonitorSelectorNilUsesHelmValues: false\n\n    ## ServiceMonitors to be selected for target discovery.\n    ## If {}, select all ServiceMonitors\n    ##\n    serviceMonitorSelector: {}\n    ## Example which selects ServiceMonitors with label \"prometheus\" set to \"somelabel\"\n    # serviceMonitorSelector:\n    #   matchLabels:\n    #     prometheus: somelabel\n\n    ## Namespaces to be selected for ServiceMonitor discovery.\n    ##\n    serviceMonitorNamespaceSelector: {}\n    ## Example which selects ServiceMonitors in namespaces with label \"prometheus\" set to \"somelabel\"\n    # serviceMonitorNamespaceSelector:\n    #   matchLabels:\n    #     prometheus: somelabel\n\n    ## If true, a nil or {} value for prometheus.prometheusSpec.podMonitorSelector will cause the\n    ## prometheus resource to be created with selectors based on values in the helm deployment,\n    ## which will also match the podmonitors created\n    ##\n    podMonitorSelectorNilUsesHelmValues: true\n\n    ## PodMonitors to be selected for target discovery.\n    ## If {}, select all PodMonitors\n    ##\n    podMonitorSelector: {}\n    ## Example which selects PodMonitors with label \"prometheus\" set to \"somelabel\"\n    # podMonitorSelector:\n    #   matchLabels:\n    #     prometheus: somelabel\n\n    ## Namespaces to be selected for PodMonitor discovery.\n    ## See https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#namespaceselector for usage\n    ##\n    podMonitorNamespaceSelector: {}\n\n    ## If true, a nil or {} value for prometheus.prometheusSpec.probeSelector will cause the\n    ## prometheus resource to be created with selectors based on values in the helm deployment,\n    ## which will also match the probes created\n    ##\n    probeSelectorNilUsesHelmValues: true\n\n    ## Probes to be selected for target discovery.\n    ## If {}, select all Probes\n    ##\n    probeSelector: {}\n    ## Example which selects Probes with label \"prometheus\" set to \"somelabel\"\n    # probeSelector:\n    #   matchLabels:\n    #     prometheus: somelabel\n\n    ## Namespaces to be selected for Probe discovery.\n    ## See https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#namespaceselector for usage\n    ##\n    probeNamespaceSelector: {}\n\n    ## How long to retain metrics\n    ##\n    retention: 10d\n\n    ## Maximum size of metrics\n    ##\n    retentionSize: \"\"\n\n    ## Enable compression of the write-ahead log using Snappy.\n    ##\n    walCompression: false\n\n    ## If true, the Operator won't process any Prometheus configuration changes\n    ##\n    paused: false\n\n    ## Number of replicas of each shard to deploy for a Prometheus deployment.\n    ## Number of replicas multiplied by shards is the total number of Pods created.\n    ##\n    replicas: 1\n\n    ## EXPERIMENTAL: Number of shards to distribute targets onto.\n    ## Number of replicas multiplied by shards is the total number of Pods created.\n    ## Note that scaling down shards will not reshard data onto remaining instances, it must be manually moved.\n    ## Increasing shards will not reshard data either but it will continue to be available from the same instances.\n    ## To query globally use Thanos sidecar and Thanos querier or remote write data to a central location.\n    ## Sharding is done on the content of the `__address__` target meta-label.\n    ##\n    shards: 1\n\n    ## Log level for Prometheus be configured in\n    ##\n    logLevel: info\n\n    ## Log format for Prometheus be configured in\n    ##\n    logFormat: logfmt\n\n    ## Prefix used to register routes, overriding externalUrl route.\n    ## Useful for proxies that rewrite URLs.\n    ##\n    routePrefix: /\n\n    ## Standard object's metadata. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#metadata\n    ## Metadata Labels and Annotations gets propagated to the prometheus pods.\n    ##\n    podMetadata: {}\n    # labels:\n    #   app: prometheus\n    #   k8s-app: prometheus\n\n    ## Pod anti-affinity can prevent the scheduler from placing Prometheus replicas on the same node.\n    ## The default value \"soft\" means that the scheduler should *prefer* to not schedule two replica pods onto the same node but no guarantee is provided.\n    ## The value \"hard\" means that the scheduler is *required* to not schedule two replica pods onto the same node.\n    ## The value \"\" will disable pod anti-affinity so that no anti-affinity rules will be configured.\n    podAntiAffinity: \"\"\n\n    ## If anti-affinity is enabled sets the topologyKey to use for anti-affinity.\n    ## This can be changed to, for example, failure-domain.beta.kubernetes.io/zone\n    ##\n    podAntiAffinityTopologyKey: kubernetes.io/hostname\n\n    ## Assign custom affinity rules to the prometheus instance\n    ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/\n    ##\n    affinity: {}\n    # nodeAffinity:\n    #   requiredDuringSchedulingIgnoredDuringExecution:\n    #     nodeSelectorTerms:\n    #     - matchExpressions:\n    #       - key: kubernetes.io/e2e-az-name\n    #         operator: In\n    #         values:\n    #         - e2e-az1\n    #         - e2e-az2\n\n    ## The remote_read spec configuration for Prometheus.\n    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#remotereadspec\n    remoteRead: []\n    # - url: http://remote1/read\n    ## additionalRemoteRead is appended to remoteRead\n    additionalRemoteRead: []\n\n    ## The remote_write spec configuration for Prometheus.\n    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#remotewritespec\n    remoteWrite: []\n    # - url: http://remote1/push\n    ## additionalRemoteWrite is appended to remoteWrite\n    additionalRemoteWrite: []\n\n    ## Enable/Disable Grafana dashboards provisioning for prometheus remote write feature\n    remoteWriteDashboards: false\n\n    ## Resource limits & requests\n    ##\n    resources: {}\n    # requests:\n    #   memory: 400Mi\n\n    ## Prometheus StorageSpec for persistent data\n    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/user-guides/storage.md\n    ##\n    storageSpec: {}\n    ## Using PersistentVolumeClaim\n    ##\n    #  volumeClaimTemplate:\n    #    spec:\n    #      storageClassName: gluster\n    #      accessModes: [\"ReadWriteOnce\"]\n    #      resources:\n    #        requests:\n    #          storage: 50Gi\n    #    selector: {}\n\n    ## Using tmpfs volume\n    ##\n    #  emptyDir:\n    #    medium: Memory\n\n    # Additional volumes on the output StatefulSet definition.\n    volumes: []\n\n    # Additional VolumeMounts on the output StatefulSet definition.\n    volumeMounts: []\n\n    ## AdditionalScrapeConfigs allows specifying additional Prometheus scrape configurations. Scrape configurations\n    ## are appended to the configurations generated by the Prometheus Operator. Job configurations must have the form\n    ## as specified in the official Prometheus documentation:\n    ## https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config. As scrape configs are\n    ## appended, the user is responsible to make sure it is valid. Note that using this feature may expose the possibility\n    ## to break upgrades of Prometheus. It is advised to review Prometheus release notes to ensure that no incompatible\n    ## scrape configs are going to break Prometheus after the upgrade.\n    ##\n    ## The scrape configuration example below will find master nodes, provided they have the name .*mst.*, relabel the\n    ## port to 2379 and allow etcd scraping provided it is running on all Kubernetes master nodes\n    ##\n    additionalScrapeConfigs: []\n    # - job_name: kube-etcd\n    #   kubernetes_sd_configs:\n    #     - role: node\n    #   scheme: https\n    #   tls_config:\n    #     ca_file:   /etc/prometheus/secrets/etcd-client-cert/etcd-ca\n    #     cert_file: /etc/prometheus/secrets/etcd-client-cert/etcd-client\n    #     key_file:  /etc/prometheus/secrets/etcd-client-cert/etcd-client-key\n    #   relabel_configs:\n    #   - action: labelmap\n    #     regex: __meta_kubernetes_node_label_(.+)\n    #   - source_labels: [__address__]\n    #     action: replace\n    #     targetLabel: __address__\n    #     regex: ([^:;]+):(\\d+)\n    #     replacement: ${1}:2379\n    #   - source_labels: [__meta_kubernetes_node_name]\n    #     action: keep\n    #     regex: .*mst.*\n    #   - source_labels: [__meta_kubernetes_node_name]\n    #     action: replace\n    #     targetLabel: node\n    #     regex: (.*)\n    #     replacement: ${1}\n    #   metric_relabel_configs:\n    #   - regex: (kubernetes_io_hostname|failure_domain_beta_kubernetes_io_region|beta_kubernetes_io_os|beta_kubernetes_io_arch|beta_kubernetes_io_instance_type|failure_domain_beta_kubernetes_io_zone)\n    #     action: labeldrop\n\n    ## If additional scrape configurations are already deployed in a single secret file you can use this section.\n    ## Expected values are the secret name and key\n    ## Cannot be used with additionalScrapeConfigs\n    additionalScrapeConfigsSecret: {}\n      # enabled: false\n      # name:\n      # key:\n\n    ## additionalPrometheusSecretsAnnotations allows to add annotations to the kubernetes secret. This can be useful\n    ## when deploying via spinnaker to disable versioning on the secret, strategy.spinnaker.io/versioned: 'false'\n    additionalPrometheusSecretsAnnotations: {}\n\n    ## AdditionalAlertManagerConfigs allows for manual configuration of alertmanager jobs in the form as specified\n    ## in the official Prometheus documentation https://prometheus.io/docs/prometheus/latest/configuration/configuration/#<alertmanager_config>.\n    ## AlertManager configurations specified are appended to the configurations generated by the Prometheus Operator.\n    ## As AlertManager configs are appended, the user is responsible to make sure it is valid. Note that using this\n    ## feature may expose the possibility to break upgrades of Prometheus. It is advised to review Prometheus release\n    ## notes to ensure that no incompatible AlertManager configs are going to break Prometheus after the upgrade.\n    ##\n    additionalAlertManagerConfigs: []\n    # - consul_sd_configs:\n    #   - server: consul.dev.test:8500\n    #     scheme: http\n    #     datacenter: dev\n    #     tag_separator: ','\n    #     services:\n    #       - metrics-prometheus-alertmanager\n\n    ## If additional alertmanager configurations are already deployed in a single secret, or you want to manage\n    ## them separately from the helm deployment, you can use this section.\n    ## Expected values are the secret name and key\n    ## Cannot be used with additionalAlertManagerConfigs\n    additionalAlertManagerConfigsSecret: {}\n      # name:\n      # key:\n\n    ## AdditionalAlertRelabelConfigs allows specifying Prometheus alert relabel configurations. Alert relabel configurations specified are appended\n    ## to the configurations generated by the Prometheus Operator. Alert relabel configurations specified must have the form as specified in the\n    ## official Prometheus documentation: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#alert_relabel_configs.\n    ## As alert relabel configs are appended, the user is responsible to make sure it is valid. Note that using this feature may expose the\n    ## possibility to break upgrades of Prometheus. It is advised to review Prometheus release notes to ensure that no incompatible alert relabel\n    ## configs are going to break Prometheus after the upgrade.\n    ##\n    additionalAlertRelabelConfigs: []\n    # - separator: ;\n    #   regex: prometheus_replica\n    #   replacement: $1\n    #   action: labeldrop\n\n    ## SecurityContext holds pod-level security attributes and common container settings.\n    ## This defaults to non root user with uid 1000 and gid 2000.\n    ## https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md\n    ##\n    securityContext:\n      runAsGroup: 2000\n      runAsNonRoot: true\n      runAsUser: 1000\n      fsGroup: 2000\n\n    ## \tPriority class assigned to the Pods\n    ##\n    priorityClassName: \"\"\n\n    ## Thanos configuration allows configuring various aspects of a Prometheus server in a Thanos environment.\n    ## This section is experimental, it may change significantly without deprecation notice in any release.\n    ## This is experimental and may change significantly without backward compatibility in any release.\n    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#thanosspec\n    ##\n    thanos: {}\n\n    ## Containers allows injecting additional containers. This is meant to allow adding an authentication proxy to a Prometheus pod.\n    ##  if using proxy extraContainer  update targetPort with proxy container port\n    containers: []\n\n    ## InitContainers allows injecting additional initContainers. This is meant to allow doing some changes\n    ## (permissions, dir tree) on mounted volumes before starting prometheus\n    initContainers: []\n\n    ## PortName to use for Prometheus.\n    ##\n    portName: \"web\"\n\n    ## ArbitraryFSAccessThroughSMs configures whether configuration based on a service monitor can access arbitrary files\n    ## on the file system of the Prometheus container e.g. bearer token files.\n    arbitraryFSAccessThroughSMs: false\n\n    ## OverrideHonorLabels if set to true overrides all user configured honor_labels. If HonorLabels is set in ServiceMonitor\n    ## or PodMonitor to true, this overrides honor_labels to false.\n    overrideHonorLabels: false\n\n    ## OverrideHonorTimestamps allows to globally enforce honoring timestamps in all scrape configs.\n    overrideHonorTimestamps: false\n\n    ## IgnoreNamespaceSelectors if set to true will ignore NamespaceSelector settings from the podmonitor and servicemonitor\n    ## configs, and they will only discover endpoints within their current namespace. Defaults to false.\n    ignoreNamespaceSelectors: false\n\n    ## EnforcedNamespaceLabel enforces adding a namespace label of origin for each alert and metric that is user created.\n    ## The label value will always be the namespace of the object that is being created.\n    ## Disabled by default\n    enforcedNamespaceLabel: \"\"\n\n    ## PrometheusRulesExcludedFromEnforce - list of prometheus rules to be excluded from enforcing of adding namespace labels.\n    ## Works only if enforcedNamespaceLabel set to true. Make sure both ruleNamespace and ruleName are set for each pair\n    prometheusRulesExcludedFromEnforce: []\n\n    ## QueryLogFile specifies the file to which PromQL queries are logged. Note that this location must be writable,\n    ## and can be persisted using an attached volume. Alternatively, the location can be set to a stdout location such\n    ## as /dev/stdout to log querie information to the default Prometheus log stream. This is only available in versions\n    ## of Prometheus >= 2.16.0. For more details, see the Prometheus docs (https://prometheus.io/docs/guides/query-log/)\n    queryLogFile: false\n\n    ## EnforcedSampleLimit defines global limit on number of scraped samples that will be accepted. This overrides any SampleLimit\n    ## set per ServiceMonitor or/and PodMonitor. It is meant to be used by admins to enforce the SampleLimit to keep overall\n    ## number of samples/series under the desired limit. Note that if SampleLimit is lower that value will be taken instead.\n    enforcedSampleLimit: false\n\n    ## AllowOverlappingBlocks enables vertical compaction and vertical query merge in Prometheus. This is still experimental\n    ## in Prometheus so it may change in any upcoming release.\n    allowOverlappingBlocks: false\n\n  additionalRulesForClusterRole: []\n  #  - apiGroups: [ \"\" ]\n  #    resources:\n  #      - nodes/proxy\n  #    verbs: [ \"get\", \"list\", \"watch\" ]\n\n  additionalServiceMonitors: []\n  ## Name of the ServiceMonitor to create\n  ##\n  # - name: \"\"\n\n    ## Additional labels to set used for the ServiceMonitorSelector. Together with standard labels from\n    ## the chart\n    ##\n    # additionalLabels: {}\n\n    ## Service label for use in assembling a job name of the form <label value>-<port>\n    ## If no label is specified, the service name is used.\n    ##\n    # jobLabel: \"\"\n\n    ## labels to transfer from the kubernetes service to the target\n    ##\n    # targetLabels: []\n\n    ## labels to transfer from the kubernetes pods to the target\n    ##\n    # podTargetLabels: []\n\n    ## Label selector for services to which this ServiceMonitor applies\n    ##\n    # selector: {}\n\n    ## Namespaces from which services are selected\n    ##\n    # namespaceSelector:\n      ## Match any namespace\n      ##\n      # any: false\n\n      ## Explicit list of namespace names to select\n      ##\n      # matchNames: []\n\n    ## Endpoints of the selected service to be monitored\n    ##\n    # endpoints: []\n      ## Name of the endpoint's service port\n      ## Mutually exclusive with targetPort\n      # - port: \"\"\n\n      ## Name or number of the endpoint's target port\n      ## Mutually exclusive with port\n      # - targetPort: \"\"\n\n      ## File containing bearer token to be used when scraping targets\n      ##\n      #   bearerTokenFile: \"\"\n\n      ## Interval at which metrics should be scraped\n      ##\n      #   interval: 30s\n\n      ## HTTP path to scrape for metrics\n      ##\n      #   path: /metrics\n\n      ## HTTP scheme to use for scraping\n      ##\n      #   scheme: http\n\n      ## TLS configuration to use when scraping the endpoint\n      ##\n      #   tlsConfig:\n\n          ## Path to the CA file\n          ##\n          # caFile: \"\"\n\n          ## Path to client certificate file\n          ##\n          # certFile: \"\"\n\n          ## Skip certificate verification\n          ##\n          # insecureSkipVerify: false\n\n          ## Path to client key file\n          ##\n          # keyFile: \"\"\n\n          ## Server name used to verify host name\n          ##\n          # serverName: \"\"\n\n  additionalPodMonitors: []\n  ## Name of the PodMonitor to create\n  ##\n  # - name: \"\"\n\n    ## Additional labels to set used for the PodMonitorSelector. Together with standard labels from\n    ## the chart\n    ##\n    # additionalLabels: {}\n\n    ## Pod label for use in assembling a job name of the form <label value>-<port>\n    ## If no label is specified, the pod endpoint name is used.\n    ##\n    # jobLabel: \"\"\n\n    ## Label selector for pods to which this PodMonitor applies\n    ##\n    # selector: {}\n\n    ## PodTargetLabels transfers labels on the Kubernetes Pod onto the target.\n    ##\n    # podTargetLabels: {}\n\n    ## SampleLimit defines per-scrape limit on number of scraped samples that will be accepted.\n    ##\n    # sampleLimit: 0\n\n    ## Namespaces from which pods are selected\n    ##\n    # namespaceSelector:\n      ## Match any namespace\n      ##\n      # any: false\n\n      ## Explicit list of namespace names to select\n      ##\n      # matchNames: []\n\n    ## Endpoints of the selected pods to be monitored\n    ## https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#podmetricsendpoint\n    ##\n    # podMetricsEndpoints: []\n"
  },
  {
    "path": "charts/charts/tapp/.helmignore",
    "content": "# Patterns to ignore when building packages.\n# This supports shell glob matching, relative path matching, and\n# negation (prefixed with !). Only one pattern per line.\n.DS_Store\n# Common VCS dirs\n.git/\n.gitignore\n.bzr/\n.bzrignore\n.hg/\n.hgignore\n.svn/\n# Common backup files\n*.swp\n*.bak\n*.tmp\n*.orig\n*~\n# Various IDEs\n.project\n.idea/\n*.tmproj\n.vscode/\n"
  },
  {
    "path": "charts/charts/tapp/Chart.yaml",
    "content": "apiVersion: v2\nname: tapp\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.1.0\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\"\n"
  },
  {
    "path": "charts/charts/tapp/templates/_helpers.tpl",
    "content": "{{/*\nExpand the name of the chart.\n*/}}\n{{- define \"tapp.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 \"tapp.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 \"tapp.chart\" -}}\n{{- printf \"%s-%s\" .Chart.Name .Chart.Version | replace \"+\" \"_\" | trunc 63 | trimSuffix \"-\" }}\n{{- end }}\n\n{{/*\nCommon labels\n*/}}\n{{- define \"tapp.labels\" -}}\nhelm.sh/chart: {{ include \"tapp.chart\" . }}\n{{ include \"tapp.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 \"tapp.selectorLabels\" -}}\napp.kubernetes.io/name: {{ include \"tapp.name\" . }}\napp.kubernetes.io/instance: {{ .Release.Name }}\n{{- end }}\n\n{{/*\nCreate the name of the service account to use\n*/}}\n{{- define \"tapp.serviceAccountName\" -}}\n{{- if .Values.serviceAccount.create }}\n{{- default (include \"tapp.fullname\" .) .Values.serviceAccount.name }}\n{{- else }}\n{{- default \"default\" .Values.serviceAccount.name }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/tapp/templates/configmap.yaml",
    "content": "apiVersion: v1\ndata:\n  ca.pem: |\n    -----BEGIN CERTIFICATE-----\n    MIIDrzCCApegAwIBAgIIXKC0USDrkqAwDQYJKoZIhvcNAQELBQAwZjELMAkGA1UE\n    BhMCQ04xLTARBgNVBAoTCnRlbmNlbnR5dW4wGAYDVQQKExFjbG91ZC50ZW5jZW50\n    LmNvbTEoMCYGA1UEAxMfdGFwcC1jb250cm9sbGVyLmt1YmUtc3lzdGVtLnN2YzAe\n    Fw0yMTExMDgxNTE0NTVaFw00MTExMDgxNTE0NTVaMGYxCzAJBgNVBAYTAkNOMS0w\n    EQYDVQQKEwp0ZW5jZW50eXVuMBgGA1UEChMRY2xvdWQudGVuY2VudC5jb20xKDAm\n    BgNVBAMTH3RhcHAtY29udHJvbGxlci5rdWJlLXN5c3RlbS5zdmMwggEiMA0GCSqG\n    SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAjK4kj9CvGtrVkrm5kyqUyPYG/1aYoV77\n    PKug8EfZqQjlEAWsxdMltTigLk1Q5D1Ta/A6uc9mERMYjBRHTfvXfkWu6wQeISsy\n    3BT7O3DeG00DYsiZ63CckTtq+LgFrbN/ARB496nuwKCog2CesXmFMf+pBgihYYMH\n    iodKjRi2bxa5/+KZilX4ghuMgR7tGBv+Q0GzTYCA1zVS09xaQzGe37wkrk3AJF8N\n    KkTWbHsr57q7j9/0gMqdMtMFkJSiNLV9HrfZDOacDrYAuGuPi3VkQi9eKsCkI/AV\n    b88wL1i3Yi8MRbETc5+PbK6/2wJZoIquU+cYGfrKYA3OdPkzum9TAgMBAAGjYTBf\n    MA4GA1UdDwEB/wQEAwIChDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEw\n    DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWpTX6J/rjMHNfkdOhIvcPlSXFoEw\n    DQYJKoZIhvcNAQELBQADggEBALFwMm94ncjIWAQ47qiwvAY9Z9cLeVhbMqndJGIV\n    fcOddl382NWjDOCTAv4a107SFAZHCjo46zAgG5znAF3InnWkUVn6vi1aHklokOHW\n    vnF/aN0s9LwHyy4N3hXh1NHTJwB5HUfKKJke+Kf2Kiif5lD6tDuOQ1C14CslD6if\n    rBNBF730SoqyuEEaVXfDFQFc/DVFLbXXElEypUrJHhrjs1zKPFzoHiDs/Jz1X5jt\n    qYPF3WB8juPLBYWN9y4cPRmBIIZNSwKGFUJnT6mHv5XY+olZQq8MgS6lh3WQIu/Z\n    CUjiy0Y+vpeN58ri2WqbTicEP7ExEFWZedK5Qq4iYlXC+L0=\n    -----END CERTIFICATE-----\n  server.crt: |\n    -----BEGIN CERTIFICATE-----\n    MIIDuTCCAqGgAwIBAgIIH9lNVRc2YsAwDQYJKoZIhvcNAQELBQAwZjELMAkGA1UE\n    BhMCQ04xLTARBgNVBAoTCnRlbmNlbnR5dW4wGAYDVQQKExFjbG91ZC50ZW5jZW50\n    LmNvbTEoMCYGA1UEAxMfdGFwcC1jb250cm9sbGVyLmt1YmUtc3lzdGVtLnN2YzAe\n    Fw0yMTExMDgxNTE0NTVaFw00MTExMDgxNTE0NTVaMGYxCzAJBgNVBAYTAkNOMS0w\n    EQYDVQQKEwp0ZW5jZW50eXVuMBgGA1UEChMRY2xvdWQudGVuY2VudC5jb20xKDAm\n    BgNVBAMTH3RhcHAtY29udHJvbGxlci5rdWJlLXN5c3RlbS5zdmMwggEiMA0GCSqG\n    SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDbl84mM1nv2zx8gtyKohEsEWLTjNFCgLwp\n    z7NzKAMdbWAVKlBPIernJ5qH+t8Z6iOFB/43IyuHFdNzYFACpuolShlnN9sZ0W9W\n    q47uvfJd/gpsBpxoYORo5uT7un9DGO3Rq9TBPnDtoE4GR1iMZqeGEMWh671nozjV\n    uGg/nV0LRCDijcBIdyhNSIhQDaPqTr+6UQB7uFi7OEN+V9T2/r1VSZMOUY4C6Q3Y\n    r0ijbRWeYiZeIlFdu3486YZ0M3SsJ4JMvHap5aeHTATyZBisyV4rqog3nqhq1Zcc\n    t3bk7dBMa5ADOsoI6g4ThtjsXe0asjYWL7cAdLywRxogOxz1ib91AgMBAAGjazBp\n    MA4GA1UdDwEB/wQEAwIChDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEw\n    DAYDVR0TAQH/BAIwADAqBgNVHREEIzAhgh90YXBwLWNvbnRyb2xsZXIua3ViZS1z\n    eXN0ZW0uc3ZjMA0GCSqGSIb3DQEBCwUAA4IBAQBmr52hjKdNsgoUDvANZOc0y2z7\n    45i+4PD5YA9IlfeJKdUqo7dTKIYVSWaLqixaUc+dK/Uw+3tKvGIKMtYFn8pVHlau\n    Abfr2IBhH/w+YhfET/G166lsIR5cN185gjavbxb0oZSE8yFJZH1SRTEoI0twxjbF\n    fOSYJdoioJqnFFewAWrfUsRRTIH6FAZK5s+rhJ8xhMYz3+KW1EbrGPT4eDeUwgnw\n    vSmc9uM0lhgXY16L77TwPiuOhl7s+aU1vQHVBrMeY5BzwHddCfvKPq32jXojiAhA\n    ZPR8fKWYMEisIA4z6IfMVxc44Yxxwm/qN7TPR64mwcw61WAS0427jzG0/12i\n    -----END CERTIFICATE-----\n  server.key: |\n    -----BEGIN RSA PRIVATE KEY-----\n    MIIEogIBAAKCAQEA25fOJjNZ79s8fILciqIRLBFi04zRQoC8Kc+zcygDHW1gFSpQ\n    TyHq5yeah/rfGeojhQf+NyMrhxXTc2BQAqbqJUoZZzfbGdFvVquO7r3yXf4KbAac\n    aGDkaObk+7p/Qxjt0avUwT5w7aBOBkdYjGanhhDFoeu9Z6M41bhoP51dC0Qg4o3A\n    SHcoTUiIUA2j6k6/ulEAe7hYuzhDflfU9v69VUmTDlGOAukN2K9Io20VnmImXiJR\n    Xbt+POmGdDN0rCeCTLx2qeWnh0wE8mQYrMleK6qIN56oatWXHLd25O3QTGuQAzrK\n    COoOE4bY7F3tGrI2Fi+3AHS8sEcaIDsc9Ym/dQIDAQABAoIBAEuzpLTUpR+kI9EE\n    yATe5C6d+8TUWdukR7neSY3ccF53s1T4lmEBX1q683IHUVw8tGwLGl9lt37FTnUK\n    8epIIpYiWmmT/uuCoPBvCkJRpzkx9+PPz6HILVXgq3YAkBjQgkPzCdBot0OkLOHL\n    PMKCLSRxqcAtZclRoqlC/mVX2ZilC3MbKHZSglmoTkXxM+ARJqJHc/vANFFlZDNJ\n    wGqSPYvCTTediTPewMG6csxt3SUrD7KlBBVNKVe8NEbXvbMAdViSu2AbJr8UVxt2\n    5wmlQrgnJ0MCojQo6uiB4gUSVhw1eaZ+LghOl7Dm8pzV1TpLz85lAiJHrT9Yr+eH\n    tmhleMECgYEA8d4x0lTImYj6CGiloFymY6hFutBo8SSBrXxfyAbnsqvJlDRqgdtA\n    f40i6kEjNR9/KMuxe+9tkH/rtyEd+NpYw+zKTjn++mm4/YWRHc5amKPMKs/sn/Yj\n    iVOCIOFdOauzDb7kzQxr7ArSl62SjQxqZxyPSNmFjX8BBGzc37gJ9DECgYEA6Gxt\n    SxwFNYikTF40srcg7J1M4vxV603byj85fXY34JzsowmY5mgtZIj+YtDTZOLSwToN\n    IsW1YluEN6Xj55dQwyUO4epH1zri8awBX93fxV4PEmdYagdoPkn21wGChk4Zpo9w\n    dnLQjeM8ne9TUrqoXqBf/DdX+m9yiIDZCIntgoUCgYB9LhG9GVJlXGaD+Z1XPPyE\n    8a99O6ZEwC85mfh8r041xAFlaieBo/dizKo4cZQGR5HpjFsEmOus8PgPZN19UYzF\n    goVGLXARLKyo0ftEYOu0unnN4qVGOP81cPoViG5Wjc3zHEyQ74/fr85E4HnL9JQR\n    X8+s1Z/wlr3xC2LZiwfj0QKBgD+RCAM20qXljSnlyfvm4fZUvyaFZOpKDQavbAXI\n    Q1gHEyE0CsFZVLDeVtSn0GkTMBjwy47rC8SuyuZ9VGuOkuQMSpm2/Zb73/3A0U9q\n    2zybkPuzkBbPl88RY5VCMHSS/6jyKgv7Mtbbg0Seo+dIbawTqKzOZh10RZrXwoP3\n    VSIRAoGAIVXkFnJXxhYOgVY5+3WbeREfh0uWyVD76Rksk+pTmpHMWZFu/UVafazi\n    eH/5ziBAhidJ00g8MC5SubbiRYWvjLlk2tUa5t/Ni0DrwG9yuxJ9GpB1I9MSljlf\n    aQ0pkqMK2yWHJUoz/FfToQtGeVD8ZjnX+F8KIB975hOuKBtiSJw=\n    -----END RSA PRIVATE KEY-----\nkind: ConfigMap\nmetadata:\n  name: tapp-controller-certs\n#  namespace: {{ .Release.Namespace }}\n  namespace: kube-system"
  },
  {
    "path": "charts/charts/tapp/templates/deployment.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: {{ include \"tapp.fullname\" . }}\n  labels:\n    {{- include \"tapp.labels\" . | nindent 4 }}\n  namespace: kube-system\nspec:\n  {{- if not .Values.autoscaling.enabled }}\n  replicas: {{ .Values.replicaCount }}\n  {{- end }}\n  selector:\n    matchLabels:\n      {{- include \"tapp.selectorLabels\" . | nindent 6 }}\n  template:\n    metadata:\n      {{- with .Values.podAnnotations }}\n      annotations:\n        {{- toYaml . | nindent 8 }}\n      {{- end }}\n      labels:\n        {{- include \"tapp.selectorLabels\" . | nindent 8 }}\n    spec:\n      {{- with .Values.imagePullSecrets }}\n      imagePullSecrets:\n        {{- toYaml . | nindent 8 }}\n      {{- end }}\n      serviceAccountName: {{ include \"tapp.serviceAccountName\" . }}\n      securityContext:\n        {{- toYaml .Values.podSecurityContext | nindent 8 }}\n      volumes:\n        - configMap:\n            defaultMode: 420\n            name: tapp-controller-certs\n          name: tapp-controller-certs\n      containers:\n        - name: {{ .Chart.Name }}\n          securityContext:\n            {{- toYaml .Values.securityContext | nindent 12 }}\n          image: \"{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}\"\n          args:\n            - \"--v=3\"\n            - \"--register-admission=true\"\n            - \"--tlsCAFile=/etc/tapp/certs/ca.pem\"\n            - \"--tlsCertFile=/etc/tapp/certs/server.crt\"\n            - \"--tlsKeyFile=/etc/tapp/certs/server.key\"\n          imagePullPolicy: {{ .Values.image.pullPolicy }}\n          resources:\n            {{- if eq .Values.global.env \"production\" }}\n            {{- toYaml .Values.prodResources | nindent 12 }}\n            {{- else }}\n            {{- toYaml .Values.testResources | nindent 12 }}\n            {{- end }}\n          volumeMounts:\n            - mountPath: /etc/tapp/certs\n              name: tapp-controller-certs\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"
  },
  {
    "path": "charts/charts/tapp/templates/hpa.yaml",
    "content": "{{- if .Values.autoscaling.enabled }}\napiVersion: autoscaling/v2beta1\nkind: HorizontalPodAutoscaler\nmetadata:\n  name: {{ include \"tapp.fullname\" . }}\n  labels:\n    {{- include \"tapp.labels\" . | nindent 4 }}\n  namespace: kube-system\nspec:\n  scaleTargetRef:\n    apiVersion: apps/v1\n    kind: Deployment\n    name: {{ include \"tapp.fullname\" . }}\n  minReplicas: {{ .Values.autoscaling.minReplicas }}\n  maxReplicas: {{ .Values.autoscaling.maxReplicas }}\n  metrics:\n    {{- if .Values.autoscaling.targetCPUUtilizationPercentage }}\n    - type: Resource\n      resource:\n        name: cpu\n        targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}\n    {{- end }}\n    {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}\n    - type: Resource\n      resource:\n        name: memory\n        targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}\n    {{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/charts/tapp/templates/service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n#  name: {{ include \"tapp.fullname\" . }}\n  name: tapp-controller\n  labels:\n    {{- include \"tapp.labels\" . | nindent 4 }}\n  namespace: kube-system\nspec:\n  type: {{ .Values.service.type }}\n  ports:\n    - port: {{ .Values.service.port }}\n      targetPort: 8443\n      protocol: TCP\n  selector:\n    {{- include \"tapp.selectorLabels\" . | nindent 4 }}\n"
  },
  {
    "path": "charts/charts/tapp/templates/serviceaccount.yaml",
    "content": "{{- if .Values.serviceAccount.create -}}\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: {{ include \"tapp.serviceAccountName\" . }}\n#  namespace: {{ .Release.Namespace }}\n  namespace: kube-system\n  labels:\n    {{- include \"tapp.labels\" . | nindent 4 }}\n  {{- with .Values.serviceAccount.annotations }}\n  annotations:\n    {{- toYaml . | nindent 4 }}\n  {{- end }}\n---\nkind: ClusterRoleBinding\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  name: {{ include \"tapp.serviceAccountName\" . }}-role-binding\nsubjects:\n  - kind: ServiceAccount\n    name: {{ include \"tapp.serviceAccountName\" . }}\n#    namespace: {{ .Release.Namespace }}\n    namespace: kube-system\nroleRef:\n  kind: ClusterRole\n  name: cluster-admin\n  apiGroup: rbac.authorization.k8s.io\n{{- end }}\n"
  },
  {
    "path": "charts/charts/tapp/templates/tests/test-connection.yaml",
    "content": "apiVersion: v1\nkind: Pod\nmetadata:\n  name: \"{{ include \"tapp.fullname\" . }}-test-connection\"\n  labels:\n    {{- include \"tapp.labels\" . | nindent 4 }}\n  annotations:\n    \"helm.sh/hook\": test\nspec:\n  containers:\n    - name: wget\n      image: busybox\n      command: ['wget']\n      args: ['{{ include \"tapp.fullname\" . }}:{{ .Values.service.port }}']\n  restartPolicy: Never\n"
  },
  {
    "path": "charts/charts/tapp/values.yaml",
    "content": "# Default values for tapp.\n# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\n\nreplicaCount: 1\n\nimage:\n  repository: tkestack/tapp-controller\n  pullPolicy: IfNotPresent\n  # Overrides the image tag whose default is the chart appVersion.\n  tag: v1.2.1\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: tapp-controller\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\nservice:\n  type: ClusterIP\n  port: 443\n\nprodResources:\n  limits:\n    cpu: 1\n    memory: 1Gi\n  requests:\n    cpu: 500m\n    memory: 512Mi\n\ntestResources:\n  limits:\n    cpu: 1\n    memory: 1Gi\n  requests:\n    cpu: 100m\n    memory: 50Mi\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": "charts/templates/_helpers.tpl",
    "content": "{{/*\nExpand the name of the chart.\n*/}}\n{{- define \"kstone.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 \"kstone.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 \"kstone.chart\" -}}\n{{- printf \"%s-%s\" .Chart.Name .Chart.Version | replace \"+\" \"_\" | trunc 63 | trimSuffix \"-\" }}\n{{- end }}\n\n{{/*\nCommon labels\n*/}}\n{{- define \"kstone.labels\" -}}\nhelm.sh/chart: {{ include \"kstone.chart\" . }}\n{{ include \"kstone.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 \"kstone.selectorLabels\" -}}\napp.kubernetes.io/name: {{ include \"kstone.name\" . }}\napp.kubernetes.io/instance: {{ .Release.Name }}\n{{- end }}\n\n{{/*\nCreate the name of the service account to use\n*/}}\n{{- define \"kstone.serviceAccountName\" -}}\n{{- if .Values.serviceAccount.create }}\n{{- default (include \"kstone.fullname\" .) .Values.serviceAccount.name }}\n{{- else }}\n{{- default \"default\" .Values.serviceAccount.name }}\n{{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/templates/crd.yaml",
    "content": "{{- if .Values.crd.create -}}\napiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.4.1\n  creationTimestamp: null\n  name: etcdclusters.kstone.tkestack.io\nspec:\n  group: kstone.tkestack.io\n  names:\n    kind: EtcdCluster\n    listKind: EtcdClusterList\n    plural: etcdclusters\n    singular: etcdcluster\n    shortNames:\n      - cluster\n  scope: Namespaced\n  versions:\n    - name: v1alpha2\n      schema:\n        openAPIV3Schema:\n          description: EtcdCluster is the Schema for the etcdclusters 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              x-kubernetes-preserve-unknown-fields: true\n              description: EtcdClusterSpec defines the desired state of EtcdCluster\n              properties:\n                affinity:\n                  description: Affinity is a group of affinity scheduling rules.\n                  properties:\n                    nodeAffinity:\n                      description: Describes node affinity scheduling rules for the\n                        pod.\n                      properties:\n                        preferredDuringSchedulingIgnoredDuringExecution:\n                          description: The scheduler will prefer to schedule pods to\n                            nodes that satisfy the affinity expressions specified by\n                            this field, but it may choose a node that violates one or\n                            more of the expressions. The node that is most preferred\n                            is the one with the greatest sum of weights, i.e. for each\n                            node that meets all of the scheduling requirements (resource\n                            request, requiredDuringScheduling affinity expressions,\n                            etc.), compute a sum by iterating through the elements of\n                            this field and adding \"weight\" to the sum if the node matches\n                            the corresponding matchExpressions; the node(s) with the\n                            highest sum are the most preferred.\n                          items:\n                            description: An empty preferred scheduling term matches\n                              all objects with implicit weight 0 (i.e. it's a no-op).\n                              A null preferred scheduling term matches no objects (i.e.\n                              is also a no-op).\n                            properties:\n                              preference:\n                                description: A node selector term, associated with the\n                                  corresponding weight.\n                                properties:\n                                  matchExpressions:\n                                    description: A list of node selector requirements\n                                      by node's labels.\n                                    items:\n                                      description: A node selector requirement is a\n                                        selector that contains values, a key, and an\n                                        operator that relates the key and values.\n                                      properties:\n                                        key:\n                                          description: The label key that the selector\n                                            applies to.\n                                          type: string\n                                        operator:\n                                          description: Represents a key's relationship\n                                            to a set of values. Valid operators are\n                                            In, NotIn, Exists, DoesNotExist. Gt, and\n                                            Lt.\n                                          type: string\n                                        values:\n                                          description: An array of string values. If\n                                            the operator is In or NotIn, the values\n                                            array must be non-empty. If the operator\n                                            is Exists or DoesNotExist, the values array\n                                            must be empty. If the operator is Gt or\n                                            Lt, the values array must have a single\n                                            element, which will be interpreted as an\n                                            integer. This array is replaced during a\n                                            strategic merge patch.\n                                          items:\n                                            type: string\n                                          type: array\n                                      required:\n                                        - key\n                                        - operator\n                                      type: object\n                                    type: array\n                                  matchFields:\n                                    description: A list of node selector requirements\n                                      by node's fields.\n                                    items:\n                                      description: A node selector requirement is a\n                                        selector that contains values, a key, and an\n                                        operator that relates the key and values.\n                                      properties:\n                                        key:\n                                          description: The label key that the selector\n                                            applies to.\n                                          type: string\n                                        operator:\n                                          description: Represents a key's relationship\n                                            to a set of values. Valid operators are\n                                            In, NotIn, Exists, DoesNotExist. Gt, and\n                                            Lt.\n                                          type: string\n                                        values:\n                                          description: An array of string values. If\n                                            the operator is In or NotIn, the values\n                                            array must be non-empty. If the operator\n                                            is Exists or DoesNotExist, the values array\n                                            must be empty. If the operator is Gt or\n                                            Lt, the values array must have a single\n                                            element, which will be interpreted as an\n                                            integer. This array is replaced during a\n                                            strategic merge patch.\n                                          items:\n                                            type: string\n                                          type: array\n                                      required:\n                                        - key\n                                        - operator\n                                      type: object\n                                    type: array\n                                type: object\n                              weight:\n                                description: Weight associated with matching the corresponding\n                                  nodeSelectorTerm, in the range 1-100.\n                                format: int32\n                                type: integer\n                            required:\n                              - preference\n                              - weight\n                            type: object\n                          type: array\n                        requiredDuringSchedulingIgnoredDuringExecution:\n                          description: If the affinity requirements specified by this\n                            field are not met at scheduling time, the pod will not be\n                            scheduled onto the node. If the affinity requirements specified\n                            by this field cease to be met at some point during pod execution\n                            (e.g. due to an update), the system may or may not try to\n                            eventually evict the pod from its node.\n                          properties:\n                            nodeSelectorTerms:\n                              description: Required. A list of node selector terms.\n                                The terms are ORed.\n                              items:\n                                description: A null or empty node selector term matches\n                                  no objects. The requirements of them are ANDed. The\n                                  TopologySelectorTerm type implements a subset of the\n                                  NodeSelectorTerm.\n                                properties:\n                                  matchExpressions:\n                                    description: A list of node selector requirements\n                                      by node's labels.\n                                    items:\n                                      description: A node selector requirement is a\n                                        selector that contains values, a key, and an\n                                        operator that relates the key and values.\n                                      properties:\n                                        key:\n                                          description: The label key that the selector\n                                            applies to.\n                                          type: string\n                                        operator:\n                                          description: Represents a key's relationship\n                                            to a set of values. Valid operators are\n                                            In, NotIn, Exists, DoesNotExist. Gt, and\n                                            Lt.\n                                          type: string\n                                        values:\n                                          description: An array of string values. If\n                                            the operator is In or NotIn, the values\n                                            array must be non-empty. If the operator\n                                            is Exists or DoesNotExist, the values array\n                                            must be empty. If the operator is Gt or\n                                            Lt, the values array must have a single\n                                            element, which will be interpreted as an\n                                            integer. This array is replaced during a\n                                            strategic merge patch.\n                                          items:\n                                            type: string\n                                          type: array\n                                      required:\n                                        - key\n                                        - operator\n                                      type: object\n                                    type: array\n                                  matchFields:\n                                    description: A list of node selector requirements\n                                      by node's fields.\n                                    items:\n                                      description: A node selector requirement is a\n                                        selector that contains values, a key, and an\n                                        operator that relates the key and values.\n                                      properties:\n                                        key:\n                                          description: The label key that the selector\n                                            applies to.\n                                          type: string\n                                        operator:\n                                          description: Represents a key's relationship\n                                            to a set of values. Valid operators are\n                                            In, NotIn, Exists, DoesNotExist. Gt, and\n                                            Lt.\n                                          type: string\n                                        values:\n                                          description: An array of string values. If\n                                            the operator is In or NotIn, the values\n                                            array must be non-empty. If the operator\n                                            is Exists or DoesNotExist, the values array\n                                            must be empty. If the operator is Gt or\n                                            Lt, the values array must have a single\n                                            element, which will be interpreted as an\n                                            integer. This array is replaced during a\n                                            strategic merge patch.\n                                          items:\n                                            type: string\n                                          type: array\n                                      required:\n                                        - key\n                                        - operator\n                                      type: object\n                                    type: array\n                                type: object\n                              type: array\n                          required:\n                            - nodeSelectorTerms\n                          type: object\n                      type: object\n                    podAffinity:\n                      description: Describes pod affinity scheduling rules (e.g. co-locate\n                        this pod in the same node, zone, etc. as some other pod(s)).\n                      properties:\n                        preferredDuringSchedulingIgnoredDuringExecution:\n                          description: The scheduler will prefer to schedule pods to\n                            nodes that satisfy the affinity expressions specified by\n                            this field, but it may choose a node that violates one or\n                            more of the expressions. The node that is most preferred\n                            is the one with the greatest sum of weights, i.e. for each\n                            node that meets all of the scheduling requirements (resource\n                            request, requiredDuringScheduling affinity expressions,\n                            etc.), compute a sum by iterating through the elements of\n                            this field and adding \"weight\" to the sum if the node has\n                            pods which matches the corresponding podAffinityTerm; the\n                            node(s) with the highest sum are the most preferred.\n                          items:\n                            description: The weights of all of the matched WeightedPodAffinityTerm\n                              fields are added per-node to find the most preferred node(s)\n                            properties:\n                              podAffinityTerm:\n                                description: Required. A pod affinity term, associated\n                                  with the corresponding weight.\n                                properties:\n                                  labelSelector:\n                                    description: A label query over a set of resources,\n                                      in this case pods.\n                                    properties:\n                                      matchExpressions:\n                                        description: matchExpressions is a list of label\n                                          selector requirements. The requirements are\n                                          ANDed.\n                                        items:\n                                          description: A label selector requirement\n                                            is a selector that contains values, a key,\n                                            and an operator that relates the key and\n                                            values.\n                                          properties:\n                                            key:\n                                              description: key is the label key that\n                                                the selector applies to.\n                                              type: string\n                                            operator:\n                                              description: operator represents a key's\n                                                relationship to a set of values. Valid\n                                                operators are In, NotIn, Exists and\n                                                DoesNotExist.\n                                              type: string\n                                            values:\n                                              description: values is an array of string\n                                                values. If the operator is In or NotIn,\n                                                the values array must be non-empty.\n                                                If the operator is Exists or DoesNotExist,\n                                                the values array must be empty. This\n                                                array is replaced during a strategic\n                                                merge patch.\n                                              items:\n                                                type: string\n                                              type: array\n                                          required:\n                                            - key\n                                            - operator\n                                          type: object\n                                        type: array\n                                      matchLabels:\n                                        additionalProperties:\n                                          type: string\n                                        description: matchLabels is a map of {key,value}\n                                          pairs. A single {key,value} in the matchLabels\n                                          map is equivalent to an element of matchExpressions,\n                                          whose key field is \"key\", the operator is\n                                          \"In\", and the values array contains only \"value\".\n                                          The requirements are ANDed.\n                                        type: object\n                                    type: object\n                                  namespaceSelector:\n                                    description: A label query over the set of namespaces\n                                      that the term applies to. The term is applied\n                                      to the union of the namespaces selected by this\n                                      field and the ones listed in the namespaces field.\n                                      null selector and null or empty namespaces list\n                                      means \"this pod's namespace\". An empty selector\n                                      ({}) matches all namespaces. This field is alpha-level\n                                      and is only honored when PodAffinityNamespaceSelector\n                                      feature is enabled.\n                                    properties:\n                                      matchExpressions:\n                                        description: matchExpressions is a list of label\n                                          selector requirements. The requirements are\n                                          ANDed.\n                                        items:\n                                          description: A label selector requirement\n                                            is a selector that contains values, a key,\n                                            and an operator that relates the key and\n                                            values.\n                                          properties:\n                                            key:\n                                              description: key is the label key that\n                                                the selector applies to.\n                                              type: string\n                                            operator:\n                                              description: operator represents a key's\n                                                relationship to a set of values. Valid\n                                                operators are In, NotIn, Exists and\n                                                DoesNotExist.\n                                              type: string\n                                            values:\n                                              description: values is an array of string\n                                                values. If the operator is In or NotIn,\n                                                the values array must be non-empty.\n                                                If the operator is Exists or DoesNotExist,\n                                                the values array must be empty. This\n                                                array is replaced during a strategic\n                                                merge patch.\n                                              items:\n                                                type: string\n                                              type: array\n                                          required:\n                                            - key\n                                            - operator\n                                          type: object\n                                        type: array\n                                      matchLabels:\n                                        additionalProperties:\n                                          type: string\n                                        description: matchLabels is a map of {key,value}\n                                          pairs. A single {key,value} in the matchLabels\n                                          map is equivalent to an element of matchExpressions,\n                                          whose key field is \"key\", the operator is\n                                          \"In\", and the values array contains only \"value\".\n                                          The requirements are ANDed.\n                                        type: object\n                                    type: object\n                                  namespaces:\n                                    description: namespaces specifies a static list\n                                      of namespace names that the term applies to. The\n                                      term is applied to the union of the namespaces\n                                      listed in this field and the ones selected by\n                                      namespaceSelector. null or empty namespaces list\n                                      and null namespaceSelector means \"this pod's namespace\"\n                                    items:\n                                      type: string\n                                    type: array\n                                  topologyKey:\n                                    description: This pod should be co-located (affinity)\n                                      or not co-located (anti-affinity) with the pods\n                                      matching the labelSelector in the specified namespaces,\n                                      where co-located is defined as running on a node\n                                      whose value of the label with key topologyKey\n                                      matches that of any node on which any of the selected\n                                      pods is running. Empty topologyKey is not allowed.\n                                    type: string\n                                required:\n                                  - topologyKey\n                                type: object\n                              weight:\n                                description: weight associated with matching the corresponding\n                                  podAffinityTerm, in the range 1-100.\n                                format: int32\n                                type: integer\n                            required:\n                              - podAffinityTerm\n                              - weight\n                            type: object\n                          type: array\n                        requiredDuringSchedulingIgnoredDuringExecution:\n                          description: If the affinity requirements specified by this\n                            field are not met at scheduling time, the pod will not be\n                            scheduled onto the node. If the affinity requirements specified\n                            by this field cease to be met at some point during pod execution\n                            (e.g. due to a pod label update), the system may or may\n                            not try to eventually evict the pod from its node. When\n                            there are multiple elements, the lists of nodes corresponding\n                            to each podAffinityTerm are intersected, i.e. all terms\n                            must be satisfied.\n                          items:\n                            description: Defines a set of pods (namely those matching\n                              the labelSelector relative to the given namespace(s))\n                              that this pod should be co-located (affinity) or not co-located\n                              (anti-affinity) with, where co-located is defined as running\n                              on a node whose value of the label with key <topologyKey>\n                              matches that of any node on which a pod of the set of\n                              pods is running\n                            properties:\n                              labelSelector:\n                                description: A label query over a set of resources,\n                                  in this case pods.\n                                properties:\n                                  matchExpressions:\n                                    description: matchExpressions is a list of label\n                                      selector requirements. The requirements are ANDed.\n                                    items:\n                                      description: A label selector requirement is a\n                                        selector that contains values, a key, and an\n                                        operator that relates the key and values.\n                                      properties:\n                                        key:\n                                          description: key is the label key that the\n                                            selector applies to.\n                                          type: string\n                                        operator:\n                                          description: operator represents a key's relationship\n                                            to a set of values. Valid operators are\n                                            In, NotIn, Exists and DoesNotExist.\n                                          type: string\n                                        values:\n                                          description: values is an array of string\n                                            values. If the operator is In or NotIn,\n                                            the values array must be non-empty. If the\n                                            operator is Exists or DoesNotExist, the\n                                            values array must be empty. This array is\n                                            replaced during a strategic merge patch.\n                                          items:\n                                            type: string\n                                          type: array\n                                      required:\n                                        - key\n                                        - operator\n                                      type: object\n                                    type: array\n                                  matchLabels:\n                                    additionalProperties:\n                                      type: string\n                                    description: matchLabels is a map of {key,value}\n                                      pairs. A single {key,value} in the matchLabels\n                                      map is equivalent to an element of matchExpressions,\n                                      whose key field is \"key\", the operator is \"In\",\n                                      and the values array contains only \"value\". The\n                                      requirements are ANDed.\n                                    type: object\n                                type: object\n                              namespaceSelector:\n                                description: A label query over the set of namespaces\n                                  that the term applies to. The term is applied to the\n                                  union of the namespaces selected by this field and\n                                  the ones listed in the namespaces field. null selector\n                                  and null or empty namespaces list means \"this pod's\n                                  namespace\". An empty selector ({}) matches all namespaces.\n                                  This field is alpha-level and is only honored when\n                                  PodAffinityNamespaceSelector feature is enabled.\n                                properties:\n                                  matchExpressions:\n                                    description: matchExpressions is a list of label\n                                      selector requirements. The requirements are ANDed.\n                                    items:\n                                      description: A label selector requirement is a\n                                        selector that contains values, a key, and an\n                                        operator that relates the key and values.\n                                      properties:\n                                        key:\n                                          description: key is the label key that the\n                                            selector applies to.\n                                          type: string\n                                        operator:\n                                          description: operator represents a key's relationship\n                                            to a set of values. Valid operators are\n                                            In, NotIn, Exists and DoesNotExist.\n                                          type: string\n                                        values:\n                                          description: values is an array of string\n                                            values. If the operator is In or NotIn,\n                                            the values array must be non-empty. If the\n                                            operator is Exists or DoesNotExist, the\n                                            values array must be empty. This array is\n                                            replaced during a strategic merge patch.\n                                          items:\n                                            type: string\n                                          type: array\n                                      required:\n                                        - key\n                                        - operator\n                                      type: object\n                                    type: array\n                                  matchLabels:\n                                    additionalProperties:\n                                      type: string\n                                    description: matchLabels is a map of {key,value}\n                                      pairs. A single {key,value} in the matchLabels\n                                      map is equivalent to an element of matchExpressions,\n                                      whose key field is \"key\", the operator is \"In\",\n                                      and the values array contains only \"value\". The\n                                      requirements are ANDed.\n                                    type: object\n                                type: object\n                              namespaces:\n                                description: namespaces specifies a static list of namespace\n                                  names that the term applies to. The term is applied\n                                  to the union of the namespaces listed in this field\n                                  and the ones selected by namespaceSelector. null or\n                                  empty namespaces list and null namespaceSelector means\n                                  \"this pod's namespace\"\n                                items:\n                                  type: string\n                                type: array\n                              topologyKey:\n                                description: This pod should be co-located (affinity)\n                                  or not co-located (anti-affinity) with the pods matching\n                                  the labelSelector in the specified namespaces, where\n                                  co-located is defined as running on a node whose value\n                                  of the label with key topologyKey matches that of\n                                  any node on which any of the selected pods is running.\n                                  Empty topologyKey is not allowed.\n                                type: string\n                            required:\n                              - topologyKey\n                            type: object\n                          type: array\n                      type: object\n                    podAntiAffinity:\n                      description: Describes pod anti-affinity scheduling rules (e.g.\n                        avoid putting this pod in the same node, zone, etc. as some\n                        other pod(s)).\n                      properties:\n                        preferredDuringSchedulingIgnoredDuringExecution:\n                          description: The scheduler will prefer to schedule pods to\n                            nodes that satisfy the anti-affinity expressions specified\n                            by this field, but it may choose a node that violates one\n                            or more of the expressions. The node that is most preferred\n                            is the one with the greatest sum of weights, i.e. for each\n                            node that meets all of the scheduling requirements (resource\n                            request, requiredDuringScheduling anti-affinity expressions,\n                            etc.), compute a sum by iterating through the elements of\n                            this field and adding \"weight\" to the sum if the node has\n                            pods which matches the corresponding podAffinityTerm; the\n                            node(s) with the highest sum are the most preferred.\n                          items:\n                            description: The weights of all of the matched WeightedPodAffinityTerm\n                              fields are added per-node to find the most preferred node(s)\n                            properties:\n                              podAffinityTerm:\n                                description: Required. A pod affinity term, associated\n                                  with the corresponding weight.\n                                properties:\n                                  labelSelector:\n                                    description: A label query over a set of resources,\n                                      in this case pods.\n                                    properties:\n                                      matchExpressions:\n                                        description: matchExpressions is a list of label\n                                          selector requirements. The requirements are\n                                          ANDed.\n                                        items:\n                                          description: A label selector requirement\n                                            is a selector that contains values, a key,\n                                            and an operator that relates the key and\n                                            values.\n                                          properties:\n                                            key:\n                                              description: key is the label key that\n                                                the selector applies to.\n                                              type: string\n                                            operator:\n                                              description: operator represents a key's\n                                                relationship to a set of values. Valid\n                                                operators are In, NotIn, Exists and\n                                                DoesNotExist.\n                                              type: string\n                                            values:\n                                              description: values is an array of string\n                                                values. If the operator is In or NotIn,\n                                                the values array must be non-empty.\n                                                If the operator is Exists or DoesNotExist,\n                                                the values array must be empty. This\n                                                array is replaced during a strategic\n                                                merge patch.\n                                              items:\n                                                type: string\n                                              type: array\n                                          required:\n                                            - key\n                                            - operator\n                                          type: object\n                                        type: array\n                                      matchLabels:\n                                        additionalProperties:\n                                          type: string\n                                        description: matchLabels is a map of {key,value}\n                                          pairs. A single {key,value} in the matchLabels\n                                          map is equivalent to an element of matchExpressions,\n                                          whose key field is \"key\", the operator is\n                                          \"In\", and the values array contains only \"value\".\n                                          The requirements are ANDed.\n                                        type: object\n                                    type: object\n                                  namespaceSelector:\n                                    description: A label query over the set of namespaces\n                                      that the term applies to. The term is applied\n                                      to the union of the namespaces selected by this\n                                      field and the ones listed in the namespaces field.\n                                      null selector and null or empty namespaces list\n                                      means \"this pod's namespace\". An empty selector\n                                      ({}) matches all namespaces. This field is alpha-level\n                                      and is only honored when PodAffinityNamespaceSelector\n                                      feature is enabled.\n                                    properties:\n                                      matchExpressions:\n                                        description: matchExpressions is a list of label\n                                          selector requirements. The requirements are\n                                          ANDed.\n                                        items:\n                                          description: A label selector requirement\n                                            is a selector that contains values, a key,\n                                            and an operator that relates the key and\n                                            values.\n                                          properties:\n                                            key:\n                                              description: key is the label key that\n                                                the selector applies to.\n                                              type: string\n                                            operator:\n                                              description: operator represents a key's\n                                                relationship to a set of values. Valid\n                                                operators are In, NotIn, Exists and\n                                                DoesNotExist.\n                                              type: string\n                                            values:\n                                              description: values is an array of string\n                                                values. If the operator is In or NotIn,\n                                                the values array must be non-empty.\n                                                If the operator is Exists or DoesNotExist,\n                                                the values array must be empty. This\n                                                array is replaced during a strategic\n                                                merge patch.\n                                              items:\n                                                type: string\n                                              type: array\n                                          required:\n                                            - key\n                                            - operator\n                                          type: object\n                                        type: array\n                                      matchLabels:\n                                        additionalProperties:\n                                          type: string\n                                        description: matchLabels is a map of {key,value}\n                                          pairs. A single {key,value} in the matchLabels\n                                          map is equivalent to an element of matchExpressions,\n                                          whose key field is \"key\", the operator is\n                                          \"In\", and the values array contains only \"value\".\n                                          The requirements are ANDed.\n                                        type: object\n                                    type: object\n                                  namespaces:\n                                    description: namespaces specifies a static list\n                                      of namespace names that the term applies to. The\n                                      term is applied to the union of the namespaces\n                                      listed in this field and the ones selected by\n                                      namespaceSelector. null or empty namespaces list\n                                      and null namespaceSelector means \"this pod's namespace\"\n                                    items:\n                                      type: string\n                                    type: array\n                                  topologyKey:\n                                    description: This pod should be co-located (affinity)\n                                      or not co-located (anti-affinity) with the pods\n                                      matching the labelSelector in the specified namespaces,\n                                      where co-located is defined as running on a node\n                                      whose value of the label with key topologyKey\n                                      matches that of any node on which any of the selected\n                                      pods is running. Empty topologyKey is not allowed.\n                                    type: string\n                                required:\n                                  - topologyKey\n                                type: object\n                              weight:\n                                description: weight associated with matching the corresponding\n                                  podAffinityTerm, in the range 1-100.\n                                format: int32\n                                type: integer\n                            required:\n                              - podAffinityTerm\n                              - weight\n                            type: object\n                          type: array\n                        requiredDuringSchedulingIgnoredDuringExecution:\n                          description: If the anti-affinity requirements specified by\n                            this field are not met at scheduling time, the pod will\n                            not be scheduled onto the node. If the anti-affinity requirements\n                            specified by this field cease to be met at some point during\n                            pod execution (e.g. due to a pod label update), the system\n                            may or may not try to eventually evict the pod from its\n                            node. When there are multiple elements, the lists of nodes\n                            corresponding to each podAffinityTerm are intersected, i.e.\n                            all terms must be satisfied.\n                          items:\n                            description: Defines a set of pods (namely those matching\n                              the labelSelector relative to the given namespace(s))\n                              that this pod should be co-located (affinity) or not co-located\n                              (anti-affinity) with, where co-located is defined as running\n                              on a node whose value of the label with key <topologyKey>\n                              matches that of any node on which a pod of the set of\n                              pods is running\n                            properties:\n                              labelSelector:\n                                description: A label query over a set of resources,\n                                  in this case pods.\n                                properties:\n                                  matchExpressions:\n                                    description: matchExpressions is a list of label\n                                      selector requirements. The requirements are ANDed.\n                                    items:\n                                      description: A label selector requirement is a\n                                        selector that contains values, a key, and an\n                                        operator that relates the key and values.\n                                      properties:\n                                        key:\n                                          description: key is the label key that the\n                                            selector applies to.\n                                          type: string\n                                        operator:\n                                          description: operator represents a key's relationship\n                                            to a set of values. Valid operators are\n                                            In, NotIn, Exists and DoesNotExist.\n                                          type: string\n                                        values:\n                                          description: values is an array of string\n                                            values. If the operator is In or NotIn,\n                                            the values array must be non-empty. If the\n                                            operator is Exists or DoesNotExist, the\n                                            values array must be empty. This array is\n                                            replaced during a strategic merge patch.\n                                          items:\n                                            type: string\n                                          type: array\n                                      required:\n                                        - key\n                                        - operator\n                                      type: object\n                                    type: array\n                                  matchLabels:\n                                    additionalProperties:\n                                      type: string\n                                    description: matchLabels is a map of {key,value}\n                                      pairs. A single {key,value} in the matchLabels\n                                      map is equivalent to an element of matchExpressions,\n                                      whose key field is \"key\", the operator is \"In\",\n                                      and the values array contains only \"value\". The\n                                      requirements are ANDed.\n                                    type: object\n                                type: object\n                              namespaceSelector:\n                                description: A label query over the set of namespaces\n                                  that the term applies to. The term is applied to the\n                                  union of the namespaces selected by this field and\n                                  the ones listed in the namespaces field. null selector\n                                  and null or empty namespaces list means \"this pod's\n                                  namespace\". An empty selector ({}) matches all namespaces.\n                                  This field is alpha-level and is only honored when\n                                  PodAffinityNamespaceSelector feature is enabled.\n                                properties:\n                                  matchExpressions:\n                                    description: matchExpressions is a list of label\n                                      selector requirements. The requirements are ANDed.\n                                    items:\n                                      description: A label selector requirement is a\n                                        selector that contains values, a key, and an\n                                        operator that relates the key and values.\n                                      properties:\n                                        key:\n                                          description: key is the label key that the\n                                            selector applies to.\n                                          type: string\n                                        operator:\n                                          description: operator represents a key's relationship\n                                            to a set of values. Valid operators are\n                                            In, NotIn, Exists and DoesNotExist.\n                                          type: string\n                                        values:\n                                          description: values is an array of string\n                                            values. If the operator is In or NotIn,\n                                            the values array must be non-empty. If the\n                                            operator is Exists or DoesNotExist, the\n                                            values array must be empty. This array is\n                                            replaced during a strategic merge patch.\n                                          items:\n                                            type: string\n                                          type: array\n                                      required:\n                                        - key\n                                        - operator\n                                      type: object\n                                    type: array\n                                  matchLabels:\n                                    additionalProperties:\n                                      type: string\n                                    description: matchLabels is a map of {key,value}\n                                      pairs. A single {key,value} in the matchLabels\n                                      map is equivalent to an element of matchExpressions,\n                                      whose key field is \"key\", the operator is \"In\",\n                                      and the values array contains only \"value\". The\n                                      requirements are ANDed.\n                                    type: object\n                                type: object\n                              namespaces:\n                                description: namespaces specifies a static list of namespace\n                                  names that the term applies to. The term is applied\n                                  to the union of the namespaces listed in this field\n                                  and the ones selected by namespaceSelector. null or\n                                  empty namespaces list and null namespaceSelector means\n                                  \"this pod's namespace\"\n                                items:\n                                  type: string\n                                type: array\n                              topologyKey:\n                                description: This pod should be co-located (affinity)\n                                  or not co-located (anti-affinity) with the pods matching\n                                  the labelSelector in the specified namespaces, where\n                                  co-located is defined as running on a node whose value\n                                  of the label with key topologyKey matches that of\n                                  any node on which any of the selected pods is running.\n                                  Empty topologyKey is not allowed.\n                                type: string\n                            required:\n                              - topologyKey\n                            type: object\n                          type: array\n                      type: object\n                  type: object\n                args:\n                  items:\n                    type: string\n                  type: array\n                authConfig:\n                  description: AuthTlsConfig defines tls\n                  properties:\n                    enableTLS:\n                      type: boolean\n                    san:\n                      items:\n                        type: string\n                      type: array\n                    tlsSecret:\n                      type: string\n                  type: object\n                clusterType:\n                  description: provider, if has extra info, please use annotation to\n                    store\n                  type: string\n                description:\n                  type: string\n                diskSize:\n                  type: integer\n                diskType:\n                  type: string\n                env:\n                  items:\n                    description: EnvVar represents an environment variable present in\n                      a Container.\n                    properties:\n                      name:\n                        description: Name of the environment variable. Must be a C_IDENTIFIER.\n                        type: string\n                      value:\n                        description: 'Variable references $(VAR_NAME) are expanded using\n                        the previous defined environment variables in the container\n                        and any service environment variables. If a variable cannot\n                        be resolved, the reference in the input string will be unchanged.\n                        The $(VAR_NAME) syntax can be escaped with a double $$, ie:\n                        $$(VAR_NAME). Escaped references will never be expanded, regardless\n                        of whether the variable exists or not. Defaults to \"\".'\n                        type: string\n                      valueFrom:\n                        description: Source for the environment variable's value. Cannot\n                          be used if value is not empty.\n                        properties:\n                          configMapKeyRef:\n                            description: Selects a key of a ConfigMap.\n                            properties:\n                              key:\n                                description: The key to select.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the ConfigMap or its key\n                                  must be defined\n                                type: boolean\n                            required:\n                              - key\n                            type: object\n                          fieldRef:\n                            description: 'Selects a field of the pod: supports metadata.name,\n                            metadata.namespace, `metadata.labels[''<KEY>'']`, `metadata.annotations[''<KEY>'']`,\n                            spec.nodeName, spec.serviceAccountName, status.hostIP,\n                            status.podIP, status.podIPs.'\n                            properties:\n                              apiVersion:\n                                description: Version of the schema the FieldPath is\n                                  written in terms of, defaults to \"v1\".\n                                type: string\n                              fieldPath:\n                                description: Path of the field to select in the specified\n                                  API version.\n                                type: string\n                            required:\n                              - fieldPath\n                            type: object\n                          resourceFieldRef:\n                            description: 'Selects a resource of the container: only\n                            resources limits and requests (limits.cpu, limits.memory,\n                            limits.ephemeral-storage, requests.cpu, requests.memory\n                            and requests.ephemeral-storage) are currently supported.'\n                            properties:\n                              containerName:\n                                description: 'Container name: required for volumes,\n                                optional for env vars'\n                                type: string\n                              divisor:\n                                anyOf:\n                                  - type: integer\n                                  - type: string\n                                description: Specifies the output format of the exposed\n                                  resources, defaults to \"1\"\n                                pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                x-kubernetes-int-or-string: true\n                              resource:\n                                description: 'Required: resource to select'\n                                type: string\n                            required:\n                              - resource\n                            type: object\n                          secretKeyRef:\n                            description: Selects a key of a secret in the pod's namespace\n                            properties:\n                              key:\n                                description: The key of the secret to select from.  Must\n                                  be a valid secret key.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret or its key must\n                                  be defined\n                                type: boolean\n                            required:\n                              - key\n                            type: object\n                        type: object\n                    required:\n                      - name\n                    type: object\n                  type: array\n                name:\n                  type: string\n                repository:\n                  type: string\n                size:\n                  type: integer\n                version:\n                  type: string\n              required:\n                - clusterType\n                - description\n                - diskSize\n                - diskType\n                - name\n                - size\n                - version\n              type: object\n            status:\n              description: EtcdClusterStatus defines the observed state of EtcdCluster\n              properties:\n                conditions:\n                  items:\n                    description: EtcdClusterCondition contains condition information\n                      for a EtcdCluster.\n                    properties:\n                      endTime:\n                        description: Last time the condition transit from one status\n                          to another.\n                        format: date-time\n                        type: string\n                      message:\n                        description: Human readable message indicating details about\n                          last transition.\n                        type: string\n                      reason:\n                        description: (brief) reason for the condition's last transition.\n                        type: string\n                      startTime:\n                        description: Last time we got an update on a given condition.\n                        format: date-time\n                        type: string\n                      status:\n                        description: Status of the condition, one of True, False, Unknown.\n                        type: string\n                      type:\n                        description: Type of EtcdCluster condition.\n                        type: string\n                    required:\n                      - status\n                      - type\n                    type: object\n                  type: array\n                featureGatesStatus:\n                  additionalProperties:\n                    type: string\n                  type: object\n                members:\n                  items:\n                    properties:\n                      clientUrl:\n                        type: string\n                      endpoint:\n                        type: string\n                      errors:\n                        items:\n                          type: string\n                        type: array\n                      extensionClientUrl:\n                        type: string\n                      memberId:\n                        type: string\n                      name:\n                        type: string\n                      port:\n                        type: string\n                      role:\n                        type: string\n                      status:\n                        type: string\n                      version:\n                        type: string\n                    required:\n                      - clientUrl\n                      - endpoint\n                      - extensionClientUrl\n                      - memberId\n                      - name\n                      - port\n                      - role\n                      - status\n                      - version\n                    type: object\n                  type: array\n                phase:\n                  type: string\n                serviceName:\n                  type: string\n              required:\n                - phase\n              type: object\n          type: object\n      served: true\n      storage: true\nstatus:\n  acceptedNames:\n    kind: EtcdCluster\n    plural: etcdclusters\n    singular: etcdcluster\n    shortNames:\n      - cluster\n  conditions: []\n  storedVersions: []\n---\napiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.4.1\n  creationTimestamp: null\n  name: etcdinspections.kstone.tkestack.io\nspec:\n  group: kstone.tkestack.io\n  names:\n    kind: EtcdInspection\n    listKind: EtcdInspectionList\n    plural: etcdinspections\n    singular: etcdinspection\n    shortNames:\n      - inspection\n  scope: Namespaced\n  versions:\n    - name: v1alpha2\n      schema:\n        openAPIV3Schema:\n          description: EtcdInspection is a specification for a EtcdInspection resource\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: EtcdInspectionSpec is the spec for a EtcdInspectionSpec resource\n              properties:\n                clusterName:\n                  type: string\n                intervalInSecond:\n                  type: integer\n                inspectionProvider:\n                  type: string\n                inspectionType:\n                  type: string\n              required:\n                - clusterName\n                - inspectionType\n              type: object\n            status:\n              properties:\n                elapsedTime:\n                  type: integer\n                message:\n                  type: string\n                reason:\n                  type: string\n                records:\n                  items:\n                    description: EtcdInspectionStatus is the status for a EtcdInspectionStatus\n                      resource\n                    properties:\n                      endTime:\n                        description: Last time the condition transit from one status\n                          to another.\n                        format: date-time\n                        type: string\n                      message:\n                        description: Human readable message indicating details about\n                          last transition.\n                        type: string\n                      reason:\n                        description: (brief) reason for the condition's last transition.\n                        type: string\n                      startTime:\n                        description: Last time we got an update on a given condition.\n                        format: date-time\n                        type: string\n                    type: object\n                  type: array\n                updatedAt:\n                  format: date-time\n                  type: string\n              type: object\n          type: object\n      served: true\n      storage: true\nstatus:\n  acceptedNames:\n    kind: \"\"\n    plural: \"\"\n  conditions: []\n  storedVersions: []\n{{- end }}"
  },
  {
    "path": "charts/templates/ingress.yaml",
    "content": "{{- if and .Values.ingress.className (not (semverCompare \">=1.18-0\" .Capabilities.KubeVersion.GitVersion)) }}\n{{- if not (hasKey .Values.ingress.annotations \"kubernetes.io/ingress.class\") }}\n{{- $_ := set .Values.ingress.annotations \"kubernetes.io/ingress.class\" .Values.ingress.className}}\n{{- end }}\n{{- end }}\n\n{{- if .Values.ingress.enabled -}}\n{{- $fullName := include \"kstone.fullname\" . -}}\n{{- if semverCompare \">=1.19-0\" .Capabilities.KubeVersion.GitVersion -}}\napiVersion: networking.k8s.io/v1\n{{- else if semverCompare \">=1.14-0\" .Capabilities.KubeVersion.GitVersion -}}\napiVersion: networking.k8s.io/v1beta1\n{{- else -}}\napiVersion: extensions/v1beta1\n{{- end }}\nkind: Ingress\nmetadata:\n  name: {{ $fullName }}\n  labels:\n    {{- include \"kstone.labels\" . | nindent 4 }}\n  {{- with .Values.ingress.annotations }}\n  annotations:\n    {{- toYaml . | nindent 4 }}\n  {{- end }}\nspec:\n  rules:\n    {{- range .Values.ingress.hosts }}\n    - host: {{ .host | quote }}\n      http:\n        paths:\n          {{- range .paths }}\n          - path: {{ .path }}\n            pathType: {{ .pathType }}\n            backend:\n              {{- if semverCompare \">=1.19-0\" $.Capabilities.KubeVersion.GitVersion }}\n              service:\n                name: {{ $.Release.Name }}-{{ .backend.serviceName }}\n                port:\n                  number: {{ .backend.servicePort }}\n              {{- else }}\n              serviceName: {{ $.Release.Name }}-{{ .backend.serviceName }}\n              servicePort: {{ .backend.servicePort }}\n              {{- end }}\n          {{- end }}\n    {{- end }}\n{{- end }}\n"
  },
  {
    "path": "charts/templates/serviceaccount.yaml",
    "content": "{{- if .Values.serviceAccount.create -}}\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: {{ include \"kstone.serviceAccountName\" . }}\n  labels:\n    {{- include \"kstone.labels\" . | nindent 4 }}\n  {{- with .Values.serviceAccount.annotations }}\n  annotations:\n    {{- toYaml . | nindent 4 }}\n  {{- end }}\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: {{ include \"kstone.serviceAccountName\" . }}\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: cluster-admin\nsubjects:\n  - kind: ServiceAccount\n    name: {{ include \"kstone.serviceAccountName\" . }}\n    namespace: {{ .Release.Namespace }}\n{{- end }}\n\n"
  },
  {
    "path": "charts/values.test.yaml",
    "content": "# Default values for kstone.\n# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\n\nglobal:\n  env: test\n  kstone:\n    tag: v0.2.0-beta.2\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: \"kstone\"\n\ningress:\n  enabled: true\n  className: \"\"\n  annotations:\n#    nginx.ingress.kubernetes.io/rewrite-target: /$2\n    service.cloud.tencent.com/direct-access: 'false'\n    kubernetes.io/ingress.class: qcloud\n#    # lb info\n#    service.kubernetes.io/tke-existed-lbid: ${lb-id}\n#    kubernetes.io/ingress.existLbId: ${lb-id}\n#    kubernetes.io/ingress.subnetId: ${subnet-id}\n  hosts:\n    - host: \"\"\n      paths:\n        - path: /\n          pathType: ImplementationSpecific\n          backend:\n            serviceName: dashboard\n            servicePort: 80\n        - path: /apis\n          pathType: ImplementationSpecific\n          backend:\n            serviceName: dashboard-api\n            servicePort: 80\n        - path: /grafana\n          pathType: ImplementationSpecific\n          backend:\n            serviceName: grafana\n            servicePort: 80\n  tls: []\n  #  - secretName: chart-example-tls\n  #    hosts:\n  #      - chart-example.local\n\ncrd:\n  create: true\n"
  },
  {
    "path": "charts/values.yaml",
    "content": "# Default values for kstone.\n# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\n\nglobal:\n  env: production\n  kstone:\n    tag: v0.2.0-beta.2\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: \"kstone\"\n\ningress:\n  enabled: true\n  className: \"\"\n  annotations:\n#    nginx.ingress.kubernetes.io/rewrite-target: /$2\n    service.cloud.tencent.com/direct-access: 'false'\n    kubernetes.io/ingress.class: qcloud\n#    # lb info\n#    service.kubernetes.io/tke-existed-lbid: ${lb-id}\n#    kubernetes.io/ingress.existLbId: ${lb-id}\n#    kubernetes.io/ingress.subnetId: ${subnet-id}\n  hosts:\n    - host: \"\"\n      paths:\n        - path: /\n          pathType: ImplementationSpecific\n          backend:\n            serviceName: dashboard\n            servicePort: 80\n        - path: /apis\n          pathType: ImplementationSpecific\n          backend:\n            serviceName: dashboard-api\n            servicePort: 80\n        - path: /grafana\n          pathType: ImplementationSpecific\n          backend:\n            serviceName: grafana\n            servicePort: 80\n  tls: []\n  #  - secretName: chart-example-tls\n  #    hosts:\n  #      - chart-example.local\n\ncrd:\n  create: true\n\n"
  },
  {
    "path": "cmd/kstone-api/apiserver.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage main\n\nimport (\n\t\"math/rand\"\n\t\"os\"\n\t\"time\"\n\n\tklog \"k8s.io/klog/v2\"\n\n\t\"tkestack.io/kstone/cmd/kstone-api/app\"\n)\n\nfunc main() {\n\trand.Seed(time.Now().UnixNano())\n\n\tcommand := app.NewAPIServerCommand()\n\n\tif err := command.Execute(); err != nil {\n\t\tklog.Errorf(\"failed to execute api, err: %v\", err)\n\t\tos.Exit(1)\n\t}\n}\n"
  },
  {
    "path": "cmd/kstone-api/app/server.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage app\n\nimport (\n\t\"github.com/spf13/cobra\"\n\t\"github.com/spf13/pflag\"\n\t\"k8s.io/klog/v2\"\n\n\t\"tkestack.io/kstone/cmd/kstone-api/config\"\n\t\"tkestack.io/kstone/pkg/authentication\"\n\t\"tkestack.io/kstone/pkg/middlewares\"\n\tkstoneRouter \"tkestack.io/kstone/pkg/router\"\n)\n\ntype APIServerCommand struct {\n\ttoken           string\n\tauthenticator   string\n\tnamespace       string\n\tauthCfg         string\n\tenableProfiling bool\n}\n\n// NewAPIServerCommand creates a *cobra.Command object with default parameters\nfunc NewAPIServerCommand() *cobra.Command {\n\tac := &APIServerCommand{}\n\tcmd := &cobra.Command{\n\t\tUse: \"kstone-apiserver\",\n\t\tLong: `The Kstone API server validates and configures data\nfor the api objects which include etcdinspections, etcdclusters, and others.\nThe API Server services REST operations and provides the frontend to the \nother components interact, such as kstone-controller, kstone-dashboard.`,\n\n\t\t// stop printing usage when the command errors\n\t\tSilenceUsage: true,\n\t\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\t\tcmd.Flags().VisitAll(func(flag *pflag.Flag) {\n\t\t\t\tklog.V(1).Infof(\"FLAG: --%s=%q\", flag.Name, flag.Value)\n\t\t\t})\n\t\t\tif err := ac.Run(); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tfs := cmd.PersistentFlags()\n\tac.AddFlags(fs)\n\treturn cmd\n}\n\nfunc (c *APIServerCommand) Run() error {\n\tklog.Info(\"start kstone-api\")\n\tconfig.CreateConfigFromFlags(c.token, c.authenticator, c.enableProfiling)\n\tkstoneRouter.SetWorkNamespace(c.namespace)\n\tauthentication.SetAuthConfigMapName(c.authCfg)\n\n\trouter := kstoneRouter.NewRouter()\n\trouter.Use(middlewares.Cors())\n\terr := router.Run()\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc (c *APIServerCommand) AddFlags(fs *pflag.FlagSet) {\n\tfs.StringVar(\n\t\t&c.token,\n\t\t\"token\",\n\t\t\"jwt\",\n\t\t\"specify the authentication token type.\",\n\t)\n\tfs.StringVar(\n\t\t&c.authenticator,\n\t\t\"authenticator\",\n\t\t\"bearertoken\",\n\t\t\"specify the authenticator type.\",\n\t)\n\tfs.StringVar(&c.namespace,\n\t\t\"namespace\",\n\t\t\"kstone\",\n\t\t\"specify the work namespace of kstone.\")\n\tfs.StringVar(&c.authCfg,\n\t\t\"auth\",\n\t\t\"kstone-api-user\",\n\t\t\"specify the auth configmap of kstone.\")\n\tfs.BoolVar(&c.enableProfiling,\n\t\t\"profiling\",\n\t\ttrue,\n\t\t\"enable profiling via web interface host:port/apis/debug/pprof/.\")\n}\n"
  },
  {
    "path": "cmd/kstone-api/config/config.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage config\n\nvar Cfg *Config\n\ntype Config struct {\n\tToken           string\n\tAuthenticator   string\n\tEnableProfiling bool\n}\n\n// CreateConfigFromOptions creates a running configuration instance based\n// on a given kstone-api command line or configuration file option.\nfunc CreateConfigFromFlags(token, authenticator string, enableProfiling bool) {\n\tCfg = &Config{\n\t\tToken:           token,\n\t\tAuthenticator:   authenticator,\n\t\tEnableProfiling: enableProfiling,\n\t}\n}\n"
  },
  {
    "path": "cmd/kstone-controller/etcdcluster-controller/controller.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage etcdclustercontroller\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"time\"\n\n\t// import http pprof\n\t_ \"net/http/pprof\"\n\n\t\"github.com/spf13/cobra\"\n\t\"github.com/spf13/pflag\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/util/uuid\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/client-go/tools/clientcmd\"\n\t\"k8s.io/client-go/tools/leaderelection\"\n\t\"k8s.io/client-go/tools/leaderelection/resourcelock\"\n\tklog \"k8s.io/klog/v2\"\n\n\t\"tkestack.io/kstone/pkg/controllers/etcdcluster\"\n\t\"tkestack.io/kstone/pkg/controllers/util\"\n\t\"tkestack.io/kstone/pkg/k8s\"\n\t\"tkestack.io/kstone/pkg/signals\"\n)\n\ntype EtcdClusterCommand struct {\n\tout                io.Writer\n\tkubeconfig         string\n\tmasterURL          string\n\tlabelSelector      string\n\tleaseLockName      string\n\tleaseLockNamespace string\n\tenableProfiling    bool\n}\n\n// NewEtcdClusterControllerCommand creates a *cobra.Command object with default parameters\nfunc NewEtcdClusterControllerCommand(out io.Writer) *cobra.Command {\n\tcc := &EtcdClusterCommand{out: out}\n\tcmd := &cobra.Command{\n\t\tUse:   \"etcdcluster\",\n\t\tShort: \"run etcdcluster controller\",\n\t\tLong: `The etcdcluster controller is a daemon, it will watches the changes of EtcdCluster resources \nthrough the apiserver and makes changes attempting to move the current state towards the desired state.`,\n\t\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\t\tcmd.Flags().VisitAll(func(flag *pflag.Flag) {\n\t\t\t\tklog.V(1).Infof(\"FLAG: --%s=%q\", flag.Name, flag.Value)\n\t\t\t})\n\t\t\tif err := cc.Run(); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tfs := cmd.PersistentFlags()\n\tcc.AddFlags(fs)\n\treturn cmd\n}\n\n// Run start etcdcluster controller\nfunc (c *EtcdClusterCommand) Run() error {\n\tstopCh := signals.SetupSignalHandler()\n\n\tconfig, err := clientcmd.BuildConfigFromFlags(c.masterURL, c.kubeconfig)\n\tif err != nil {\n\t\tklog.Fatalf(\"Error to build kube config: %v\", err)\n\t\treturn err\n\t}\n\n\tkubeClient, clusterClient, kubeInformerFactory, informerFactory, err := k8s.GenerateInformer(config, c.labelSelector)\n\tif err != nil {\n\t\tklog.Fatalf(\"Error to generate informer: %v\", err)\n\t\treturn err\n\t}\n\n\tcontroller := etcdcluster.NewEtcdclusterController(\n\t\tutil.NewSimpleClientBuilder(c.kubeconfig),\n\t\tkubeClient,\n\t\tclusterClient,\n\t\tkubeInformerFactory.Core().V1().Secrets(),\n\t\tinformerFactory.Kstone().V1alpha2().EtcdClusters(),\n\t)\n\t// notice that there is no need to run Start methods in a separate goroutine.\n\t// (i.e. go kubeInformerFactory.Start(stopCh)\n\t// Start method is non-blocking and runs all registered informers in a dedicated goroutine.\n\tkubeInformerFactory.Start(stopCh)\n\tinformerFactory.Start(stopCh)\n\n\tleaderElectionConfig, err := c.makeLeaderElectionConfig(kubeClient, controller, stopCh)\n\tif err != nil {\n\t\tklog.Fatalf(\"Error to generate leader election config: %v\", err)\n\t\treturn err\n\t}\n\n\t// use a Go context so we can tell the leaderelection code when we\n\t// want to step down\n\tctx, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\n\tif c.enableProfiling {\n\t\tgo func() {\n\t\t\taddr := \"0.0.0.0:6060\"\n\t\t\tklog.Infof(\"Listen on %s for profiling\", addr)\n\t\t\tklog.Error(http.ListenAndServe(addr, nil))\n\t\t}()\n\t}\n\n\tgo func() {\n\t\t<-stopCh\n\t\tklog.Info(\"Received termination, signaling shutdown\")\n\t\tcancel()\n\t}()\n\n\t// start the leader election code loop\n\tleaderelection.RunOrDie(ctx, *leaderElectionConfig)\n\treturn err\n}\n\nfunc (c *EtcdClusterCommand) AddFlags(fs *pflag.FlagSet) {\n\tfs.StringVarP(\n\t\t&c.kubeconfig,\n\t\t\"kubeconfig\",\n\t\t\"k\",\n\t\t\"\",\n\t\t\"force to specify the kubeconfig\",\n\t)\n\tfs.StringVar(\n\t\t&c.masterURL,\n\t\t\"master\",\n\t\t\"\",\n\t\t\"The address of the Kubernetes API server. Overrides any value in kubeconfig. Only required if out-of-cluster.\",\n\t)\n\tfs.StringVar(\n\t\t&c.labelSelector,\n\t\t\"labelSelector\",\n\t\t\"\",\n\t\t\"The address of the Kubernetes API server. Overrides any value in kubeconfig. Only required if out-of-cluster.\",\n\t)\n\tfs.StringVar(\n\t\t&c.leaseLockName,\n\t\t\"lease-lock-name\",\n\t\t\"kstone-etcdcluster-controller\",\n\t\t\"the lease lock resource name\",\n\t)\n\tfs.StringVar(&c.leaseLockNamespace,\n\t\t\"lease-lock-namespace\",\n\t\t\"kstone\",\n\t\t\"the lease lock resource namespace\",\n\t)\n\tfs.BoolVar(&c.enableProfiling,\n\t\t\"profiling\",\n\t\ttrue,\n\t\t\"enable profiling via web interface host:port/debug/pprof/.\")\n}\n\nfunc (c *EtcdClusterCommand) makeLeaderElectionConfig(kubeClient *kubernetes.Clientset, controller *etcdcluster.ClusterController, stopCh <-chan struct{}) (*leaderelection.LeaderElectionConfig, error) {\n\tif c.leaseLockName == \"\" {\n\t\tklog.Fatal(\"unable to get lease lock resource name (missing lease-lock-name flag).\")\n\t}\n\tif c.leaseLockNamespace == \"\" {\n\t\tklog.Fatal(\"unable to get lease lock resource namespace (missing lease-lock-namespace flag).\")\n\t}\n\n\thostname, err := os.Hostname()\n\tif err != nil {\n\t\tklog.Errorf(\"unable to get hostname: %v\", err)\n\t\treturn nil, err\n\t}\n\t// add a uniquifier so that two processes on the same host don't accidentally both become active\n\tid := hostname + \"_\" + string(uuid.NewUUID())\n\n\t// we use the Lease lock type since edits to Leases are less common\n\t// and fewer objects in the cluster watch \"all Leases\".\n\tlock := &resourcelock.LeaseLock{\n\t\tLeaseMeta: metav1.ObjectMeta{\n\t\t\tName:      c.leaseLockName,\n\t\t\tNamespace: c.leaseLockNamespace,\n\t\t},\n\t\tClient: kubeClient.CoordinationV1(),\n\t\tLockConfig: resourcelock.ResourceLockConfig{\n\t\t\tIdentity: id,\n\t\t},\n\t}\n\n\t// start the leader election code loop\n\treturn &leaderelection.LeaderElectionConfig{\n\t\tLock: lock,\n\t\t// IMPORTANT: you MUST ensure that any code you have that\n\t\t// is protected by the lease must terminate **before**\n\t\t// you call cancel. Otherwise, you could have a background\n\t\t// loop still running and another process could\n\t\t// get elected before your background loop finished, violating\n\t\t// the stated goal of the lease.\n\t\tReleaseOnCancel: true,\n\t\tLeaseDuration:   60 * time.Second,\n\t\tRenewDeadline:   15 * time.Second,\n\t\tRetryPeriod:     5 * time.Second,\n\t\tCallbacks: leaderelection.LeaderCallbacks{\n\t\t\tOnStartedLeading: func(ctx context.Context) {\n\t\t\t\t// we're notified when we start - this is where you would\n\t\t\t\t// usually put your code\n\t\t\t\tif err := controller.Run(2, stopCh); err != nil {\n\t\t\t\t\tklog.Fatalf(\"Error running etcd controller: %s\", err.Error())\n\t\t\t\t}\n\t\t\t},\n\t\t\tOnStoppedLeading: func() {\n\t\t\t\t// we can do cleanup here\n\t\t\t\tklog.Infof(\"leader lost: %s\", id)\n\t\t\t\tos.Exit(0)\n\t\t\t},\n\t\t\tOnNewLeader: func(identity string) {\n\t\t\t\t// we're notified when new leader elected\n\t\t\t\tif identity == id {\n\t\t\t\t\t// I just got the lock\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tklog.Infof(\"new leader elected: %s\", identity)\n\t\t\t},\n\t\t},\n\t}, nil\n\n}\n"
  },
  {
    "path": "cmd/kstone-controller/etcdinspection-controller/controller.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage etcdinspectioncontroller\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"time\"\n\n\t// import http pprof\n\t_ \"net/http/pprof\"\n\n\t\"github.com/spf13/cobra\"\n\t\"github.com/spf13/pflag\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/util/uuid\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/client-go/tools/clientcmd\"\n\t\"k8s.io/client-go/tools/leaderelection\"\n\t\"k8s.io/client-go/tools/leaderelection/resourcelock\"\n\tklog \"k8s.io/klog/v2\"\n\n\t\"tkestack.io/kstone/pkg/controllers/etcdinspection\"\n\t\"tkestack.io/kstone/pkg/controllers/util\"\n\t\"tkestack.io/kstone/pkg/k8s\"\n\t\"tkestack.io/kstone/pkg/signals\"\n)\n\ntype EtcdInspectionCommand struct {\n\tout                io.Writer\n\tkubeconfig         string\n\tmasterURL          string\n\tlabelSelector      string\n\tleaseLockName      string\n\tleaseLockNamespace string\n\tenableProfiling    bool\n}\n\n// NewEtcdInspectionControllerCommand creates a *cobra.Command object with default parameters\nfunc NewEtcdInspectionControllerCommand(out io.Writer) *cobra.Command {\n\tcc := &EtcdInspectionCommand{out: out}\n\tcmd := &cobra.Command{\n\t\tUse:   \"inspection\",\n\t\tShort: \"run inspection controller\",\n\t\tLong: `The inspection controller is a daemon, it will watches the changes of etcdinspection resources \nthrough the apiserver and makes changes attempting to move the current state towards the desired state.`,\n\t\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\t\tcmd.Flags().VisitAll(func(flag *pflag.Flag) {\n\t\t\t\tklog.V(1).Infof(\"FLAG: --%s=%q\", flag.Name, flag.Value)\n\t\t\t})\n\t\t\tif err := cc.Run(); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tfs := cmd.PersistentFlags()\n\tcc.AddFlags(fs)\n\treturn cmd\n}\n\n// Run start etcdinspection controller\nfunc (c *EtcdInspectionCommand) Run() error {\n\tstopCh := signals.SetupSignalHandler()\n\tconfig, err := clientcmd.BuildConfigFromFlags(c.masterURL, c.kubeconfig)\n\tif err != nil {\n\t\tklog.Fatalf(\"Error building kubeconfig: %v\", err)\n\t\treturn err\n\t}\n\n\tkubeClient, clusterClient, kubeInformerFactory, informerFactory, err := k8s.GenerateInformer(config, c.labelSelector)\n\tif err != nil {\n\t\tklog.Fatalf(\"Error generate informer: %v\", err)\n\t\treturn err\n\t}\n\n\tcontroller := etcdinspection.NewEtcdInspectionController(\n\t\tutil.NewSimpleClientBuilder(c.kubeconfig),\n\t\tkubeClient,\n\t\tclusterClient,\n\t\tkubeInformerFactory.Core().V1().Secrets(),\n\t\tinformerFactory.Kstone().V1alpha2().EtcdInspections(),\n\t)\n\t// notice that there is no need to run Start methods in a separate goroutine.\n\t// (i.e. go kubeInformerFactory.Start(stopCh)\n\t// Start method is non-blocking and runs all registered informers in a dedicated goroutine.\n\tkubeInformerFactory.Start(stopCh)\n\tinformerFactory.Start(stopCh)\n\n\tleaderElectionConfig, err := c.makeLeaderElectionConfig(kubeClient, controller, stopCh)\n\tif err != nil {\n\t\tklog.Fatalf(\"Error to generate leader election config: %v\", err)\n\t\treturn err\n\t}\n\n\t// use a Go context so we can tell the leaderelection code when we\n\t// want to step down\n\tctx, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\n\tif c.enableProfiling {\n\t\tgo func() {\n\t\t\taddr := \"0.0.0.0:6060\"\n\t\t\tklog.Infof(\"Listen on %s for profiling\", addr)\n\t\t\tklog.Error(http.ListenAndServe(addr, nil))\n\t\t}()\n\t}\n\n\tgo func() {\n\t\t<-stopCh\n\t\tklog.Info(\"Received termination, signaling shutdown\")\n\t\tcancel()\n\t}()\n\n\t// start the leader election code loop\n\tleaderelection.RunOrDie(ctx, *leaderElectionConfig)\n\treturn err\n}\n\nfunc (c *EtcdInspectionCommand) AddFlags(fs *pflag.FlagSet) {\n\tfs.StringVarP(\n\t\t&c.kubeconfig,\n\t\t\"kubeconfig\",\n\t\t\"k\",\n\t\t\"\",\n\t\t\"force to specify the kubeconfig\",\n\t)\n\tfs.StringVar(\n\t\t&c.masterURL,\n\t\t\"master\",\n\t\t\"\",\n\t\t\"The address of the Kubernetes API server. Overrides any value in kubeconfig. Only required if out-of-cluster.\",\n\t)\n\tfs.StringVar(\n\t\t&c.labelSelector,\n\t\t\"labelSelector\",\n\t\t\"\",\n\t\t\"The address of the Kubernetes API server. Overrides any value in kubeconfig. Only required if out-of-cluster.\",\n\t)\n\tfs.StringVar(\n\t\t&c.leaseLockName,\n\t\t\"lease-lock-name\",\n\t\t\"kstone-etcdinspection-controller\",\n\t\t\"the lease lock resource name\",\n\t)\n\tfs.StringVar(&c.leaseLockNamespace,\n\t\t\"lease-lock-namespace\",\n\t\t\"kstone\",\n\t\t\"the lease lock resource namespace\",\n\t)\n\tfs.BoolVar(&c.enableProfiling,\n\t\t\"profiling\",\n\t\ttrue,\n\t\t\"enable profiling via web interface host:port/debug/pprof/.\")\n}\n\nfunc (c *EtcdInspectionCommand) makeLeaderElectionConfig(kubeClient *kubernetes.Clientset, controller *etcdinspection.InspectionController, stopCh <-chan struct{}) (*leaderelection.LeaderElectionConfig, error) {\n\tif c.leaseLockName == \"\" {\n\t\tklog.Fatal(\"unable to get lease lock resource name (missing lease-lock-name flag).\")\n\t}\n\tif c.leaseLockNamespace == \"\" {\n\t\tklog.Fatal(\"unable to get lease lock resource namespace (missing lease-lock-namespace flag).\")\n\t}\n\n\thostname, err := os.Hostname()\n\tif err != nil {\n\t\tklog.Errorf(\"unable to get hostname: %v\", err)\n\t\treturn nil, err\n\t}\n\t// add a uniquifier so that two processes on the same host don't accidentally both become active\n\tid := hostname + \"_\" + string(uuid.NewUUID())\n\n\t// we use the Lease lock type since edits to Leases are less common\n\t// and fewer objects in the cluster watch \"all Leases\".\n\tlock := &resourcelock.LeaseLock{\n\t\tLeaseMeta: metav1.ObjectMeta{\n\t\t\tName:      c.leaseLockName,\n\t\t\tNamespace: c.leaseLockNamespace,\n\t\t},\n\t\tClient: kubeClient.CoordinationV1(),\n\t\tLockConfig: resourcelock.ResourceLockConfig{\n\t\t\tIdentity: id,\n\t\t},\n\t}\n\n\t// start the leader election code loop\n\treturn &leaderelection.LeaderElectionConfig{\n\t\tLock: lock,\n\t\t// IMPORTANT: you MUST ensure that any code you have that\n\t\t// is protected by the lease must terminate **before**\n\t\t// you call cancel. Otherwise, you could have a background\n\t\t// loop still running and another process could\n\t\t// get elected before your background loop finished, violating\n\t\t// the stated goal of the lease.\n\t\tReleaseOnCancel: true,\n\t\tLeaseDuration:   60 * time.Second,\n\t\tRenewDeadline:   15 * time.Second,\n\t\tRetryPeriod:     5 * time.Second,\n\t\tCallbacks: leaderelection.LeaderCallbacks{\n\t\t\tOnStartedLeading: func(ctx context.Context) {\n\t\t\t\t// we're notified when we start - this is where you would\n\t\t\t\t// usually put your code\n\t\t\t\tif err := controller.Run(2, stopCh); err != nil {\n\t\t\t\t\tklog.Fatalf(\"Error running etcd controller: %s\", err.Error())\n\t\t\t\t}\n\t\t\t},\n\t\t\tOnStoppedLeading: func() {\n\t\t\t\t// we can do cleanup here\n\t\t\t\tklog.Infof(\"leader lost: %s\", id)\n\t\t\t\tos.Exit(0)\n\t\t\t},\n\t\t\tOnNewLeader: func(identity string) {\n\t\t\t\t// we're notified when new leader elected\n\t\t\t\tif identity == id {\n\t\t\t\t\t// I just got the lock\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tklog.Infof(\"new leader elected: %s\", identity)\n\t\t\t},\n\t\t},\n\t}, nil\n\n}\n"
  },
  {
    "path": "cmd/kstone-controller/main.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage main\n\nimport (\n\tgoflag \"flag\"\n\t\"math/rand\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/spf13/cobra\"\n\tflag \"github.com/spf13/pflag\"\n\tklog \"k8s.io/klog/v2\"\n\n\tetcdclustercontroller \"tkestack.io/kstone/cmd/kstone-controller/etcdcluster-controller\"\n\tetcdinspectioncontroller \"tkestack.io/kstone/cmd/kstone-controller/etcdinspection-controller\"\n)\n\nfunc main() {\n\trand.Seed(time.Now().UnixNano())\n\tvar cmd = &cobra.Command{\n\t\tUse:              \"kstone-controller\",\n\t\tShort:            \"run etcdcluster/etcdinspection controller\",\n\t\tPersistentPreRun: func(c *cobra.Command, args []string) {},\n\t}\n\n\tflags := cmd.PersistentFlags()\n\tout := cmd.OutOrStdout()\n\tcmd.AddCommand(\n\t\tetcdclustercontroller.NewEtcdClusterControllerCommand(out),\n\t\tetcdinspectioncontroller.NewEtcdInspectionControllerCommand(out),\n\t)\n\n\tklog.InitFlags(nil)\n\tdefer klog.Flush()\n\n\tflag.CommandLine.AddGoFlagSet(goflag.CommandLine)\n\terr := flags.Parse(os.Args[1:])\n\tif err != nil {\n\t\tklog.Errorf(\"failed to parse args, err is %v\", err)\n\t}\n\n\tif err = cmd.Execute(); err != nil {\n\t\tklog.Errorf(\"failed to execute controller, err: %v\", err)\n\t\tos.Exit(1)\n\t}\n}\n"
  },
  {
    "path": "deploy/crds/kstone.tkestack.io_etcdclusters.yaml",
    "content": "\n---\napiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.4.1\n  creationTimestamp: null\n  name: etcdclusters.kstone.tkestack.io\nspec:\n  group: kstone.tkestack.io\n  names:\n    kind: EtcdCluster\n    listKind: EtcdClusterList\n    plural: etcdclusters\n    singular: etcdcluster\n    shortNames:\n      - cluster\n  scope: Namespaced\n  versions:\n    - name: v1alpha2\n      schema:\n        openAPIV3Schema:\n          description: EtcdCluster is the Schema for the etcdclusters 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              x-kubernetes-preserve-unknown-fields: true\n              description: EtcdClusterSpec defines the desired state of EtcdCluster\n              properties:\n                affinity:\n                  description: Affinity is a group of affinity scheduling rules.\n                  properties:\n                    nodeAffinity:\n                      description: Describes node affinity scheduling rules for the\n                        pod.\n                      properties:\n                        preferredDuringSchedulingIgnoredDuringExecution:\n                          description: The scheduler will prefer to schedule pods to\n                            nodes that satisfy the affinity expressions specified by\n                            this field, but it may choose a node that violates one or\n                            more of the expressions. The node that is most preferred\n                            is the one with the greatest sum of weights, i.e. for each\n                            node that meets all of the scheduling requirements (resource\n                            request, requiredDuringScheduling affinity expressions,\n                            etc.), compute a sum by iterating through the elements of\n                            this field and adding \"weight\" to the sum if the node matches\n                            the corresponding matchExpressions; the node(s) with the\n                            highest sum are the most preferred.\n                          items:\n                            description: An empty preferred scheduling term matches\n                              all objects with implicit weight 0 (i.e. it's a no-op).\n                              A null preferred scheduling term matches no objects (i.e.\n                              is also a no-op).\n                            properties:\n                              preference:\n                                description: A node selector term, associated with the\n                                  corresponding weight.\n                                properties:\n                                  matchExpressions:\n                                    description: A list of node selector requirements\n                                      by node's labels.\n                                    items:\n                                      description: A node selector requirement is a\n                                        selector that contains values, a key, and an\n                                        operator that relates the key and values.\n                                      properties:\n                                        key:\n                                          description: The label key that the selector\n                                            applies to.\n                                          type: string\n                                        operator:\n                                          description: Represents a key's relationship\n                                            to a set of values. Valid operators are\n                                            In, NotIn, Exists, DoesNotExist. Gt, and\n                                            Lt.\n                                          type: string\n                                        values:\n                                          description: An array of string values. If\n                                            the operator is In or NotIn, the values\n                                            array must be non-empty. If the operator\n                                            is Exists or DoesNotExist, the values array\n                                            must be empty. If the operator is Gt or\n                                            Lt, the values array must have a single\n                                            element, which will be interpreted as an\n                                            integer. This array is replaced during a\n                                            strategic merge patch.\n                                          items:\n                                            type: string\n                                          type: array\n                                      required:\n                                        - key\n                                        - operator\n                                      type: object\n                                    type: array\n                                  matchFields:\n                                    description: A list of node selector requirements\n                                      by node's fields.\n                                    items:\n                                      description: A node selector requirement is a\n                                        selector that contains values, a key, and an\n                                        operator that relates the key and values.\n                                      properties:\n                                        key:\n                                          description: The label key that the selector\n                                            applies to.\n                                          type: string\n                                        operator:\n                                          description: Represents a key's relationship\n                                            to a set of values. Valid operators are\n                                            In, NotIn, Exists, DoesNotExist. Gt, and\n                                            Lt.\n                                          type: string\n                                        values:\n                                          description: An array of string values. If\n                                            the operator is In or NotIn, the values\n                                            array must be non-empty. If the operator\n                                            is Exists or DoesNotExist, the values array\n                                            must be empty. If the operator is Gt or\n                                            Lt, the values array must have a single\n                                            element, which will be interpreted as an\n                                            integer. This array is replaced during a\n                                            strategic merge patch.\n                                          items:\n                                            type: string\n                                          type: array\n                                      required:\n                                        - key\n                                        - operator\n                                      type: object\n                                    type: array\n                                type: object\n                              weight:\n                                description: Weight associated with matching the corresponding\n                                  nodeSelectorTerm, in the range 1-100.\n                                format: int32\n                                type: integer\n                            required:\n                              - preference\n                              - weight\n                            type: object\n                          type: array\n                        requiredDuringSchedulingIgnoredDuringExecution:\n                          description: If the affinity requirements specified by this\n                            field are not met at scheduling time, the pod will not be\n                            scheduled onto the node. If the affinity requirements specified\n                            by this field cease to be met at some point during pod execution\n                            (e.g. due to an update), the system may or may not try to\n                            eventually evict the pod from its node.\n                          properties:\n                            nodeSelectorTerms:\n                              description: Required. A list of node selector terms.\n                                The terms are ORed.\n                              items:\n                                description: A null or empty node selector term matches\n                                  no objects. The requirements of them are ANDed. The\n                                  TopologySelectorTerm type implements a subset of the\n                                  NodeSelectorTerm.\n                                properties:\n                                  matchExpressions:\n                                    description: A list of node selector requirements\n                                      by node's labels.\n                                    items:\n                                      description: A node selector requirement is a\n                                        selector that contains values, a key, and an\n                                        operator that relates the key and values.\n                                      properties:\n                                        key:\n                                          description: The label key that the selector\n                                            applies to.\n                                          type: string\n                                        operator:\n                                          description: Represents a key's relationship\n                                            to a set of values. Valid operators are\n                                            In, NotIn, Exists, DoesNotExist. Gt, and\n                                            Lt.\n                                          type: string\n                                        values:\n                                          description: An array of string values. If\n                                            the operator is In or NotIn, the values\n                                            array must be non-empty. If the operator\n                                            is Exists or DoesNotExist, the values array\n                                            must be empty. If the operator is Gt or\n                                            Lt, the values array must have a single\n                                            element, which will be interpreted as an\n                                            integer. This array is replaced during a\n                                            strategic merge patch.\n                                          items:\n                                            type: string\n                                          type: array\n                                      required:\n                                        - key\n                                        - operator\n                                      type: object\n                                    type: array\n                                  matchFields:\n                                    description: A list of node selector requirements\n                                      by node's fields.\n                                    items:\n                                      description: A node selector requirement is a\n                                        selector that contains values, a key, and an\n                                        operator that relates the key and values.\n                                      properties:\n                                        key:\n                                          description: The label key that the selector\n                                            applies to.\n                                          type: string\n                                        operator:\n                                          description: Represents a key's relationship\n                                            to a set of values. Valid operators are\n                                            In, NotIn, Exists, DoesNotExist. Gt, and\n                                            Lt.\n                                          type: string\n                                        values:\n                                          description: An array of string values. If\n                                            the operator is In or NotIn, the values\n                                            array must be non-empty. If the operator\n                                            is Exists or DoesNotExist, the values array\n                                            must be empty. If the operator is Gt or\n                                            Lt, the values array must have a single\n                                            element, which will be interpreted as an\n                                            integer. This array is replaced during a\n                                            strategic merge patch.\n                                          items:\n                                            type: string\n                                          type: array\n                                      required:\n                                        - key\n                                        - operator\n                                      type: object\n                                    type: array\n                                type: object\n                              type: array\n                          required:\n                            - nodeSelectorTerms\n                          type: object\n                      type: object\n                    podAffinity:\n                      description: Describes pod affinity scheduling rules (e.g. co-locate\n                        this pod in the same node, zone, etc. as some other pod(s)).\n                      properties:\n                        preferredDuringSchedulingIgnoredDuringExecution:\n                          description: The scheduler will prefer to schedule pods to\n                            nodes that satisfy the affinity expressions specified by\n                            this field, but it may choose a node that violates one or\n                            more of the expressions. The node that is most preferred\n                            is the one with the greatest sum of weights, i.e. for each\n                            node that meets all of the scheduling requirements (resource\n                            request, requiredDuringScheduling affinity expressions,\n                            etc.), compute a sum by iterating through the elements of\n                            this field and adding \"weight\" to the sum if the node has\n                            pods which matches the corresponding podAffinityTerm; the\n                            node(s) with the highest sum are the most preferred.\n                          items:\n                            description: The weights of all of the matched WeightedPodAffinityTerm\n                              fields are added per-node to find the most preferred node(s)\n                            properties:\n                              podAffinityTerm:\n                                description: Required. A pod affinity term, associated\n                                  with the corresponding weight.\n                                properties:\n                                  labelSelector:\n                                    description: A label query over a set of resources,\n                                      in this case pods.\n                                    properties:\n                                      matchExpressions:\n                                        description: matchExpressions is a list of label\n                                          selector requirements. The requirements are\n                                          ANDed.\n                                        items:\n                                          description: A label selector requirement\n                                            is a selector that contains values, a key,\n                                            and an operator that relates the key and\n                                            values.\n                                          properties:\n                                            key:\n                                              description: key is the label key that\n                                                the selector applies to.\n                                              type: string\n                                            operator:\n                                              description: operator represents a key's\n                                                relationship to a set of values. Valid\n                                                operators are In, NotIn, Exists and\n                                                DoesNotExist.\n                                              type: string\n                                            values:\n                                              description: values is an array of string\n                                                values. If the operator is In or NotIn,\n                                                the values array must be non-empty.\n                                                If the operator is Exists or DoesNotExist,\n                                                the values array must be empty. This\n                                                array is replaced during a strategic\n                                                merge patch.\n                                              items:\n                                                type: string\n                                              type: array\n                                          required:\n                                            - key\n                                            - operator\n                                          type: object\n                                        type: array\n                                      matchLabels:\n                                        additionalProperties:\n                                          type: string\n                                        description: matchLabels is a map of {key,value}\n                                          pairs. A single {key,value} in the matchLabels\n                                          map is equivalent to an element of matchExpressions,\n                                          whose key field is \"key\", the operator is\n                                          \"In\", and the values array contains only \"value\".\n                                          The requirements are ANDed.\n                                        type: object\n                                    type: object\n                                  namespaceSelector:\n                                    description: A label query over the set of namespaces\n                                      that the term applies to. The term is applied\n                                      to the union of the namespaces selected by this\n                                      field and the ones listed in the namespaces field.\n                                      null selector and null or empty namespaces list\n                                      means \"this pod's namespace\". An empty selector\n                                      ({}) matches all namespaces. This field is alpha-level\n                                      and is only honored when PodAffinityNamespaceSelector\n                                      feature is enabled.\n                                    properties:\n                                      matchExpressions:\n                                        description: matchExpressions is a list of label\n                                          selector requirements. The requirements are\n                                          ANDed.\n                                        items:\n                                          description: A label selector requirement\n                                            is a selector that contains values, a key,\n                                            and an operator that relates the key and\n                                            values.\n                                          properties:\n                                            key:\n                                              description: key is the label key that\n                                                the selector applies to.\n                                              type: string\n                                            operator:\n                                              description: operator represents a key's\n                                                relationship to a set of values. Valid\n                                                operators are In, NotIn, Exists and\n                                                DoesNotExist.\n                                              type: string\n                                            values:\n                                              description: values is an array of string\n                                                values. If the operator is In or NotIn,\n                                                the values array must be non-empty.\n                                                If the operator is Exists or DoesNotExist,\n                                                the values array must be empty. This\n                                                array is replaced during a strategic\n                                                merge patch.\n                                              items:\n                                                type: string\n                                              type: array\n                                          required:\n                                            - key\n                                            - operator\n                                          type: object\n                                        type: array\n                                      matchLabels:\n                                        additionalProperties:\n                                          type: string\n                                        description: matchLabels is a map of {key,value}\n                                          pairs. A single {key,value} in the matchLabels\n                                          map is equivalent to an element of matchExpressions,\n                                          whose key field is \"key\", the operator is\n                                          \"In\", and the values array contains only \"value\".\n                                          The requirements are ANDed.\n                                        type: object\n                                    type: object\n                                  namespaces:\n                                    description: namespaces specifies a static list\n                                      of namespace names that the term applies to. The\n                                      term is applied to the union of the namespaces\n                                      listed in this field and the ones selected by\n                                      namespaceSelector. null or empty namespaces list\n                                      and null namespaceSelector means \"this pod's namespace\"\n                                    items:\n                                      type: string\n                                    type: array\n                                  topologyKey:\n                                    description: This pod should be co-located (affinity)\n                                      or not co-located (anti-affinity) with the pods\n                                      matching the labelSelector in the specified namespaces,\n                                      where co-located is defined as running on a node\n                                      whose value of the label with key topologyKey\n                                      matches that of any node on which any of the selected\n                                      pods is running. Empty topologyKey is not allowed.\n                                    type: string\n                                required:\n                                  - topologyKey\n                                type: object\n                              weight:\n                                description: weight associated with matching the corresponding\n                                  podAffinityTerm, in the range 1-100.\n                                format: int32\n                                type: integer\n                            required:\n                              - podAffinityTerm\n                              - weight\n                            type: object\n                          type: array\n                        requiredDuringSchedulingIgnoredDuringExecution:\n                          description: If the affinity requirements specified by this\n                            field are not met at scheduling time, the pod will not be\n                            scheduled onto the node. If the affinity requirements specified\n                            by this field cease to be met at some point during pod execution\n                            (e.g. due to a pod label update), the system may or may\n                            not try to eventually evict the pod from its node. When\n                            there are multiple elements, the lists of nodes corresponding\n                            to each podAffinityTerm are intersected, i.e. all terms\n                            must be satisfied.\n                          items:\n                            description: Defines a set of pods (namely those matching\n                              the labelSelector relative to the given namespace(s))\n                              that this pod should be co-located (affinity) or not co-located\n                              (anti-affinity) with, where co-located is defined as running\n                              on a node whose value of the label with key <topologyKey>\n                              matches that of any node on which a pod of the set of\n                              pods is running\n                            properties:\n                              labelSelector:\n                                description: A label query over a set of resources,\n                                  in this case pods.\n                                properties:\n                                  matchExpressions:\n                                    description: matchExpressions is a list of label\n                                      selector requirements. The requirements are ANDed.\n                                    items:\n                                      description: A label selector requirement is a\n                                        selector that contains values, a key, and an\n                                        operator that relates the key and values.\n                                      properties:\n                                        key:\n                                          description: key is the label key that the\n                                            selector applies to.\n                                          type: string\n                                        operator:\n                                          description: operator represents a key's relationship\n                                            to a set of values. Valid operators are\n                                            In, NotIn, Exists and DoesNotExist.\n                                          type: string\n                                        values:\n                                          description: values is an array of string\n                                            values. If the operator is In or NotIn,\n                                            the values array must be non-empty. If the\n                                            operator is Exists or DoesNotExist, the\n                                            values array must be empty. This array is\n                                            replaced during a strategic merge patch.\n                                          items:\n                                            type: string\n                                          type: array\n                                      required:\n                                        - key\n                                        - operator\n                                      type: object\n                                    type: array\n                                  matchLabels:\n                                    additionalProperties:\n                                      type: string\n                                    description: matchLabels is a map of {key,value}\n                                      pairs. A single {key,value} in the matchLabels\n                                      map is equivalent to an element of matchExpressions,\n                                      whose key field is \"key\", the operator is \"In\",\n                                      and the values array contains only \"value\". The\n                                      requirements are ANDed.\n                                    type: object\n                                type: object\n                              namespaceSelector:\n                                description: A label query over the set of namespaces\n                                  that the term applies to. The term is applied to the\n                                  union of the namespaces selected by this field and\n                                  the ones listed in the namespaces field. null selector\n                                  and null or empty namespaces list means \"this pod's\n                                  namespace\". An empty selector ({}) matches all namespaces.\n                                  This field is alpha-level and is only honored when\n                                  PodAffinityNamespaceSelector feature is enabled.\n                                properties:\n                                  matchExpressions:\n                                    description: matchExpressions is a list of label\n                                      selector requirements. The requirements are ANDed.\n                                    items:\n                                      description: A label selector requirement is a\n                                        selector that contains values, a key, and an\n                                        operator that relates the key and values.\n                                      properties:\n                                        key:\n                                          description: key is the label key that the\n                                            selector applies to.\n                                          type: string\n                                        operator:\n                                          description: operator represents a key's relationship\n                                            to a set of values. Valid operators are\n                                            In, NotIn, Exists and DoesNotExist.\n                                          type: string\n                                        values:\n                                          description: values is an array of string\n                                            values. If the operator is In or NotIn,\n                                            the values array must be non-empty. If the\n                                            operator is Exists or DoesNotExist, the\n                                            values array must be empty. This array is\n                                            replaced during a strategic merge patch.\n                                          items:\n                                            type: string\n                                          type: array\n                                      required:\n                                        - key\n                                        - operator\n                                      type: object\n                                    type: array\n                                  matchLabels:\n                                    additionalProperties:\n                                      type: string\n                                    description: matchLabels is a map of {key,value}\n                                      pairs. A single {key,value} in the matchLabels\n                                      map is equivalent to an element of matchExpressions,\n                                      whose key field is \"key\", the operator is \"In\",\n                                      and the values array contains only \"value\". The\n                                      requirements are ANDed.\n                                    type: object\n                                type: object\n                              namespaces:\n                                description: namespaces specifies a static list of namespace\n                                  names that the term applies to. The term is applied\n                                  to the union of the namespaces listed in this field\n                                  and the ones selected by namespaceSelector. null or\n                                  empty namespaces list and null namespaceSelector means\n                                  \"this pod's namespace\"\n                                items:\n                                  type: string\n                                type: array\n                              topologyKey:\n                                description: This pod should be co-located (affinity)\n                                  or not co-located (anti-affinity) with the pods matching\n                                  the labelSelector in the specified namespaces, where\n                                  co-located is defined as running on a node whose value\n                                  of the label with key topologyKey matches that of\n                                  any node on which any of the selected pods is running.\n                                  Empty topologyKey is not allowed.\n                                type: string\n                            required:\n                              - topologyKey\n                            type: object\n                          type: array\n                      type: object\n                    podAntiAffinity:\n                      description: Describes pod anti-affinity scheduling rules (e.g.\n                        avoid putting this pod in the same node, zone, etc. as some\n                        other pod(s)).\n                      properties:\n                        preferredDuringSchedulingIgnoredDuringExecution:\n                          description: The scheduler will prefer to schedule pods to\n                            nodes that satisfy the anti-affinity expressions specified\n                            by this field, but it may choose a node that violates one\n                            or more of the expressions. The node that is most preferred\n                            is the one with the greatest sum of weights, i.e. for each\n                            node that meets all of the scheduling requirements (resource\n                            request, requiredDuringScheduling anti-affinity expressions,\n                            etc.), compute a sum by iterating through the elements of\n                            this field and adding \"weight\" to the sum if the node has\n                            pods which matches the corresponding podAffinityTerm; the\n                            node(s) with the highest sum are the most preferred.\n                          items:\n                            description: The weights of all of the matched WeightedPodAffinityTerm\n                              fields are added per-node to find the most preferred node(s)\n                            properties:\n                              podAffinityTerm:\n                                description: Required. A pod affinity term, associated\n                                  with the corresponding weight.\n                                properties:\n                                  labelSelector:\n                                    description: A label query over a set of resources,\n                                      in this case pods.\n                                    properties:\n                                      matchExpressions:\n                                        description: matchExpressions is a list of label\n                                          selector requirements. The requirements are\n                                          ANDed.\n                                        items:\n                                          description: A label selector requirement\n                                            is a selector that contains values, a key,\n                                            and an operator that relates the key and\n                                            values.\n                                          properties:\n                                            key:\n                                              description: key is the label key that\n                                                the selector applies to.\n                                              type: string\n                                            operator:\n                                              description: operator represents a key's\n                                                relationship to a set of values. Valid\n                                                operators are In, NotIn, Exists and\n                                                DoesNotExist.\n                                              type: string\n                                            values:\n                                              description: values is an array of string\n                                                values. If the operator is In or NotIn,\n                                                the values array must be non-empty.\n                                                If the operator is Exists or DoesNotExist,\n                                                the values array must be empty. This\n                                                array is replaced during a strategic\n                                                merge patch.\n                                              items:\n                                                type: string\n                                              type: array\n                                          required:\n                                            - key\n                                            - operator\n                                          type: object\n                                        type: array\n                                      matchLabels:\n                                        additionalProperties:\n                                          type: string\n                                        description: matchLabels is a map of {key,value}\n                                          pairs. A single {key,value} in the matchLabels\n                                          map is equivalent to an element of matchExpressions,\n                                          whose key field is \"key\", the operator is\n                                          \"In\", and the values array contains only \"value\".\n                                          The requirements are ANDed.\n                                        type: object\n                                    type: object\n                                  namespaceSelector:\n                                    description: A label query over the set of namespaces\n                                      that the term applies to. The term is applied\n                                      to the union of the namespaces selected by this\n                                      field and the ones listed in the namespaces field.\n                                      null selector and null or empty namespaces list\n                                      means \"this pod's namespace\". An empty selector\n                                      ({}) matches all namespaces. This field is alpha-level\n                                      and is only honored when PodAffinityNamespaceSelector\n                                      feature is enabled.\n                                    properties:\n                                      matchExpressions:\n                                        description: matchExpressions is a list of label\n                                          selector requirements. The requirements are\n                                          ANDed.\n                                        items:\n                                          description: A label selector requirement\n                                            is a selector that contains values, a key,\n                                            and an operator that relates the key and\n                                            values.\n                                          properties:\n                                            key:\n                                              description: key is the label key that\n                                                the selector applies to.\n                                              type: string\n                                            operator:\n                                              description: operator represents a key's\n                                                relationship to a set of values. Valid\n                                                operators are In, NotIn, Exists and\n                                                DoesNotExist.\n                                              type: string\n                                            values:\n                                              description: values is an array of string\n                                                values. If the operator is In or NotIn,\n                                                the values array must be non-empty.\n                                                If the operator is Exists or DoesNotExist,\n                                                the values array must be empty. This\n                                                array is replaced during a strategic\n                                                merge patch.\n                                              items:\n                                                type: string\n                                              type: array\n                                          required:\n                                            - key\n                                            - operator\n                                          type: object\n                                        type: array\n                                      matchLabels:\n                                        additionalProperties:\n                                          type: string\n                                        description: matchLabels is a map of {key,value}\n                                          pairs. A single {key,value} in the matchLabels\n                                          map is equivalent to an element of matchExpressions,\n                                          whose key field is \"key\", the operator is\n                                          \"In\", and the values array contains only \"value\".\n                                          The requirements are ANDed.\n                                        type: object\n                                    type: object\n                                  namespaces:\n                                    description: namespaces specifies a static list\n                                      of namespace names that the term applies to. The\n                                      term is applied to the union of the namespaces\n                                      listed in this field and the ones selected by\n                                      namespaceSelector. null or empty namespaces list\n                                      and null namespaceSelector means \"this pod's namespace\"\n                                    items:\n                                      type: string\n                                    type: array\n                                  topologyKey:\n                                    description: This pod should be co-located (affinity)\n                                      or not co-located (anti-affinity) with the pods\n                                      matching the labelSelector in the specified namespaces,\n                                      where co-located is defined as running on a node\n                                      whose value of the label with key topologyKey\n                                      matches that of any node on which any of the selected\n                                      pods is running. Empty topologyKey is not allowed.\n                                    type: string\n                                required:\n                                  - topologyKey\n                                type: object\n                              weight:\n                                description: weight associated with matching the corresponding\n                                  podAffinityTerm, in the range 1-100.\n                                format: int32\n                                type: integer\n                            required:\n                              - podAffinityTerm\n                              - weight\n                            type: object\n                          type: array\n                        requiredDuringSchedulingIgnoredDuringExecution:\n                          description: If the anti-affinity requirements specified by\n                            this field are not met at scheduling time, the pod will\n                            not be scheduled onto the node. If the anti-affinity requirements\n                            specified by this field cease to be met at some point during\n                            pod execution (e.g. due to a pod label update), the system\n                            may or may not try to eventually evict the pod from its\n                            node. When there are multiple elements, the lists of nodes\n                            corresponding to each podAffinityTerm are intersected, i.e.\n                            all terms must be satisfied.\n                          items:\n                            description: Defines a set of pods (namely those matching\n                              the labelSelector relative to the given namespace(s))\n                              that this pod should be co-located (affinity) or not co-located\n                              (anti-affinity) with, where co-located is defined as running\n                              on a node whose value of the label with key <topologyKey>\n                              matches that of any node on which a pod of the set of\n                              pods is running\n                            properties:\n                              labelSelector:\n                                description: A label query over a set of resources,\n                                  in this case pods.\n                                properties:\n                                  matchExpressions:\n                                    description: matchExpressions is a list of label\n                                      selector requirements. The requirements are ANDed.\n                                    items:\n                                      description: A label selector requirement is a\n                                        selector that contains values, a key, and an\n                                        operator that relates the key and values.\n                                      properties:\n                                        key:\n                                          description: key is the label key that the\n                                            selector applies to.\n                                          type: string\n                                        operator:\n                                          description: operator represents a key's relationship\n                                            to a set of values. Valid operators are\n                                            In, NotIn, Exists and DoesNotExist.\n                                          type: string\n                                        values:\n                                          description: values is an array of string\n                                            values. If the operator is In or NotIn,\n                                            the values array must be non-empty. If the\n                                            operator is Exists or DoesNotExist, the\n                                            values array must be empty. This array is\n                                            replaced during a strategic merge patch.\n                                          items:\n                                            type: string\n                                          type: array\n                                      required:\n                                        - key\n                                        - operator\n                                      type: object\n                                    type: array\n                                  matchLabels:\n                                    additionalProperties:\n                                      type: string\n                                    description: matchLabels is a map of {key,value}\n                                      pairs. A single {key,value} in the matchLabels\n                                      map is equivalent to an element of matchExpressions,\n                                      whose key field is \"key\", the operator is \"In\",\n                                      and the values array contains only \"value\". The\n                                      requirements are ANDed.\n                                    type: object\n                                type: object\n                              namespaceSelector:\n                                description: A label query over the set of namespaces\n                                  that the term applies to. The term is applied to the\n                                  union of the namespaces selected by this field and\n                                  the ones listed in the namespaces field. null selector\n                                  and null or empty namespaces list means \"this pod's\n                                  namespace\". An empty selector ({}) matches all namespaces.\n                                  This field is alpha-level and is only honored when\n                                  PodAffinityNamespaceSelector feature is enabled.\n                                properties:\n                                  matchExpressions:\n                                    description: matchExpressions is a list of label\n                                      selector requirements. The requirements are ANDed.\n                                    items:\n                                      description: A label selector requirement is a\n                                        selector that contains values, a key, and an\n                                        operator that relates the key and values.\n                                      properties:\n                                        key:\n                                          description: key is the label key that the\n                                            selector applies to.\n                                          type: string\n                                        operator:\n                                          description: operator represents a key's relationship\n                                            to a set of values. Valid operators are\n                                            In, NotIn, Exists and DoesNotExist.\n                                          type: string\n                                        values:\n                                          description: values is an array of string\n                                            values. If the operator is In or NotIn,\n                                            the values array must be non-empty. If the\n                                            operator is Exists or DoesNotExist, the\n                                            values array must be empty. This array is\n                                            replaced during a strategic merge patch.\n                                          items:\n                                            type: string\n                                          type: array\n                                      required:\n                                        - key\n                                        - operator\n                                      type: object\n                                    type: array\n                                  matchLabels:\n                                    additionalProperties:\n                                      type: string\n                                    description: matchLabels is a map of {key,value}\n                                      pairs. A single {key,value} in the matchLabels\n                                      map is equivalent to an element of matchExpressions,\n                                      whose key field is \"key\", the operator is \"In\",\n                                      and the values array contains only \"value\". The\n                                      requirements are ANDed.\n                                    type: object\n                                type: object\n                              namespaces:\n                                description: namespaces specifies a static list of namespace\n                                  names that the term applies to. The term is applied\n                                  to the union of the namespaces listed in this field\n                                  and the ones selected by namespaceSelector. null or\n                                  empty namespaces list and null namespaceSelector means\n                                  \"this pod's namespace\"\n                                items:\n                                  type: string\n                                type: array\n                              topologyKey:\n                                description: This pod should be co-located (affinity)\n                                  or not co-located (anti-affinity) with the pods matching\n                                  the labelSelector in the specified namespaces, where\n                                  co-located is defined as running on a node whose value\n                                  of the label with key topologyKey matches that of\n                                  any node on which any of the selected pods is running.\n                                  Empty topologyKey is not allowed.\n                                type: string\n                            required:\n                              - topologyKey\n                            type: object\n                          type: array\n                      type: object\n                  type: object\n                args:\n                  items:\n                    type: string\n                  type: array\n                authConfig:\n                  description: AuthTlsConfig defines tls\n                  properties:\n                    enableTLS:\n                      type: boolean\n                    san:\n                      items:\n                        type: string\n                      type: array\n                    tlsSecret:\n                      type: string\n                  type: object\n                clusterType:\n                  description: provider, if has extra info, please use annotation to\n                    store\n                  type: string\n                description:\n                  type: string\n                diskSize:\n                  type: integer\n                diskType:\n                  type: string\n                env:\n                  items:\n                    description: EnvVar represents an environment variable present in\n                      a Container.\n                    properties:\n                      name:\n                        description: Name of the environment variable. Must be a C_IDENTIFIER.\n                        type: string\n                      value:\n                        description: 'Variable references $(VAR_NAME) are expanded using\n                        the previous defined environment variables in the container\n                        and any service environment variables. If a variable cannot\n                        be resolved, the reference in the input string will be unchanged.\n                        The $(VAR_NAME) syntax can be escaped with a double $$, ie:\n                        $$(VAR_NAME). Escaped references will never be expanded, regardless\n                        of whether the variable exists or not. Defaults to \"\".'\n                        type: string\n                      valueFrom:\n                        description: Source for the environment variable's value. Cannot\n                          be used if value is not empty.\n                        properties:\n                          configMapKeyRef:\n                            description: Selects a key of a ConfigMap.\n                            properties:\n                              key:\n                                description: The key to select.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the ConfigMap or its key\n                                  must be defined\n                                type: boolean\n                            required:\n                              - key\n                            type: object\n                          fieldRef:\n                            description: 'Selects a field of the pod: supports metadata.name,\n                            metadata.namespace, `metadata.labels[''<KEY>'']`, `metadata.annotations[''<KEY>'']`,\n                            spec.nodeName, spec.serviceAccountName, status.hostIP,\n                            status.podIP, status.podIPs.'\n                            properties:\n                              apiVersion:\n                                description: Version of the schema the FieldPath is\n                                  written in terms of, defaults to \"v1\".\n                                type: string\n                              fieldPath:\n                                description: Path of the field to select in the specified\n                                  API version.\n                                type: string\n                            required:\n                              - fieldPath\n                            type: object\n                          resourceFieldRef:\n                            description: 'Selects a resource of the container: only\n                            resources limits and requests (limits.cpu, limits.memory,\n                            limits.ephemeral-storage, requests.cpu, requests.memory\n                            and requests.ephemeral-storage) are currently supported.'\n                            properties:\n                              containerName:\n                                description: 'Container name: required for volumes,\n                                optional for env vars'\n                                type: string\n                              divisor:\n                                anyOf:\n                                  - type: integer\n                                  - type: string\n                                description: Specifies the output format of the exposed\n                                  resources, defaults to \"1\"\n                                pattern: ^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$\n                                x-kubernetes-int-or-string: true\n                              resource:\n                                description: 'Required: resource to select'\n                                type: string\n                            required:\n                              - resource\n                            type: object\n                          secretKeyRef:\n                            description: Selects a key of a secret in the pod's namespace\n                            properties:\n                              key:\n                                description: The key of the secret to select from.  Must\n                                  be a valid secret key.\n                                type: string\n                              name:\n                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names\n                                TODO: Add other useful fields. apiVersion, kind, uid?'\n                                type: string\n                              optional:\n                                description: Specify whether the Secret or its key must\n                                  be defined\n                                type: boolean\n                            required:\n                              - key\n                            type: object\n                        type: object\n                    required:\n                      - name\n                    type: object\n                  type: array\n                name:\n                  type: string\n                repository:\n                  type: string\n                size:\n                  type: integer\n                version:\n                  type: string\n              required:\n                - clusterType\n                - description\n                - diskSize\n                - diskType\n                - name\n                - size\n                - version\n              type: object\n            status:\n              description: EtcdClusterStatus defines the observed state of EtcdCluster\n              properties:\n                conditions:\n                  items:\n                    description: EtcdClusterCondition contains condition information\n                      for a EtcdCluster.\n                    properties:\n                      endTime:\n                        description: Last time the condition transit from one status\n                          to another.\n                        format: date-time\n                        type: string\n                      message:\n                        description: Human readable message indicating details about\n                          last transition.\n                        type: string\n                      reason:\n                        description: (brief) reason for the condition's last transition.\n                        type: string\n                      startTime:\n                        description: Last time we got an update on a given condition.\n                        format: date-time\n                        type: string\n                      status:\n                        description: Status of the condition, one of True, False, Unknown.\n                        type: string\n                      type:\n                        description: Type of EtcdCluster condition.\n                        type: string\n                    required:\n                      - status\n                      - type\n                    type: object\n                  type: array\n                featureGatesStatus:\n                  additionalProperties:\n                    type: string\n                  type: object\n                members:\n                  items:\n                    properties:\n                      clientUrl:\n                        type: string\n                      endpoint:\n                        type: string\n                      errors:\n                        items:\n                          type: string\n                        type: array\n                      extensionClientUrl:\n                        type: string\n                      memberId:\n                        type: string\n                      name:\n                        type: string\n                      port:\n                        type: string\n                      role:\n                        type: string\n                      status:\n                        type: string\n                      version:\n                        type: string\n                    required:\n                      - clientUrl\n                      - endpoint\n                      - extensionClientUrl\n                      - memberId\n                      - name\n                      - port\n                      - role\n                      - status\n                      - version\n                    type: object\n                  type: array\n                phase:\n                  type: string\n                serviceName:\n                  type: string\n              required:\n                - phase\n              type: object\n          type: object\n      served: true\n      storage: true\nstatus:\n  acceptedNames:\n    kind: EtcdCluster\n    plural: etcdclusters\n    singular: etcdcluster\n    shortNames:\n      - cluster\n  conditions: []\n  storedVersions: []\n"
  },
  {
    "path": "deploy/crds/kstone.tkestack.io_etcdinspections.yaml",
    "content": "\n---\napiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.4.1\n  creationTimestamp: null\n  name: etcdinspections.kstone.tkestack.io\nspec:\n  group: kstone.tkestack.io\n  names:\n    kind: EtcdInspection\n    listKind: EtcdInspectionList\n    plural: etcdinspections\n    singular: etcdinspection\n    shortNames:\n      - inspection\n  scope: Namespaced\n  versions:\n    - name: v1alpha2\n      schema:\n        openAPIV3Schema:\n          description: EtcdInspection is a specification for a EtcdInspection resource\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: EtcdInspectionSpec is the spec for a EtcdInspectionSpec resource\n              properties:\n                clusterName:\n                  type: string\n                intervalInSecond:\n                  type: integer\n                inspectionProvider:\n                  type: string\n                inspectionType:\n                  type: string\n              required:\n                - clusterName\n                - inspectionType\n              type: object\n            status:\n              properties:\n                elapsedTime:\n                  type: integer\n                message:\n                  type: string\n                reason:\n                  type: string\n                records:\n                  items:\n                    description: EtcdInspectionStatus is the status for a EtcdInspectionStatus\n                      resource\n                    properties:\n                      endTime:\n                        description: Last time the condition transit from one status\n                          to another.\n                        format: date-time\n                        type: string\n                      message:\n                        description: Human readable message indicating details about\n                          last transition.\n                        type: string\n                      reason:\n                        description: (brief) reason for the condition's last transition.\n                        type: string\n                      startTime:\n                        description: Last time we got an update on a given condition.\n                        format: date-time\n                        type: string\n                    type: object\n                  type: array\n                updatedAt:\n                  format: date-time\n                  type: string\n              type: object\n          type: object\n      served: true\n      storage: true\nstatus:\n  acceptedNames:\n    kind: \"\"\n    plural: \"\"\n  conditions: []\n  storedVersions: []\n"
  },
  {
    "path": "deploy/etcd-backup-operator.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: etcd-backup-operator\n  namespace: kstone\n  labels:\n    app: etcd-backup-operator\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: etcd-backup-operator\n  template:\n    metadata:\n      labels:\n        app: etcd-backup-operator\n    spec:\n      serviceAccountName: kstone-controller\n      containers:\n        - name: etcd-backup-operator\n          image: ccr.ccs.tencentyun.com/ccs-dev/etcd-operator:v1.0.4\n          imagePullPolicy: Always\n          command:\n            - etcd-backup-operator\n          env:\n            - name: MY_POD_NAMESPACE\n              valueFrom:\n                fieldRef:\n                  apiVersion: v1\n                  fieldPath: metadata.namespace\n            - name: MY_POD_NAME\n              valueFrom:\n                fieldRef:\n                  apiVersion: v1\n                  fieldPath: metadata.name"
  },
  {
    "path": "deploy/kstone-controller.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: kstone-etcdcluster-controller\n  namespace: kstone\n  labels:\n    app: kstone-etcdcluster-controller\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: kstone-etcdcluster-controller\n  template:\n    metadata:\n      labels:\n        app: kstone-etcdcluster-controller\n    spec:\n      serviceAccountName: kstone-controller\n      volumes:\n        - name: kstone-kubeconfig\n          secret:\n            secretName: kstone-kubeconfig\n      containers:\n        - name: kstone-etcdcluster-controller\n          image: mirrors.tencent.com/etcd/kstone-controller:dev\n          imagePullPolicy: Always\n          volumeMounts:\n            - name: kstone-kubeconfig\n              mountPath: \"/etc/kstone/config/kubeconfig\"\n              readOnly: true\n          args:\n            - etcdcluster\n            - --kubeconfig\n            - /etc/kstone/config/kubeconfig/default.yaml\n          command:\n            - /data/app\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: kstone-etcdinspection-controller\n  namespace: kstone\n  labels:\n    app: kstone-etcdinspection-controller\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: kstone-etcdinspection-controller\n  template:\n    metadata:\n      labels:\n        app: kstone-etcdinspection-controller\n    spec:\n      serviceAccountName: kstone-controller\n      volumes:\n        - name: kstone-kubeconfig\n          secret:\n            secretName: kstone-kubeconfig\n      containers:\n        - name: kstone-etcdinspection-controller\n          image: mirrors.tencent.com/etcd/kstone-controller:dev\n          imagePullPolicy: Always\n          volumeMounts:\n            - name: kstone-kubeconfig\n              mountPath: \"/etc/kstone/config/kubeconfig\"\n              readOnly: true\n          args:\n            - etcdinspection\n            - --kubeconfig\n            - /etc/kstone/config/kubeconfig/default.yaml\n          command:\n            - /data/app\n---\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: kstone-controller\n  namespace: kstone\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: kstone-controller\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: cluster-admin\nsubjects:\n  - kind: ServiceAccount\n    name: kstone-controller\n    namespace: kstone"
  },
  {
    "path": "docs/README.md",
    "content": "# Documentation\r\n\r\n[中文](README_CN.md)\r\n\r\nIn this page You can find kstone documentation.\r\n\r\n**Note**: The `master` branch may be in an *unstable or even broken state* during development. For stable versions, see [releases][releases].\r\n## Installation\r\nplease refer to [installation guide](installation)\r\n\r\n## Backup\r\nplease refer to [backup guide](backup)\r\n\r\n## Proposal\r\nplease refer to [proposal list](proposal)\r\n\r\n[releases]: https://github.com/tkestack/kstone/releases"
  },
  {
    "path": "docs/README_CN.md",
    "content": "# 文档\r\n\r\n[English](README.md)\r\n\r\n你可以在本页面找到 kstone 相关文档\r\n\r\n**注意**:  `master` 分支是开发中的 *非稳定* 版本。 对于稳定版本， 请看 [releases][releases].\r\n## 安装部署\r\n请参考 [安装文档](installation)\r\n\r\n## 备份\r\n请参考 [备份文档](backup)\r\n\r\n## 提案\r\n请参考 [提案](proposal)\r\n\r\n[releases]: https://github.com/tkestack/kstone/releases"
  },
  {
    "path": "docs/backup/cos/cos_en.md",
    "content": "# Backup guide for Tencent COS\r\n\r\n[中文](cos_zh.md)\r\n## 1 Preparation\r\n\r\n+ Prerequisites\r\n\r\n  - Kubernetes Cluster with kstone installed.\r\n  - Tencent cloud account with COS feature enabled. \r\n\r\n  \r\n\r\n# 2 Guide\r\n\r\n### Step 1: Access kstone-dashboard UI and Click \"Import Cluster\":\r\n\r\n![kstone-associate](../../images/images_for_backup_cos/en/kstone-associate.png)\r\n\r\n### Step 2: Associate etcd cluster with kstone:\r\n\r\nin this document we will use kubeadm managed etcd cluster \r\n\r\nfill the content and click \"Submit\"\r\n\r\n![kstone-associate](../../images/images_for_backup_cos/en/kstone-associate2.png)\r\n\r\n![kstone-associate](../../images/images_for_backup_cos/en/kstone-associate3.png)\r\n\r\nCluster Name : etcd cluster name，uniqueKey\r\n\r\nCluster Description : description about this cluster\r\n\r\nFor Kubernetes : Is this cluster used by kubernetes\r\n\r\nAccess Method :  the access method of etcd, if choose HTTPS, etcd certificate and key should be provided.\r\n\r\nCPU Cores :  single node's CPU, unit: Core\r\n\r\nMemory Size : single node's mem, unit: GiB\r\n\r\nDisk type : disk type, CLOUD_SSD/CLOUD_PREMIUM/CLOUD_BASIC\r\n\r\nDisk size : single node's disk size, unit: GB\r\n\r\nCluster Size : etcd cluster member count: support 1, 3, 5, 7\r\n\r\nCluster Node Mapping : the private and public address of etcd cluster, omit if not used\r\n\r\nCA Certificate : the ca certificate of etcd cluster\r\n\r\nClient Certificate :  the client certificate of etcd cluster\r\n\r\nClient Private Key : the client key of etcd cluster\r\n\r\nDescription : etcd description\r\n\r\n### Step3: Enable BACKUP feature\r\n\r\n![kstone-enable-backup](../../images/images_for_backup_cos/en/kstone-enable-backup.png)\r\n\r\nnow we have a working etcd cluster, it's time for us to enable the backup feature.\r\n\r\n+ We need to get the Tencent cloud COS SecretId and SecretKey and bucket first \r\n  - open and login to  the Tencent cloud  COS website: https://console.cloud.tencent.com/cos5\r\n  - if not enabled, please enable this feature\r\n  - create a bucket and save the bucket URL path\r\n  - open and login to the Tencent cloud cam website: https://console.cloud.tencent.com/cam\r\n  - create a user with QcloudCOSDataFullControl permission  and save the secretId and SecretKey\r\n\r\n+ Let's head back to the kstone-dashboard\r\n\r\n  - click \"Operation\"\r\n\r\n  - click \"Cluster Feature\"\r\n\r\n  - toggle \"Backup:\"\r\n\r\n  - fill below parameters\r\n\r\n  - BackupIntervalInSecond determines how often the backup-operator will start an etcd backup job\r\n\r\n  - MaxBackups is the maximum backup count you want to keep in the COS bucket, if your backup file count exceeds this number, backup-operator will delete old file by time order.\r\n\r\n  - TimeoutInSecond is the timeout second for backup-operator\r\n\r\n  - SecretId is the secret id copied from the previous step\r\n\r\n  - SecretKey is the secret key copied from the previous step\r\n\r\n  - Path:\r\n\r\n  # important!!! \r\n\r\n  you need to fill this parameter without https:// and with / and backup file prefix you want\r\n\r\n  if your COS bucket URL  address is https://etcd-bakcup-XXXXXXX.cos.ap-guangzhou.myqcloud.com and you want your backup file prefix to be like my-first-cluster, you need to fill the path like below:\r\n\r\n  #### etcd-bakcup-XXXXXXX.cos.ap-guangzhou.myqcloud.com/my-first-cluster\r\n\r\n\r\n\r\n![kstone-enable-backup](../../images/images_for_backup_cos/en/kstone-enable-backup2.png)\r\n![kstone-enable-backup](../../images/images_for_backup_cos/en/kstone-enable-backup3.png)\r\n![kstone-enable-backup](../../images/images_for_backup_cos/en/kstone-enable-backup4.png)\r\n\r\n\r\n+ wait BackupIntervalInSecond  and check the COS bucket\r\n\r\n![kstone-enable-backup](../../images/images_for_backup_cos/en/kstone-enable-backup5.png)\r\n\r\nYou will find an etcd backup file with the prefix you specified in the previous step."
  },
  {
    "path": "docs/backup/cos/cos_zh.md",
    "content": "#  腾讯COS备份参考\r\n\r\n[English](cos_en.md)\r\n## 1 准备工作\r\n\r\n+ 前提条件\r\n\r\n  - 安装好kstone的Kubernetes集群.\r\n  - 开启COS功能的腾讯云账号. \r\n\r\n  \r\n\r\n# 2 参考\r\n\r\n### 步骤1: 打开 kstone-dashboard UI 然后点击 \"导入集群\":\r\n\r\n![kstone-associate](../../images/images_for_backup_cos/zh/kstone-associate.png)\r\n\r\n### 步骤 2: 导入etcd集群到kstone:\r\n\r\n本文档将会使用kubeadm管理的etcd集群\r\n\r\n填好下面的内容然后 \"提交\"\r\n\r\n![kstone-associate](../../images/images_for_backup_cos/zh/kstone-associate2.png)\r\n\r\n![kstone-associate](../../images/images_for_backup_cos/zh/kstone-associate3.png)\r\n集群名称: etcd集群的名称，唯一键\r\n\r\n集群备注: 集群的备注名称\r\n\r\n用于Kubernetes: 该集群是否用于Kubernetes\r\n\r\n访问方式:  etcd的访问方式, 如果是 HTTPS, 需要提供相应的证书还有秘钥\r\n\r\nCPU核数:  单个节点的CPU, 单位: Core\r\n\r\n内存大小:单个节点的内存, 单位: GiB\r\n\r\n磁盘类型: 磁盘种类, 比如CLOUD_SSD/CLOUD_PREMIUM/CLOUD_BASIC\r\n\r\n磁盘大小: 单个节点的磁盘大小, 单位: GB\r\n\r\n集群规模: etcd集群成员数量: 支持1, 3, 5, 7\r\n\r\n集群节点映射: etcd集群的内网还有外网地址, 如果不用可以省略\r\n\r\nCA证书: etcd集群的CA证书\r\n\r\n客户端证书:  etcd集群的客户端证书\r\n\r\n客户端私钥: etcd集群的客户端私钥\r\n\r\n描述: etcd的描述\r\n\r\n### 步骤 3: 开启备份功能\r\n\r\n![kstone-enable-backup](../../images/images_for_backup_cos/zh/kstone-enable-backup.png)\r\n\r\n现在我们有了一个状态正常的etcd集群, 让我们来开启备份功能.\r\n\r\n+ 我们首先需要拿到腾讯云COS的SecretId还有SecretKey还有bucket\r\n  - 打开并登录腾讯云COS对象存储网站: https://console.cloud.tencent.com/cos5\r\n  - 如果没有开启该功能，请开启\r\n  - 创建一个bucket然后保存下该bucket的URL路径\r\n  - 打开并登录腾讯云CAM对象存储网站: https://console.cloud.tencent.com/cam\r\n  - 创建一个具有QcloudCOSDataFullControl权限的用户并且保存下该用户的SecretId还有SecretKey\r\n\r\n+ 让我们回到 kstone-dashboard\r\n\r\n  - 点击 \"操作\"\r\n\r\n  - 点击 \"集群功能项\"\r\n\r\n  - 点击 \"Backup:\"\r\n\r\n  - 填好下面的参数\r\n\r\n  - BackupIntervalInSecond 决定了多久backup-operator会进行一次etcd备份工作\r\n\r\n  - MaxBackups 是你想要存放的etcd备份文件的最大数量,如果备份超过了这个数量，backup-operator会按时间顺序删掉多余的旧的备份文件。\r\n\r\n  - TimeoutInSecond 是 backup-operator的超时时间\r\n\r\n  - SecretId 是之前步骤保存下来的SecretId \r\n\r\n  - SecretKey 是之前步骤保存下来的SecretKey \r\n\r\n  - Path:\r\n\r\n  # 重要!!! \r\n\r\n  你首先需要去掉 https:// 然后加上  / 还有你想要的文件的备份前缀\r\n\r\n  如果你的COS bucket URL 地址是 https://etcd-bakcup-XXXXXXX.cos.ap-guangzhou.myqcloud.com \r\n\r\n  然后你想要你的备份文件的前缀是my-first-cluster, 你需要像下面一样填好path:\r\n\r\n  #### etcd-bakcup-XXXXXXX.cos.ap-guangzhou.myqcloud.com/my-first-cluster\r\n\r\n\r\n\r\n![kstone-enable-backup](../../images/images_for_backup_cos/zh/kstone-enable-backup2.png)\r\n![kstone-enable-backup](../../images/images_for_backup_cos/zh/kstone-enable-backup3.png)\r\n![kstone-enable-backup](../../images/images_for_backup_cos/zh/kstone-enable-backup4.png)\r\n\r\n\r\n+ 等待BackupIntervalInSecond秒然后检查 COS bucket\r\n\r\n![kstone-enable-backup](../../images/images_for_backup_cos/zh/kstone-enable-backup5.png)\r\n\r\n你会发现一个带有之前指定前缀的etcd备份文件"
  },
  {
    "path": "docs/installation/kubeadm_en.md",
    "content": "# Kstone Installation\t\r\n\r\n## 1 Preparation\r\n\r\n- Prerequisites\r\n  - Kubernetes version is between 1.14 and 1.20.\r\n  - The version of Prometheus Operator is v0.49.0.\r\n- Requirements：\r\n  - For production environment (recommended): Worker >= 4 vCPU 8 GB of Memory.\r\n  - For test environment (minimum): Worker >= 2 vCPU 2 GB of Memory.\r\n\r\n## 2 Install kubeadm and CNI Plugin\r\n\r\nyou can check below guide\r\n\r\nhttps://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/\r\n\r\n## 3 Deploy\r\n\r\n- 3.1 Modify Helm Configuration\r\n\r\n  ### Step 1：\r\n\r\n  - Install helm:\r\n\r\n  Please refer to [helm installation](https://helm.sh/docs/intro/install/) or just directly download and install\r\n\r\n```bash\r\n  wget https://get.helm.sh/helm-v3.7.2-linux-amd64.tar.gz \r\n  tar -zxvf helm-v3.7.2-linux-amd64.tar.gz\r\n  mv linux-amd64/helm /usr/local/bin/helm\r\n```\r\n  \r\n  - Install git:\r\n  \r\n```bash\r\n    yum -y install git\r\n```\r\n\r\n  - Download Helm Repo:\r\n  \r\n```bash\r\n  git clone -b release-0.2 git@github.com:tkestack/kstone.git\r\n  cd kstone\r\n  cd ./charts\r\n```\r\n\r\n####       Step 2：\r\n\r\n- Create Admin TOKEN for dashboard-api to access Kubernetes\r\n\r\n```bash\r\n  kubectl create serviceaccount kube-admin -n kube-system\r\n  kubectl create clusterrolebinding kube-admin --clusterrole=cluster-admin --serviceaccount=kube-system:kube-admin\r\n```\r\n\r\n- Get Admin TOKEN from Kubeadm cluster\r\n\r\n```\r\nkubectl get secrets -o jsonpath=\"{.items[?(@.metadata.annotations['kubernetes\\.io/service-account\\.name']=='kube-admin')].data.token}\" -n kube-system|base64 --decode\r\n```\r\n\r\n- Fill in the TOKEN of the cluster to deploy.\r\n\r\n```\r\n// charts/charts/dashboard-api/values.yaml\r\n\r\nkube:\r\n  token: $token\r\n  target: kubernetes.default.svc.cluster.local:443\r\n```\r\n\r\n- Requirements：\r\n  - $token is the access credential TOKEN of the cluster to be deployed.\r\n  - $token needs to have access to all resources in the cluster.\r\n\r\n#### Step 3: Using the existing Prometheus Operator (optional)\r\n\r\n- Set `prometheusOperator.enabled=false` in the file `charts/charts/kube-prometheus-stack/values.yaml`.\r\n- Set `prometheus.enabled=false` in the file `charts/charts/kube-prometheus-stack/values.yaml`.\r\n- Modify the file: `charts/charts/grafana/templates/configmap.yaml`, replace `http://{{ .Release.Name }}-prometheus-prometheus.{{ .Release.Namespace }}.svc.cluster.local:9090` to the query URL from the existing Prometheus Operator.\r\n\r\n### 3.2 Install\r\n\r\n- Create kstone namespace\r\n\r\n```bash\r\nkubectl create ns kstone\r\n```\r\n\r\n- Helm install for production environment\r\n\r\n```bash\r\ncd charts/\r\nhelm install kstone . -n kstone -f values.yaml\r\n```\r\n\r\nor\r\n\r\n- Helm install for test environment\r\n\r\n```bash\r\ncd charts/\r\nhelm install kstone . -n kstone -f values.test.yaml\r\n```\r\n\r\n- Delete Ingress Rule\r\n\r\n```bash\r\n  kubectl delete ingress kstone -n kstone\r\n```\r\n\r\n- Create a new Ingress Rule\r\n\r\n```yaml\r\ncat <<EOF | kubectl apply -f -\r\napiVersion: networking.k8s.io/v1\r\nkind: Ingress\r\nmetadata:\r\n  name: kstone-ingress\r\n  namespace: kstone\r\n  annotations:\r\n    kubernetes.io/ingress.class: nginx\r\nspec:\r\n  rules:\r\n    - http:\r\n        paths:\r\n          - path: /\r\n            pathType: Prefix\r\n            backend:\r\n              service:\r\n                name: kstone-dashboard\r\n                port:\r\n                  number: 80\r\n          - path: /apis\r\n            pathType: Prefix\r\n            backend:\r\n              service:\r\n                name: kstone-dashboard-api\r\n                port:\r\n                  number: 80\r\n          - path: /grafana\r\n            pathType: Prefix\r\n            backend:\r\n              service:\r\n                name: kstone-grafana\r\n                port:\r\n                  number: 80\r\nEOF\r\n```\r\n\r\n- Install nginx-ingress\r\n\r\n  check https://kubernetes.github.io/ingress-nginx/deploy/#quick-start  or just\r\n\r\n```bash\r\n  kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.0/deploy/static/provider/baremetal/deploy.yaml\r\n```\r\n\r\n- Expose Ingress Port\r\n\r\n```bash\r\nkubectl port-forward deployment/ingress-nginx-controller 8080:80 --namespace ingress-nginx --address 0.0.0.0\r\n```\r\n\r\n  or You can directly access the NodePort of ingress-nginx-controller\r\n\r\n```bash\r\n[root@kstone charts]# kubectl get svc -n ingress-nginx\r\nNAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE\r\ningress-nginx-controller             NodePort    10.104.79.160   <none>        80:30700/TCP,443:31221/TCP   40h\r\ningress-nginx-controller-admission   ClusterIP   10.105.48.164   <none>        443/TCP        \r\n```\r\n\r\n- Visit kstone dashboard `http://<VM IP address>:8080` or the ingress NodePort address in the browser  \r\n\r\n- ### important: Do not access the dashboard directly!!!\r\n\r\n![Kstone Overview](../images/kstone-overview.png)\r\n\r\n- Create an ETCD cluster\r\n\r\n![Kstone Overview](../images/kstone-etcd-cluster-create.png)\r\n\r\n- Cluster is Running\r\n\r\n![Kstone Cluster Running](../images/kstone-etcd-cluster-running.png)\r\n\r\n### 3.3 Update\r\n\r\n- Helm upgrade for production environment\r\n\r\n```bash\r\ncd charts\r\n\r\nhelm upgrade kstone . -n kstone -f values.yaml\r\n```\r\n\r\nor\r\n\r\n- Helm upgrade for test environment\r\n\r\n```bash\r\ncd charts\r\n\r\nhelm upgrade kstone . -n kstone -f values.test.yaml\r\n```\r\n\r\n### 3.4 Uninstall\r\n\r\n```bash\r\nhelm uninstall kstone -n kstone\r\n\r\nkubectl delete crd alertmanagerconfigs.monitoring.coreos.com\r\nkubectl delete crd alertmanagers.monitoring.coreos.com\r\nkubectl delete crd podmonitors.monitoring.coreos.com\r\nkubectl delete crd probes.monitoring.coreos.com\r\nkubectl delete crd prometheuses.monitoring.coreos.com\r\nkubectl delete crd prometheusrules.monitoring.coreos.com\r\nkubectl delete crd servicemonitors.monitoring.coreos.com\r\nkubectl delete crd thanosrulers.monitoring.coreos.com\r\nkubectl delete crd etcdclusters.kstone.tkestack.io\r\nkubectl delete crd etcdinspections.kstone.tkestack.io\r\n```\r\n\r\n- Uninstall Kubeadm \r\n\r\n  https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-reset/\r\n\r\n"
  },
  {
    "path": "docs/installation/minikube-amd64.md",
    "content": "# Kstone Installation\n\n\n## 1 Preparation\n\n- Prerequisites\n  - Kubernetes version is between 1.14 and 1.20.\n  - The version of Prometheus Operator is v0.49.0.\n- Requirements：\n  - For production environment (recommended): Worker >= 4 vCPU 8 GB of Memory.\n  - For test environment (minimum): Worker >= 2 vCPU 2 GB of Memory.\n  - Can access the managed etcd.\n\n## 2 Install Minikube\n\n#### Step 1：\n\n- Switch to non-root User \n```shell\nadduser kstone\n# set password for kstone user\npasswd kstone\n\nsu - kstone\n\nsudo groupadd docker\n\nsudo usermod -aG docker $USER\n\n# Re-Login and Restart the Docker Server\nsystemctl restart docker\n```\n\n#### Step 2：\n- [Install Minikube](https://minikube.sigs.k8s.io/docs/start/) (e.g. Linux amd64)\n    - Requirements：version <= 1.20.x\n```shell\nVERSION=v1.20.0\ncurl -LO https://github.com/kubernetes/minikube/releases/download/${VERSION}/minikube-linux-amd64\nsudo install minikube-linux-amd64 /usr/local/bin/minikube\nminikube start --driver=docker\n```\n\n\n\n- Alias `minikube kubectl`\n```shell\nalias kubectl=\"minikube kubectl --\"\n```\n#### Step 3:\n\n- Deploy ingress controller\n```shell\nminikube addons enable ingress\n```\n\n## 3 Deploy\n\n### 3.1 Modify Helm Configuration\n\n#### Step 1：\n- Install helm:\n\nPlease refer to [helm installation](https://helm.sh/docs/intro/install/)\n\n- Download Helm Repo:\n\n``` shell\ngit clone -b release-0.2 git@github.com:tkestack/kstone.git\ncd ./charts\n```\n\n#### Step 2：\n\n- Get Admin TOKEN from Minikube cluster\n\n```shell\nkubectl get secrets -o jsonpath=\"{.items[?(@.metadata.annotations['kubernetes\\.io/service-account\\.name']=='default')].data.token}\" -n kube-system|base64 --decode\n```\n\n- Fill in the TOKEN of the cluster to deploy.\n\n``` yaml\n// charts/charts/dashboard-api/values.yaml\n\nkube:\n  token: $token\n  target: kubernetes.default.svc.cluster.local:443\n```\n\n- Requirements：\n    - $token is the access credential TOKEN of the cluster to be deployed.\n    - $token needs to have access to all resources in the cluster.\n\n#### Step 3: Using the existing Prometheus Operator (optional)\n\n- Set `prometheusOperator.enabled=false` in the file `charts/charts/kube-prometheus-stack/values.yaml`.\n- Set `prometheus.enabled=false` in the file `charts/charts/kube-prometheus-stack/values.yaml`.\n- Modify the file: `charts/charts/grafana/templates/configmap.yaml`, replace `http://{{ .Release.Name }}-prometheus-prometheus.{{ .Release.Namespace }}.svc.cluster.local:9090` to the query URL from the existing Prometheus Operator.\n\n### 3.2 Install\n\n- Create kstone namespace\n\n``` shell\nkubectl create ns kstone\n```\n\n- Helm install for production environment\n```shell\ncd charts/\nhelm install kstone . -n kstone -f values.yaml\n```\n\nor\n\n- Helm install for test environment\n\n```shell\ncd charts/\nhelm install kstone . -n kstone -f values.test.yaml\n```\n\n- Create Ingress Rule\n  \n```shell\ncat <<EOF | kubectl apply -f -\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n  name: kstone-ingress\n  namespace: kstone\nspec:\n  rules:\n    - http:\n        paths:\n          - path: /\n            pathType: Prefix\n            backend:\n              service:\n                name: kstone-dashboard\n                port:\n                  number: 80\n          - path: /apis\n            pathType: Prefix\n            backend:\n              service:\n                name: kstone-dashboard-api\n                port:\n                  number: 80\n          - path: /grafana\n            pathType: Prefix\n            backend:\n              service:\n                name: kstone-grafana\n                port:\n                  number: 80\nEOF\n```\n\n- Expose Ingress Port\n```shell\nkubectl port-forward deployment/ingress-nginx-controller 8080:80 --namespace ingress-nginx --address 0.0.0.0\n```\n\n- Visit kstone dashboard `http://<VM IP address>:8080` in the browser\n\n![Kstone Overview](../images/kstone-overview.png)\n\n- Create an ETCD cluster\n\n![Kstone Overview](../images/kstone-etcd-cluster-create.png)\n\n- Cluster is Running\n\n![Kstone Cluster Running](../images/kstone-etcd-cluster-running.png)\n\n### 3.3 Update\n\n- Helm upgrade for production environment\n\n``` shell\ncd charts\n\nhelm upgrade kstone . -n kstone -f values.yaml\n```\n\nor\n\n- Helm upgrade for test environment\n\n``` shell\ncd charts\n\nhelm upgrade kstone . -n kstone -f values.test.yaml\n```\n\n### 3.4 Uninstall\n\n``` shell\nhelm uninstall kstone -n kstone\n\nkubectl delete crd alertmanagerconfigs.monitoring.coreos.com\nkubectl delete crd alertmanagers.monitoring.coreos.com\nkubectl delete crd podmonitors.monitoring.coreos.com\nkubectl delete crd probes.monitoring.coreos.com\nkubectl delete crd prometheuses.monitoring.coreos.com\nkubectl delete crd prometheusrules.monitoring.coreos.com\nkubectl delete crd servicemonitors.monitoring.coreos.com\nkubectl delete crd thanosrulers.monitoring.coreos.com\nkubectl delete crd etcdclusters.kstone.tkestack.io\nkubectl delete crd etcdinspections.kstone.tkestack.io\n```\n- Uninstall Minikube\n```shell\nminikube stop && minikube delete\n```"
  },
  {
    "path": "docs/installation/minikube-macos.md",
    "content": "# Kstone Installation\n\n## 1 Preparation\n\n- Prerequisites\n  - Kubernetes version is between 1.14 and 1.20.\n  - The version of Prometheus Operator is v0.49.0.\n- Requirements：\n  - For production environment (recommended): Worker >= 4 vCPU 8 GB of Memory.\n  - For test environment (minimum): Worker >= 2 vCPU 2 GB of Memory.\n  - Can access the managed etcd.\n\n## 2 Install Minikube\n\n#### Step 1：\n\n- [Install VirtualBox](https://www.virtualbox.org/wiki/Downloads)\n\n- [Configure Virtual Box Network](https://www.virtualbox.org/manual/ch06.html#network_hostonly) (Allow 10.0.0.0/8 and 192.168.0.0/16 IPv4 ranges)\n```shell\nsudo mkdir -p /etc/vbox && sudo bash -c \"cat  > /etc/vbox/networks.conf\" << EOF\n      * 10.0.0.0/8 192.168.0.0/16\n      * 2001::/64\nEOF\n```\n\n#### Step 2：\n- [Install Minikube](https://minikube.sigs.k8s.io/docs/start/) (e.g. Mac OSX)\n    - Requirements：version <= 1.20.x\n```shell\nVERSION=v1.20.0\ncurl -LO https://github.com/kubernetes/minikube/releases/download/${VERSION}/minikube-darwin-amd64\nsudo install minikube-darwin-amd64 /usr/local/bin/minikube\nminikube start --vm-driver=virtualbox\n```\n\n#### Step 3：\n\n- Alias `minikube kubectl`\n```shell\nalias kubectl=\"minikube kubectl --\"\n```\n#### Step 4:\n\n- Deploy ingress controller\n```shell\nminikube addons enable ingress\n```\n\n## 3 Deploy\n\n### 3.1 Modify Helm Configuration\n\n#### Step 1：\n- Install helm:\n\nPlease refer to [helm installation](https://helm.sh/docs/intro/install/)\n\n- Download Helm Repo:\n\n``` shell\ngit clone -b release-0.2 git@github.com:tkestack/kstone.git\ncd ./charts\n```\n\n#### Step 2：\n\n- Get Admin TOKEN from Minikube cluster\n\n```shell\nkubectl get secrets -o jsonpath=\"{.items[?(@.metadata.annotations['kubernetes\\.io/service-account\\.name']=='default')].data.token}\" -n kube-system|base64 --decode\n```\n\n- Fill in the TOKEN of the cluster to deploy.\n\n``` yaml\n// charts/charts/dashboard-api/values.yaml\n\nkube:\n  token: $token\n  target: kubernetes.default.svc.cluster.local:443\n```\n\n- Requirements：\n    - $token is the access credential TOKEN of the cluster to be deployed.\n    - $token needs to have access to all resources in the cluster.\n\n#### Step 3: Using the existing Prometheus Operator (optional)\n\n- Set `prometheusOperator.enabled=false` in the file `charts/charts/kube-prometheus-stack/values.yaml`.\n- Set `prometheus.enabled=false` in the file `charts/charts/kube-prometheus-stack/values.yaml`.\n- Modify the file: `charts/charts/grafana/templates/configmap.yaml`, replace `http://{{ .Release.Name }}-prometheus-prometheus.{{ .Release.Namespace }}.svc.cluster.local:9090` to the query URL from the existing Prometheus Operator.\n\n### 3.2 Install\n\n- Create kstone namespace\n\n``` shell\nkubectl create ns kstone\n```\n- Helm install for production environment\n\n```shell\ncd charts/\nhelm install kstone . -n kstone -f values.yaml\n```\n\nor\n\n- Helm install for test environment\n\n```shell\ncd charts/\nhelm install kstone . -n kstone -f values.test.yaml\n```\n\n- Create Ingress Rule\n  \n```shell\ncat <<EOF | kubectl apply -f -\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n  name: kstone-ingress\n  namespace: kstone\nspec:\n  rules:\n    - http:\n        paths:\n          - path: /\n            pathType: Prefix\n            backend:\n              service:\n                name: kstone-dashboard\n                port:\n                  number: 80\n          - path: /apis\n            pathType: Prefix\n            backend:\n              service:\n                name: kstone-dashboard-api\n                port:\n                  number: 80\n          - path: /grafana\n            pathType: Prefix\n            backend:\n              service:\n                name: kstone-grafana\n                port:\n                  number: 80\nEOF\n```\n\n- Expose Ingress Port\n```shell\nkubectl port-forward deployment/ingress-nginx-controller 8080:80 --namespace ingress-nginx --address 0.0.0.0\n```\n\n- Visit kstone dashboard `http://127.0.0.1:8080` in the browser\n\n![Kstone Overview](../images/kstone-overview.png)\n\n- Create an ETCD cluster\n\n![Kstone Overview](../images/kstone-etcd-cluster-create.png)\n\n- Cluster is Running\n\n![Kstone Cluster Running](../images/kstone-etcd-cluster-running.png)\n\n### 3.3 Update\n\n- Helm upgrade for production environment\n\n``` shell\ncd charts\n\nhelm upgrade kstone . -n kstone -f values.yaml\n```\n\nor\n\n- Helm upgrade for test environment\n\n``` shell\ncd charts\n\nhelm upgrade kstone . -n kstone -f values.test.yaml\n```\n\n### 3.4 Uninstall\n\n- Uninstall Kstone\n``` shell\nhelm uninstall kstone -n kstone\n\nkubectl delete crd alertmanagerconfigs.monitoring.coreos.com\nkubectl delete crd alertmanagers.monitoring.coreos.com\nkubectl delete crd podmonitors.monitoring.coreos.com\nkubectl delete crd probes.monitoring.coreos.com\nkubectl delete crd prometheuses.monitoring.coreos.com\nkubectl delete crd prometheusrules.monitoring.coreos.com\nkubectl delete crd servicemonitors.monitoring.coreos.com\nkubectl delete crd thanosrulers.monitoring.coreos.com\nkubectl delete crd etcdclusters.kstone.tkestack.io\nkubectl delete crd etcdinspections.kstone.tkestack.io\n```\n- Uninstall Minikube\n```shell\nminikube stop && minikube delete\n```"
  },
  {
    "path": "docs/installation/tke.md",
    "content": "# Kstone Installation\n\n[中文](README_CN.md)\n\n## 1 Preparation\n\n- Prerequisites\n  - Kubernetes version is between 1.14 and 1.20.\n  - The version of Prometheus Operator is v0.49.0.\n- Apply for a cluster from [TKE](https://cloud.tencent.com/product/tke).\n- Requirements：\n  - For production environment (recommended): Worker >= 4 vCPU 8 GB of Memory.\n  - For test environment (minimum): Worker >= 2 vCPU 2 GB of Memory.\n  - Can access the managed etcd.\n\n## 2 Deploy\n\n### 2.1 Modify Helm Configuration\n\n#### Step 1：\n- Install helm:\n  \nPlease refer to [helm installation](https://helm.sh/docs/intro/install/)\n\n- Download Helm Repo:\n\n``` shell\ngit clone -b release-0.2 git@github.com:tkestack/kstone.git\ncd ./charts\n```\n\n- Modify Setting:\n\n``` yaml\n// charts/values.yaml\n\ningress:\n  enabled: true\n  className: \"\"\n  annotations:\n    nginx.ingress.kubernetes.io/rewrite-target: /$2\n    service.cloud.tencent.com/direct-access: 'false'\n    kubernetes.io/ingress.class: qcloud\n    service.kubernetes.io/tke-existed-lbid: $lb\n    kubernetes.io/ingress.existLbId: $lb\n    kubernetes.io/ingress.subnetId: $subnet\n```\n\nMethod 1: Use existing LB\n\nRefer to the above configuration and fill in the $lb and $subnet under the same VPC of the TKE cluster.\n\nMethod 2: Do not use existing LB\n\nDelete the following configurations:\n\n- ingress.annotations.service.kubernetes.io/tke-existed-lbid\n- kubernetes.io/ingress.existLbId\n- kubernetes.io/ingress.subnetId\n\n#### Step 2：\n\n- Get Admin TOKEN from TKE cluster\n\n```shell\nkubectl get secrets -o jsonpath=\"{.items[?(@.metadata.annotations['kubernetes\\.io/service-account\\.name']=='kube-admin')].data.token}\" -n kube-system|base64 --decode\n```\n- Fill in the TOKEN of the cluster to deploy.\n\n``` yaml\n// charts/charts/dashboard-api/values.yaml\n\nkube:\n  token: $token\n  target: kubernetes.default.svc.cluster.local:443\n```\n\n- Requirements：\n    - $token is the access credential TOKEN of the TKE cluster to be deployed.\n    - $token needs to have access to all resources in the cluster.\n\n#### Step 3: Using the existing Prometheus Operator (optional)\n\n- Set `prometheusOperator.enabled=false` in the file `charts/charts/kube-prometheus-stack/values.yaml`.\n- Set `prometheus.enabled=false` in the file `charts/charts/kube-prometheus-stack/values.yaml`.\n- Modify the file: `charts/charts/grafana/templates/configmap.yaml`, replace `http://{{ .Release.Name }}-prometheus-prometheus.{{ .Release.Namespace }}.svc.cluster.local:9090` to the query URL from the existing Prometheus Operator.\n\n### 2.2 Install\n\n- Create kstone namespace\n\n``` shell\nkubectl create ns kstone\n```\n- Helm install for production environment\n\n```shell\ncd charts/\nhelm install kstone . -n kstone -f values.yaml\n```\n\nor\n\n- Helm install for test environment\n\n```shell\ncd charts/\nhelm install kstone . -n kstone -f values.test.yaml\n```\n\n### 2.3 Update\n\n- Helm upgrade for production environment\n\n```bash\ncd charts\n\nhelm upgrade kstone . -n kstone -f values.yaml\n```\n\nor\n\n- Helm upgrade for test environment\n\n```bash\ncd charts\n\nhelm upgrade kstone . -n kstone -f values.test.yaml\n```\n\n### 2.4 Uninstall\n\n``` shell\nhelm uninstall kstone -n kstone\n\nkubectl delete crd alertmanagerconfigs.monitoring.coreos.com\nkubectl delete crd alertmanagers.monitoring.coreos.com\nkubectl delete crd podmonitors.monitoring.coreos.com\nkubectl delete crd probes.monitoring.coreos.com\nkubectl delete crd prometheuses.monitoring.coreos.com\nkubectl delete crd prometheusrules.monitoring.coreos.com\nkubectl delete crd servicemonitors.monitoring.coreos.com\nkubectl delete crd thanosrulers.monitoring.coreos.com\nkubectl delete crd etcdclusters.kstone.tkestack.io\nkubectl delete crd etcdinspections.kstone.tkestack.io\n```"
  },
  {
    "path": "docs/migration/README.md",
    "content": "# API v1alpha2 Migration (Imported ETCD Clusters Only)\n\n## 1 Preparation\n\n- Prerequisites\n    - Already installed the [release-0.1.0](https://github.com/tkestack/kstone/releases/tag/v0.1.0-alpha.2) or lower version kstone.\n    - Already installed kubectl and set up the kubeconfig in /root/.kube/config for kstone cluster.\n    \n> **Risk Warning:**\n> \n> Migrating API from v1alpha1 to v1alpha2 will delete the existing clusters from kstone.\n> \n> Please notice this migration document is only for **Imported etcd** etcd clsuters migration.\n\n## 2 Backup and Recreate the cluster and secret from v1alpha1 API\n\nRun the migration script:\n\n```shell\n./hack/migratev1.sh\n```\n\nthe outputs:\n\n```shell\n==========Starting to backup...============\n==========Starting to delete clusters, inspections and secrets...==========\ncustomresourcedefinition.apiextensions.k8s.io \"etcdclusters.kstone.tkestack.io\" deleted\ncustomresourcedefinition.apiextensions.k8s.io \"etcdinspections.kstone.tkestack.io\" deleted\n==========Starting to re-create crds...==========\ncustomresourcedefinition.apiextensions.k8s.io/etcdclusters.kstone.tkestack.io created\n==========Starting to generate clusters...==========\netcdcluster.kstone.tkestack.io/test-kstone created\n==========Starting to generate secrets...==========\nsecret/xxx created\n==========finished==========\n```\n\n## 3 Upgrade kstone by helm\n\n- Helm upgrade for production environment\n\n``` shell\ncd charts\n\nhelm upgrade kstone . -n kstone -f values.yaml\n```\n\nor\n\n- Helm upgrade for test environment\n\n``` shell\ncd charts\n\nhelm upgrade kstone . -n kstone -f values.test.yaml\n```\n\n# 4 Clear browser cache\n\nIf your browser is chrome, please refer to [this](https://support.google.com/accounts/answer/32050?hl=en&co=GENIE.Platform%3DDesktop)."
  },
  {
    "path": "docs/proposal/authentication-support/README.md",
    "content": "# kstone-api Supports Authentication\n\n## Motivation\n\nKstone has become a popular solution for etcd management. Due to lack of authentication ability, it has safety vulnerability and is not recommended using in production environment. To improve safety features of kstone, we'd like to support authentication in kstone.\n\n## Goals\n\n* Designed to support multiple authentication plugins.\n* Strong security (password encryption, token expiration time, password reset only, etc.).\n* Built-in username/password authentication, the default is based on bearer token authentication (jwt).\n \n## Non-Goals\n\n* Implement a complex RBAC authentication system.\n* Implement a complete user management system(only create an admin user by default).\n\n## Use Cases\n\n* Visiting [kstone-dashboard](https://github.com/tkestack/kstone-dashboard) login page to authenticate.\n* Any requests to access kstone-api without authentication will directly return a HTTP 401 Unauthorized\nerror.\n\n### Bear Token Authentication\n\n- Users use their username and password to login.\n- The token authenticator generates a bear token set in response body.\n- Users send request with bear token request header, the token authenticator verifies if the token is valid.\n\n### External Auth\n\nUsers configure their own authentication system (e.g. ldap, oidc), and use their custom authentication system to verify identity.\n\n## Proposal\n\nIn order to implement login feature, we develop an authentication module in kstone-api. It supports not only basic auth(username/password authentication) by default but also other authentication protocols.\n\n## Design Details\n\n### Authentication Process\n\n#### 1. Login Process\n\n![Login Process](./login.png)\n\n- First time login, POST request will be sent to kstone-api, URL path `/apis/login`.\n- User login with default username and password.\n\nRequest example:\n\n```json\n{\n  \"username\":\"admin\",\n  \"password\":\"adm1n@kstone.io\"\n}\n```\n\nResponse example:\n\n```json\n{\n  \"username\":\"admin\",\n  // this will be true when login with default username and password\n  \"reset_password\": true,\n  \"token\":\"eyJhbGciOiJSUzI1N.xxx.xxx\"\n}\n```\n- **Authenticator**: Compare user and password with `kstone-api-user` configmap configuration.\n\n- **TokenGenerator**: Generate a JWT token for users and put it in response body.\n\n- If user login with default username and password, the response body will contain `\"reset_password\": true`, users must reset the password.\n\n#### 2. JWT Token Authentication Process\n\n![Logout Process](./token-auth.png)\n\n- **JWTTokenAuthenticator**: Verify JWT Token from request header.\n\n> If user sends request with JWT token header, **JWTTokenAuthenticator** middleware will only verify the token until it is expired.\n\n### Authentication Interface\n\n- Authentication Request, Token and TokenGenerator Interface\n\n```go\n\n// Token checks a string value against a backing authentication store and\n// returns a Response or an error if the token could not be checked.\ntype Token interface {\n    AuthenticateToken(ctx context.Context, token string) (*Response, bool, error)\n}\n\n// TokenGenerator generates tokens\ntype TokenGenerator interface {\n    GenerateToken(ctx context.Context, username string, password string) (string, error)\n}\n\n// Request attempts to extract authentication information from a request and\n// returns a Response or an error if the request could not be checked.\ntype Request interface {\n    AuthenticateRequest(ctx *gin.Context) (*Response, bool, error)\n}\n\n```\n\n- Store Interface\n\n```go\n// Store defines auth user/password storage interface\ntype Store interface {\n\t// UserGet gets a user\n\tUserGet() User\n\t// UserAdd adds a user\n\tUserAdd(user User) error\n\t// UserDelete deletes a user\n\tUserDelete(username string) error\n\t// UserList lists users\n\tUserList() []User\n\t// UserChangePassword changes a password of a user\n\tUserChangePassword(username, password string) error\n}\n```\n\n### Bear Token Authentication\n\n#### Auth Configuration\n\nBy default, we create a `kstone-api-key` secret and `kstone-api-user` configmap in kstone namespace.\n\n- `kstone-api-key` secret specifies private key:\n```yaml\napiVersion: v1\ndata:\n  private.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBeURuTHlyS0t4d1lhQVF1VDhSRVZ0bWR1VDYyV0xYTGIvUEs4bStJZG8yd3U1L1oxCmpCTVBIcWFzMjdabGlaeXF5bFVWZ3FsSUxNZUxPYlFtY0JvTUdGNkxuemVreHdEYVdmNTBRYW5JeTNSdFR4UVYKaEdIMnc0ZS8yQnI2NXlucUh6N0NZSy9VUHhWSWRTYWZaZ08vM0VGTWZVZVZRV0RWRWJCaTZWSW5hZzdsQjlRUQo2Q2tPTFM2ZFl5YXJnWWcrWWJZUkliVkVCNmNRTzNvcXJVTzR4OTlpZ3l3Z0Q3dlRReHdOMXB5eHVNbmlRYW5HCkREakludndTdUMxYTlUREdWc0ZXMzU5OUVoeGFuc3FUaUhvMm04YjJwNzdsWFFGYy9Qc1UwNTB6dDgxN1czTVEKbGlQRU5ycUhQTUpTNXhFQkhjdEdzb3Rtc3J6NmNIUklrclFLblFJREFRQUJBb0lCQVFDSDg0NW5aRkdNajUwSwpocVQrTXo2TjZxN2hGUmw2Wkpud3A1VGZOMm91YzU5cHkxUEhONDIxbnpDUndzZ3c1eHFrWlo5RVo5TGs3TnlnCjRxeVN3MnpoQXhsRWs1Q2p1dldIMDVsMm1HVUptRlU4TTRQa3JtdlNHaE51RmV1MUdDV3E3MzhtRFYxTk5CTk4KMEZxODl1RElHZUpvMGprSytrZlNTZlR2UGVRYlF5d3BPdVg3Wmp1RCtLOE9qRzlhWnpNOTYyUERoREJ2VlBCZQpKeXNqV0VqU0d5YWc3NjMza3Y0dWtPeDhycVBRLzJUdStIcElyQTljVXBnVDh6V0UycThxcHdVZzBHY0NuZ21mCnFsZjU1a1lzL1RhMW9iUjNxYVg2bWpKL2dFNlZyUzFpSTc1em5lbkh3Tmp6WExpaE5JL3ZkMXh1QnREV2JLTVUKK0M3bnpPZlZBb0dCQU9vaTNZM2luOGgrTjczYVdyWnIxQ29FNzBFWHg2dFZwdnBTUHJyMmZhUG5UVDBOR1RpUgpsTFJlOEp3WU9nNlgzQjU4SEwxVUtnZ05pT285TS9FSUlMblU0RzdHbDZSTG52NUNBODVtYWJ4Q3JkMTJXeWlpCmVnMy80ODRselFpdDliQ0lFV3VaekcySnBYb2Jzc3FjT0szNjNKKzBtUk1JUDhLTWVVbFlwYVo3QW9HQkFOcnMKU1R6aXhwWm0yYUYrUzNYV0l0TmRjakhMRW1BU1orcVZ6TXRRcHFLUjRlSXlodDNtczRGWmdCSFpxTVMzWTlDLwppdUFQNWJMMTA4NGdtWWJmMjhpRjNyakdhbGdHUkRpaDh6REgyR2pMVitrbE1PUm1GaFRPeDF5SHhTVWVaOEpjCmZ3aG42Y3RxcVRQaE5mQmw0SUV1eklEalZueDdUL09IMkhybDFaUEhBb0dCQU5aeW5LNnFGV05UaDhhU1NtZXYKRjZKczVwNmVJem1ndDlHcXB0NGppaXduWEsxQVpBdFYrL2ZBeFd5VEhBbmx1YTBLVEdCMHlCS2NJdjA0bFd4OAozMHlWMkFKZVR1SWlpVHVrUjB3eXJVSExhT2ZnMGRuRUJ6cnZWejJuamNZWFgyTVRIYkdLS3AxaFoza1NDWTVkCnkrUStVdmpNTnpBaGJCVExDUVBPOTlvbEFvR0FQanhrQ2FvU2VKbGVqemwvTEUybTh0Mmk1Q0x0NDEvNEtNbFQKUWcxNGdjamxKVS9sNVZsN2VHOUFLRkx2VnBVb0RDVVh6dURXRlEwcm5ITEtFbnk3VjRNdk1Pby9PeXowNGdDdwpTUkxYSTl1QzcyWENRM3YrRlFZL3lMOVVQVndxZFNla2VYaEpENm9QMWc3VkxiVllvSUQwWkVPOHg0Q3Exdm1zCmdpdXFqdXNDZ1lFQXI0WVhUWWZQUk9YQXRmN01ETUs5bmVRcHZNUytiMit5RGNhdFM0YitNT0kxY3ViNFFsdDEKMDdWV2RnWnNybTc2bkZ2TDF4SWptREhPZnJPbU1Zd2Y3VGRhYWVIbG1Qa1BvOHc2ZG1lbkdGaHV2Q1lZa3YyagpsS3o2VWhtYzlCNkc4VVlQNzdvWTR5RkhoQU9mVXpTQVF4bEpEV0hzeVA0SmRtZTlYZnNURUU0PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=\nkind: Secret\nmetadata:\n  name: kstone-api-key\n  namespace: kstone\ntype: Opaque\n```\n- `kstone-api-user` configmap specifies username and password:\n\n```yaml\ndata:\n  # password: bcrypt encryption(e.g. adm1n@kstone.io)\n  admin: $2y$10$dgolimSP5PywT3yMaRqppeA5GflVmyf/cWaL6bfmXVk6Rsjlmp0ui\nkind: ConfigMap\nmetadata:\n  name: kstone-api-user\n  namespace: kstone\n```\n\nTo customize admin username and password, modify or add the data field in `kstone-api-user` configmap.\n\n> To support multiple users, user can add multiple `username: password` key-value pairs in `kstone-api-user` configmap\n\n#### Encryption && Decryption\n\nUse [`golang.org/x/crypto`](https://pkg.go.dev/golang.org/x/crypto) to compare a **bcrypt hashed password** with its **possible plaintext equivalent**. Returns nil on success, or an error on failure.\n\n- **bcrypt hashed password** stored in `kstone-api-user` configmap.\n- **possible plaintext equivalent** is the login password from user.\n```go\nbcrypt.CompareHashAndPassword(bcryptHashedPassword, plaintextPassword)\n```\n\n#### Customize Admin Username, Password or Private Key\n\n- Specify a new username and password(e.g. admin:custom@kstone.io)\n\n```shell\nUSER=admin\nPASSWORD=custom@kstone.io\n```\n> Password must contain numbers, letters, eight digits or more in length\n\n- Generate a new password hash\n\n```shell\n# yum -y install httpd-tools\n# e.g. htpasswd -nbBC 10 admin admin\nHASH_PASSWORD=`htpasswd -nbBC 10 ${USER} ${PASSWORD}|awk -F ':' '{print $2}'`\n\n```\n\n- Update username and password:\n\n- 1. use `--dry-run=client` option to print out a custom `kstone-api-user` configmap:\n```shell\nkubectl create configmap -n kstone kstone-api-user --from-literal=${USER}=${HASH_PASSWORD} --dry-run=client -oyaml\n```\n- 2. replace the default `kstone-api-user` configmap with the new `kstone-api-user` configmap.\n    \n> If the user forgets the password, please refer to this method to reset the password.\n\n- Generate a new private key\n\n```shell\nopenssl genrsa -out private.key 2048\n```\n\n- Update private key:\n  \n- 1. use `--dry-run=client` option to print out a custom `kstone-api-key` secret:\n```shell\nkubectl create secret generic -n kstone kstone-api-key --from-file=private.pem --dry-run=client -oyaml\n```\n- 2. replace the default `kstone-api-key` secret with the new `kstone-api-key` secret.\n\n### External Auth\n\nkstone-api plans to support external auth plugins, such as: LDAP, OIDC etc. \n\nA few work needs to be done:\n\n1. Implement the Request interface to verify the external authentication request.\n\n2. Implement the Token interface to verify token for the external authentication protocol.\n\n3. Implement the TokenGenerator interface to generate a token if needed.(optional if reusing JWTTokenAuthenticator)\n\n4. Implement the Store interface to update users information.(add users, reset password etc.)\n\n### REST API\n\n#### Login\n\n- request example\n\n```json\nPOST /apis/login\n{\n  \"username\":\"admin\",\n  \"password\":\"adm1n@kstone.io\"\n}\n```\n\n- response example\n\n```json\n{\n  \"username\": \"admin\",\n  // this will be true when login with default username and password\n  \"reset_password\": true,\n  \"token\": \"eyJhbGciOiJSUzI1N.xxx.xxx\",\n  \"message\": \"\"\n}\n```\n> if `reset_password` is true, kstone-dashboard will redirect to reset password page.\n\n#### Request with Authentication\n\n- request example\n\n```json\nGET /apis/users\n\nHeader:\nkstone-api-jwt: eyJhbGciOiJSUzI1N.xxx.xxx\n```\n\n- response example\n\n```json\n{\n  \"username\": \"\",\n  // this will be true when login with default username and password\n  \"reset_password\": false,\n  \"token\": \"\",\n  \"message\": \"admin,admin-2,admin3\"\n}\n```\n\n## Testing Plan\n\nAdd e2e test to verify the login feature in kstone-api.\n\n## References\n\n- [Introduction to JSON Web Tokens](https://jwt.io/introduction)\n- [etcd v3 authentication design](https://etcd.io/docs/v3.5/learning/design-auth-v3/)\n- [grafana basic authentication](https://grafana.com/docs/grafana/latest/auth/overview/#basic-authentication)\n- [kubernetes authentication implementation](https://kubernetes.io/docs/reference/access-authn-authz/authentication/)"
  },
  {
    "path": "docs/proposal/authentication-support/proposal.yaml",
    "content": "title: kstone-api supports authentication\nproposal-number: 1\nauthors:\n  - \"@lianghao208\"\nreviewers:\n  - \"@tangcong\"\n  - \"@engow\"\n  - \"@maudL1n\"\napprovers:\n  - \"@tangcong\"\n  - \"@engow\"\ncreation-date: 2022-01-13\nlast-updated: 2022-01-13\nstatus: implementable\n"
  },
  {
    "path": "go.mod",
    "content": "module tkestack.io/kstone\n\ngo 1.16\n\nrequire (\n\tgithub.com/aws/aws-sdk-go v1.13.8\n\tgithub.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect\n\tgithub.com/coreos/etcd v3.3.13+incompatible\n\tgithub.com/coreos/etcd-operator v0.9.4\n\tgithub.com/gin-contrib/pprof v1.4.0\n\tgithub.com/gin-gonic/gin v1.8.1\n\tgithub.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab\n\tgithub.com/go-openapi/spec v0.20.3 // indirect\n\tgithub.com/go-openapi/swag v0.19.15 // indirect\n\tgithub.com/golang-jwt/jwt v3.2.2+incompatible\n\tgithub.com/google/go-querystring v1.1.0 // indirect\n\tgithub.com/mozillazg/go-httpheader v0.3.0 // indirect\n\tgithub.com/onsi/ginkgo v1.16.4\n\tgithub.com/onsi/gomega v1.16.0\n\tgithub.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.48.1\n\tgithub.com/prometheus-operator/prometheus-operator/pkg/client v0.48.1\n\tgithub.com/prometheus/client_golang v1.11.0\n\tgithub.com/spf13/cobra v1.1.3\n\tgithub.com/spf13/pflag v1.0.5\n\tgithub.com/tencentyun/cos-go-sdk-v5 v0.7.31\n\tgo.etcd.io/etcd/api/v3 v3.5.0\n\tgo.etcd.io/etcd/client/pkg/v3 v3.5.0\n\tgo.etcd.io/etcd/client/v2 v2.305.0-alpha.0\n\tgo.etcd.io/etcd/client/v3 v3.5.0\n\tgolang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97\n\tgolang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558 // indirect\n\tgolang.org/x/sync v0.0.0-20210220032951-036812b2e83c\n\tk8s.io/api v0.21.3\n\tk8s.io/apimachinery v0.21.3\n\tk8s.io/client-go v12.0.0+incompatible\n\tk8s.io/code-generator v0.21.3\n\tk8s.io/klog/v2 v2.8.0\n\tk8s.io/kubectl v0.21.3\n\tsigs.k8s.io/controller-runtime v0.9.1\n\tsigs.k8s.io/yaml v1.2.0\n)\n\nreplace (\n\tgithub.com/coreos/etcd-operator v0.9.4 => ./third_party/etcd-operator\n\tk8s.io/client-go v12.0.0+incompatible => k8s.io/client-go v0.21.1\n)\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.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw=\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/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=\ngit.apache.org/thrift.git v0.0.0-20181218151757-9b75e4fe745a/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=\ngithub.com/Azure/azure-sdk-for-go v11.3.0-beta+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=\ngithub.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=\ngithub.com/Azure/go-autorest v11.1.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=\ngithub.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=\ngithub.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=\ngithub.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630=\ngithub.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw=\ngithub.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=\ngithub.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=\ngithub.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=\ngithub.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=\ngithub.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=\ngithub.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=\ngithub.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=\ngithub.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=\ngithub.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=\ngithub.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=\ngithub.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=\ngithub.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=\ngithub.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=\ngithub.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=\ngithub.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=\ngithub.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=\ngithub.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=\ngithub.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=\ngithub.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=\ngithub.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=\ngithub.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=\ngithub.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=\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-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=\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/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=\ngithub.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=\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/aliyun/aliyun-oss-go-sdk v0.0.0-20190125095113-2b29687e15f2/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=\ngithub.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=\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/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=\ngithub.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=\ngithub.com/aws/aws-sdk-go v1.13.8 h1:2GXJr7VVErT37gjlGzkRI7Pb0alhJ2Y3XoCRcXRhavQ=\ngithub.com/aws/aws-sdk-go v1.13.8/go.mod h1:ZRmQr0FajVIyZ4ZzBYKG5P3ZqPz9IHG41ZoMu1ADI3k=\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/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/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=\ngithub.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=\ngithub.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=\ngithub.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=\ngithub.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=\ngithub.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=\ngithub.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=\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-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=\ngithub.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=\ngithub.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=\ngithub.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=\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 h1:8F3hqu9fGYLBifCmRCJsicFqDx/D68Rt3q1JMazcgBQ=\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.1.0+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 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=\ngithub.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=\ngithub.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=\ngithub.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8=\ngithub.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=\ngithub.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=\ngithub.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=\ngithub.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=\ngithub.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=\ngithub.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=\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/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=\ngithub.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=\ngithub.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=\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/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/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=\ngithub.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=\ngithub.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=\ngithub.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=\ngithub.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=\ngithub.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=\ngithub.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=\ngithub.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=\ngithub.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=\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 h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk=\ngithub.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=\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.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=\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.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=\ngithub.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=\ngithub.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=\ngithub.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs=\ngithub.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=\ngithub.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=\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/form3tech-oss/jwt-go v3.2.2+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 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=\ngithub.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=\ngithub.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=\ngithub.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=\ngithub.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=\ngithub.com/gin-contrib/pprof v1.4.0 h1:XxiBSf5jWZ5i16lNOPbMTVdgHBdhfGRD5PZ1LWazzvg=\ngithub.com/gin-contrib/pprof v1.4.0/go.mod h1:RrehPJasUVBPK6yTUwOl8/NP6i0vbUgmxtis+Z5KE90=\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/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=\ngithub.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=\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-ini/ini v1.42.0 h1:TWr1wGj35+UiWHlBA8er89seFXxzwFn11spilrrj+38=\ngithub.com/go-ini/ini v1.42.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=\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 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc=\ngithub.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=\ngithub.com/go-logr/zapr v0.4.0 h1:uc1uML3hRYL9/ZZPdgHS/n8Nzo+eaYL/Efxkkamf7OM=\ngithub.com/go-logr/zapr v0.4.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk=\ngithub.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab h1:xveKWz2iaueeTaUgdetzel+U7exyigDYBryyVfV/rZk=\ngithub.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=\ngithub.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=\ngithub.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=\ngithub.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=\ngithub.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk=\ngithub.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU=\ngithub.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=\ngithub.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=\ngithub.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=\ngithub.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=\ngithub.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=\ngithub.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=\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.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=\ngithub.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=\ngithub.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=\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/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=\ngithub.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=\ngithub.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=\ngithub.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs=\ngithub.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk=\ngithub.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA=\ngithub.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64=\ngithub.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4=\ngithub.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=\ngithub.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=\ngithub.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=\ngithub.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=\ngithub.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=\ngithub.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=\ngithub.com/go-openapi/spec v0.20.3 h1:uH9RQ6vdyPSs2pSy9fL8QPspDF2AMIMPtmK5coSSjtQ=\ngithub.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg=\ngithub.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=\ngithub.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=\ngithub.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY=\ngithub.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=\ngithub.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk=\ngithub.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=\ngithub.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=\ngithub.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=\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/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=\ngithub.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=\ngithub.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=\ngithub.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=\ngithub.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=\ngithub.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=\ngithub.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=\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.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.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.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0=\ngithub.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=\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/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=\ngithub.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=\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.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=\ngithub.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=\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.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=\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 v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=\ngithub.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=\ngithub.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=\ngithub.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\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 h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=\ngithub.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=\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/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\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.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=\ngithub.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=\ngithub.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk=\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/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.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=\ngithub.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=\ngithub.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=\ngithub.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=\ngithub.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=\ngithub.com/google/gofuzz v1.1.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/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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=\ngithub.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=\ngithub.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=\ngithub.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/googleapis/gax-go v0.0.0-20181219185031-c8a15bac9b9f/go.mod h1:5VvnLYVimBt+hOVlFtJDkYQHVmk4K27qHHioZjPbYAI=\ngithub.com/googleapis/gax-go/v2 v2.0.2/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=\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/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=\ngithub.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=\ngithub.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=\ngithub.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=\ngithub.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=\ngithub.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=\ngithub.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=\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/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=\ngithub.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=\ngithub.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=\ngithub.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=\ngithub.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc/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-middleware v1.0.1-0.20190118093823-f849b5445de4/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.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=\ngithub.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw=\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/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=\ngithub.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=\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/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=\ngithub.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=\ngithub.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=\ngithub.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=\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/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 h1:12VvqtR6Aowv3l/EQUlocDHW2Cp4G9WJVH7uyH8QFJE=\ngithub.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=\ngithub.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=\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.8/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/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=\ngithub.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=\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/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/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/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/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/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=\ngithub.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=\ngithub.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=\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/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=\ngithub.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=\ngithub.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=\ngithub.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=\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-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=\ngithub.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=\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/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/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/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=\ngithub.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc=\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/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=\ngithub.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60=\ngithub.com/mozillazg/go-httpheader v0.3.0 h1:3brX5z8HTH+0RrNA1362Rc3HsaxyWEKtGY45YrhuINM=\ngithub.com/mozillazg/go-httpheader v0.3.0/go.mod h1:PuT8h0pw6efvp8ZeUec1Rs7dwjK08bt6gKSReGMqtdA=\ngithub.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=\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.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=\ngithub.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=\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.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=\ngithub.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=\ngithub.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=\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.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=\ngithub.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=\ngithub.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=\ngithub.com/openzipkin/zipkin-go v0.1.3/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=\ngithub.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=\ngithub.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=\ngithub.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=\ngithub.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=\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/petar/GoLLRB v0.0.0-20130427215148-53be0d36a84c/go.mod h1:HUpKUBZnpzkdx0kD/+Yfuft+uD3zHGtXF/XJB14TUr4=\ngithub.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=\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/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/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=\ngithub.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.44.1/go.mod h1:3WYi4xqXxGGXWDdQIITnLNmuDzO5n6wYva9spVhR4fg=\ngithub.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.48.1 h1:OGC7+ktZ6h8xI99VB6i8iuiXecdhUmwto9vbGzoVMac=\ngithub.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.48.1/go.mod h1:3WYi4xqXxGGXWDdQIITnLNmuDzO5n6wYva9spVhR4fg=\ngithub.com/prometheus-operator/prometheus-operator/pkg/client v0.48.1 h1:i3bwALeHBJaLRw+z/8IPujQpAAVwqXpyLrftdhysFrk=\ngithub.com/prometheus-operator/prometheus-operator/pkg/client v0.48.1/go.mod h1:k4BrWlVQQsvBiTcDnKEMgyh/euRxyxgrHdur/ZX/sdA=\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.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=\ngithub.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=\ngithub.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=\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.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=\ngithub.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ=\ngithub.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=\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.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=\ngithub.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=\ngithub.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=\ngithub.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=\ngithub.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=\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/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/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=\ngithub.com/satori/uuid v1.2.0/go.mod h1:B8HLsPLik/YNn6KKWVMDJ8nzCL8RP5WyfsnmvnAEwIU=\ngithub.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=\ngithub.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=\ngithub.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=\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.7.0/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/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=\ngithub.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=\ngithub.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=\ngithub.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=\ngithub.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=\ngithub.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M=\ngithub.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=\ngithub.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=\ngithub.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=\ngithub.com/spf13/pflag v1.0.1/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.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=\ngithub.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=\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/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 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=\ngithub.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=\ngithub.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.194/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=\ngithub.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.194/go.mod h1:yrBKWhChnDqNz1xuXdSbWXG56XawEq0G5j1lg4VwBD4=\ngithub.com/tencentyun/cos-go-sdk-v5 v0.7.31 h1:NujkkOKMJ3IFs1+trCwXOKRCIPQ8qI5Lxul9JkhTg6M=\ngithub.com/tencentyun/cos-go-sdk-v5 v0.7.31/go.mod h1:4E4+bQ2gBVJcgEC9Cufwylio4mXOct2iu05WjgEBx1o=\ngithub.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=\ngithub.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=\ngithub.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=\ngithub.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=\ngithub.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=\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/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=\ngithub.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=\ngithub.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=\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/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=\ngo.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=\ngo.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=\ngo.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=\ngo.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=\ngo.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489 h1:1JFLBqwIgdyHN1ZtgjTBwO+blA6gVOmZurpiMEsETKo=\ngo.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=\ngo.etcd.io/etcd/api/v3 v3.5.0-alpha.0/go.mod h1:mPcW6aZJukV6Aa81LSKpBjQXTWlXB5r74ymPoSWa3Sw=\ngo.etcd.io/etcd/api/v3 v3.5.0 h1:GsV3S+OfZEOCNXdtNkBSR7kgLobAa/SO6tCxRa0GAYw=\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 h1:2aQv6F436YnN7I4VbI8PPYrBhu+SmrTaADcf8Mi/6PU=\ngo.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=\ngo.etcd.io/etcd/client/v2 v2.305.0-alpha.0 h1:jZepGpOeJATxsbMNBZczDS2jHdK/QVHM1iPe9jURJ8o=\ngo.etcd.io/etcd/client/v2 v2.305.0-alpha.0/go.mod h1:kdV+xzCJ3luEBSIeQyB/OEKkWKd8Zkux4sbDeANrosU=\ngo.etcd.io/etcd/client/v3 v3.5.0 h1:62Eh0XOro+rDwkrypAGDfgmNh5Joq+z+W9HZdlXMzek=\ngo.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0=\ngo.etcd.io/etcd/pkg/v3 v3.5.0-alpha.0 h1:3yLUEC0nFCxw/RArImOyRUI4OAFbg4PFpBbAhSNzKNY=\ngo.etcd.io/etcd/pkg/v3 v3.5.0-alpha.0/go.mod h1:tV31atvwzcybuqejDoY3oaNRTtlD2l/Ot78Pc9w7DMY=\ngo.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=\ngo.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=\ngo.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=\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.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=\ngo.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=\ngo.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=\ngo.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=\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/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=\ngo.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=\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/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=\ngo.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=\ngo.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=\ngo.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U=\ngo.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=\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-20190211182817-74369b46fc67/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-20190320223903-b7391e95e576/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-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/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 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=\ngolang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=\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-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=\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-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.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=\ngolang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\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-20181005035420-146acd28ed58/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-20190320064053-1272bf9dcd53/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-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=\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-20190813141303-74dc4d7220e7/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-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20191004110552-13f9640d40b9/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-20201021035429-f5854403a974/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-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-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=\ngolang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=\ngolang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=\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-20210323180902-22b0adad7558 h1:D7nTwh4J0i+5mW4Zjzn5omvlr6YBcWywE6KOcatyNxY=\ngolang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558/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 h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=\ngolang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\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-20190209173611-3b5209105503/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-20190321052220-f7bb7a8bee54/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-20190826190057-c7b8b68b1456/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-20191022100944-742c48ecaeb7/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-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-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-20200622214017-ed371f2e16b4/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-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20201119102817-f84b799fce68/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-20210225134936-a50acf3fe073/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-20210603081109-ebe580a85c40/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-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 h1:siQdpVirKtzPhKl3lZWozZraCFObP8S1v6PRp0bLrtU=\ngolang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/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 h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=\ngolang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=\ngolang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\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 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=\ngolang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\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-20210611083556-38a9dc6acbc6 h1:Vv0JUPWTyeqUq42B2WJ1FeIDjjvGKoA2Ss+Ts0lAVbs=\ngolang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6/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-20180828015842-6cd1fcedba52/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-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/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-20190125232054-d66bd3c5d5a6/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-20190617190820-da514acc4774/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-20190920225731-5eefd052ad72/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-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/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-20201224043029-2b0845dc783e/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.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA=\ngolang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=\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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=\ngolang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\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/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-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0=\ngoogle.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=\ngoogle.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=\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.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=\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.23.1/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.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=\ngoogle.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=\ngoogle.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0=\ngoogle.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=\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.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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=\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 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=\ngopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=\ngopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=\ngopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=\ngopkg.in/square/go-jose.v2 v2.2.2/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.7/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 h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=\ngopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=\ngotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=\ngotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=\nhonnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\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.18.3/go.mod h1:UOaMwERbqJMfeeeHc8XJKawj4P9TgDRnViIqqBeH2QA=\nk8s.io/api v0.19.2/go.mod h1:IQpK0zFQ1xc5iNIQPqzgoOwuFugaYHK4iCknlAQP9nI=\nk8s.io/api v0.21.1/go.mod h1:FstGROTmsSHBarKc8bylzXih8BLNYTiS3TZcsoEDg2s=\nk8s.io/api v0.21.2/go.mod h1:Lv6UGJZ1rlMI1qusN8ruAp9PUBFyBwpEHAdG24vIsiU=\nk8s.io/api v0.21.3 h1:cblWILbLO8ar+Fj6xdDGr603HRsf8Wu9E9rngJeprZQ=\nk8s.io/api v0.21.3/go.mod h1:hUgeYHUbBp23Ue4qdX9tR8/ANi/g3ehylAqDn9NWVOg=\nk8s.io/apiextensions-apiserver v0.18.3/go.mod h1:TMsNGs7DYpMXd+8MOCX8KzPOCx8fnZMoIGB24m03+JE=\nk8s.io/apiextensions-apiserver v0.21.2 h1:+exKMRep4pDrphEafRvpEi79wTnCFMqKf8LBtlA3yrE=\nk8s.io/apiextensions-apiserver v0.21.2/go.mod h1:+Axoz5/l3AYpGLlhJDfcVQzCerVYq3K3CvDMvw6X1RA=\nk8s.io/apimachinery v0.18.3/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=\nk8s.io/apimachinery v0.19.2/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA=\nk8s.io/apimachinery v0.21.1/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY=\nk8s.io/apimachinery v0.21.2/go.mod h1:CdTY8fU/BlvAbJ2z/8kBwimGki5Zp8/fbVuLY8gJumM=\nk8s.io/apimachinery v0.21.3 h1:3Ju4nvjCngxxMYby0BimUk+pQHPOQp3eCGChk5kfVII=\nk8s.io/apimachinery v0.21.3/go.mod h1:H/IM+5vH9kZRNJ4l3x/fXP/5bOPJaVP/guptnZPeCFI=\nk8s.io/apiserver v0.18.3/go.mod h1:tHQRmthRPLUtwqsOnJJMoI8SW3lnoReZeE861lH8vUw=\nk8s.io/apiserver v0.21.2/go.mod h1:lN4yBoGyiNT7SC1dmNk0ue6a5Wi6O3SWOIw91TsucQw=\nk8s.io/cli-runtime v0.21.3/go.mod h1:h65y0uXIXDnNjd5J+F3CvQU3ZNplH4+rjqbII7JkD4A=\nk8s.io/client-go v0.18.3/go.mod h1:4a/dpQEvzAhT1BbuWW09qvIaGw6Gbu1gZYiQZIi1DMw=\nk8s.io/client-go v0.19.2/go.mod h1:S5wPhCqyDNAlzM9CnEdgTGV4OqhsW3jGO1UM1epwfJA=\nk8s.io/client-go v0.21.1 h1:bhblWYLZKUu+pm50plvQF8WpY6TXdRRtcS/K9WauOj4=\nk8s.io/client-go v0.21.1/go.mod h1:/kEw4RgW+3xnBGzvp9IWxKSNA+lXn3A7AuH3gdOAzLs=\nk8s.io/client-go v0.21.2/go.mod h1:HdJ9iknWpbl3vMGtib6T2PyI/VYxiZfq936WNVHBRrA=\nk8s.io/client-go v0.21.3/go.mod h1:+VPhCgTsaFmGILxR/7E1N0S+ryO010QBeNCv5JwRGYU=\nk8s.io/client-go v11.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=\nk8s.io/code-generator v0.18.3/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=\nk8s.io/code-generator v0.21.2/go.mod h1:8mXJDCB7HcRo1xiEQstcguZkbxZaqeUOrO9SsicWs3U=\nk8s.io/code-generator v0.21.3 h1:K2Onrjuve/31D4Y5DpR9ngWM2BiiKUxrGaCxSEJS/Y8=\nk8s.io/code-generator v0.21.3/go.mod h1:K3y0Bv9Cz2cOW2vXUrNZlFbflhuPvuadW6JdnN6gGKo=\nk8s.io/component-base v0.18.3/go.mod h1:bp5GzGR0aGkYEfTj+eTY0AN/vXTgkJdQXjNTTVUaa3k=\nk8s.io/component-base v0.21.2/go.mod h1:9lvmIThzdlrJj5Hp8Z/TOgIkdfsNARQ1pT+3PByuiuc=\nk8s.io/component-base v0.21.3/go.mod h1:kkuhtfEHeZM6LkX0saqSK8PbdO7A0HigUngmhhrwfGQ=\nk8s.io/component-helpers v0.21.3/go.mod h1:FJCpEhM9fkKvNN0QAl33ozmMj+Bx8R64wcOBqhng0oQ=\nk8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=\nk8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=\nk8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=\nk8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027 h1:Uusb3oh8XcdzDF/ndlI4ToKTYVlkCSJP39SRY2mfRAw=\nk8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=\nk8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=\nk8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=\nk8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=\nk8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=\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 h1:Q3gmuM9hKEjefWFFYF0Mat+YyFJvsUyYuwyNNJ5C9Ts=\nk8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=\nk8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=\nk8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o=\nk8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7 h1:vEx13qjvaZ4yfObSSXW7BrMc/KQBBT/Jyee8XtLf4x0=\nk8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE=\nk8s.io/kubectl v0.21.3 h1:RmHvvz7tLnFmVqUzJuR44D8oE5zv1iyDojxSQllY+II=\nk8s.io/kubectl v0.21.3/go.mod h1:/x/kzrhfL1h1W07z6a1UTbd8SWZUYAWXskigkG4OBCg=\nk8s.io/metrics v0.21.3/go.mod h1:mN3Klf203Lw1hOsfg1MG7DR/kKUhwiyu8GSFCXZdz+o=\nk8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=\nk8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=\nk8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=\nk8s.io/utils v0.0.0-20210527160623-6fdb442a123b h1:MSqsVQ3pZvPGTqCjptfimO2WjG7A9un2zcpiHkA6M/s=\nk8s.io/utils v0.0.0-20210527160623-6fdb442a123b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=\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/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0=\nsigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.19/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=\nsigs.k8s.io/controller-runtime v0.9.1 h1:+LAqHAhkVW4lt/jLlrKmnGPA7OORMw/xEUH3Ey1h1Bs=\nsigs.k8s.io/controller-runtime v0.9.1/go.mod h1:cTqsgnwSOsYS03XwySYZj8k6vf0+eC4FJRcCgQ9elb4=\nsigs.k8s.io/kustomize/api v0.8.8/go.mod h1:He1zoK0nk43Pc6NlV085xDXDXTNprtcyKZVm3swsdNY=\nsigs.k8s.io/kustomize/cmd/config v0.9.10/go.mod h1:Mrby0WnRH7hA6OwOYnYpfpiY0WJIMgYrEDfwOeFdMK0=\nsigs.k8s.io/kustomize/kustomize/v4 v4.1.2/go.mod h1:PxBvo4WGYlCLeRPL+ziT64wBXqbgfcalOS/SXa/tcyo=\nsigs.k8s.io/kustomize/kyaml v0.10.17/go.mod h1:mlQFagmkm1P+W4lZJbJ/yaxMd8PqMRSC4cPcfUVt5Hg=\nsigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=\nsigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=\nsigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=\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.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno=\nsigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=\nsigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=\nsigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=\nsigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=\n"
  },
  {
    "path": "hack/boilerplate.go.txt",
    "content": "/*\nCopyright The Kubernetes Authors.\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\n"
  },
  {
    "path": "hack/custom-boilerplate.go.txt",
    "content": "/*\n* Tencent is pleased to support the open source community by making TKEStack\n* available.\n*\n* Copyright (C) 2012-2021 Tencent. All Rights Reserved.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n* this file except in compliance with the License. You may obtain a copy of the\n* License at\n*\n* https://opensource.org/licenses/Apache-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, WITHOUT\n* WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n* specific language governing permissions and limitations under the License.\n*/\n\n"
  },
  {
    "path": "hack/migratev1.sh",
    "content": "#!/bin/bash\nDATE=`date +%Y%m%d%H%M%S`\n\nmkdir -p ./migrate-${DATE} && cd ./migrate-${DATE}\n\necho \"==========Starting to backup...============\"\n\nkubectl get cluster -n kstone -oyaml > cluster-v1-backup-${DATE}.yaml\n\nsed 's#apiVersion: kstone.tkestack.io/v1alpha1#apiVersion: kstone.tkestack.io/v1alpha2#g;/ totalCpu/,/ totalMem/d' cluster-v1-backup-${DATE}.yaml > cluster-v2-backup-${DATE}.yaml\n\nfor i in `kubectl get cluster -n kstone --no-headers | awk '{print $1}'`;do kubectl get secret ${i} -n kstone -oyaml > secret-backup-${i}-${DATE}.yaml;done\n\nfor i in `ls secret-backup-*`;do sed '/ ownerReferences:/,/ uid:/d' ${i} > new-${i} ;done\n\necho \"==========Starting to delete clusters, inspections and secrets...==========\"\n\nkubectl delete crd etcdclusters.kstone.tkestack.io etcdinspections.kstone.tkestack.io\n\necho \"==========Starting to re-create crds...==========\"\n\nfor i in `ls ../deploy/crds/kstone.tkestack.io_*`;do kubectl create -f $i ;done\n\necho \"==========Starting to generate clusters...==========\"\n\nkubectl create -f cluster-v2-backup-${DATE}.yaml\n\necho \"==========Starting to generate secrets...==========\"\n\nfor i in `ls new-secret-backup-*`;do kubectl create -f ${i} ;done\n\necho \"==========finished==========\"\n"
  },
  {
    "path": "hack/tools.go",
    "content": "//go:build tools\n// +build tools\n\n/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// This package imports things required by build scripts, to force `go mod` to see them as dependencies\npackage tools\n\n// import tools\nimport _ \"k8s.io/code-generator\"\n"
  },
  {
    "path": "hack/update-codegen.sh",
    "content": "#!/usr/bin/env bash\n\n#\n# Tencent is pleased to support the open source community by making TKEStack\n# available.\n#\n# Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n# this file except in compliance with the License. You may obtain a copy of the\n# License at\n#\n# https://opensource.org/licenses/Apache-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, WITHOUT\n# WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations under the License.\n#\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nSCRIPT_ROOT=$(dirname \"${BASH_SOURCE[0]}\")/..\nCODEGEN_PKG=${CODEGEN_PKG:-$(cd \"${SCRIPT_ROOT}\"; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)}\n\n# generate the code with:\n# --output-base    because this script should also be able to run inside the vendor dir of\n#                  k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir\n#                  instead of the $GOPATH directly. For normal projects this can be dropped.\nbash \"${CODEGEN_PKG}\"/generate-groups.sh \"deepcopy,client,informer,lister\" \\\n  tkestack.io/kstone/pkg/generated tkestack.io/kstone/pkg/apis \\\n  kstone:v1alpha1 kstone.v1alpha2\\\n  --output-base \"$(dirname \"${BASH_SOURCE[0]}\")/../../..\" \\\n  --go-header-file \"${SCRIPT_ROOT}\"/hack/custom-boilerplate.go.txt\n"
  },
  {
    "path": "hack/verify-codegen.sh",
    "content": "#!/usr/bin/env bash\n\n#\n# Tencent is pleased to support the open source community by making TKEStack\n# available.\n#\n# Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n# this file except in compliance with the License. You may obtain a copy of the\n# License at\n#\n# https://opensource.org/licenses/Apache-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, WITHOUT\n# WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations under the License.\n#\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nSCRIPT_ROOT=$(dirname \"${BASH_SOURCE[0]}\")/..\n\nDIFFROOT=\"${SCRIPT_ROOT}/pkg\"\nTMP_DIFFROOT=\"${SCRIPT_ROOT}/_tmp/pkg\"\n_tmp=\"${SCRIPT_ROOT}/_tmp\"\n\ncleanup() {\n  rm -rf \"${_tmp}\"\n}\ntrap \"cleanup\" EXIT SIGINT\n\ncleanup\n\nmkdir -p \"${TMP_DIFFROOT}\"\ncp -a \"${DIFFROOT}\"/* \"${TMP_DIFFROOT}\"\n\n\"${SCRIPT_ROOT}/hack/update-codegen.sh\"\necho \"diffing ${DIFFROOT} against freshly generated codegen\"\nret=0\ndiff -Naupr \"${DIFFROOT}\" \"${TMP_DIFFROOT}\" || ret=$?\ncp -a \"${TMP_DIFFROOT}\"/* \"${DIFFROOT}\"\nif [[ $ret -eq 0 ]]\nthen\n  echo \"${DIFFROOT} up to date.\"\nelse\n  echo \"${DIFFROOT} is out of date. Please run hack/update-codegen.sh\"\n  exit 1\nfi\n"
  },
  {
    "path": "pkg/apis/kstone/register.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage kstone\n\n// GroupName is the group name used in this package\nconst (\n\tGroupName = \"kstone.tkestack.io\"\n)\n"
  },
  {
    "path": "pkg/apis/kstone/v1alpha1/doc.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// +k8s:deepcopy-gen=package\n// +groupName=kstone.tkestack.io\n\n// Package v1alpha1 is the v1alpha1 version of the API.\npackage v1alpha1\n"
  },
  {
    "path": "pkg/apis/kstone/v1alpha1/register.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage v1alpha1\n\nimport (\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\n\tplatform \"tkestack.io/kstone/pkg/apis/kstone\"\n)\n\n// SchemeGroupVersion is group version used to register these objects\nvar SchemeGroupVersion = schema.GroupVersion{Group: platform.GroupName, Version: \"v1alpha1\"}\n\n// Kind takes an unqualified kind and returns back a Group qualified GroupKind\nfunc Kind(kind string) schema.GroupKind {\n\treturn SchemeGroupVersion.WithKind(kind).GroupKind()\n}\n\n// Resource takes an unqualified resource and returns a Group qualified GroupResource\nfunc Resource(resource string) schema.GroupResource {\n\treturn SchemeGroupVersion.WithResource(resource).GroupResource()\n}\n\nvar (\n\t// SchemeBuilder initializes a scheme builder\n\tSchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)\n\t// AddToScheme is a global function that registers this API group & version to a scheme\n\tAddToScheme = SchemeBuilder.AddToScheme\n)\n\n// Adds the list of known types to Scheme.\nfunc addKnownTypes(scheme *runtime.Scheme) error {\n\tscheme.AddKnownTypes(SchemeGroupVersion,\n\t\t&EtcdCluster{},\n\t\t&EtcdClusterList{},\n\t\t&EtcdInspection{},\n\t\t&EtcdInspectionList{},\n\t)\n\tmetav1.AddToGroupVersion(scheme, SchemeGroupVersion)\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/apis/kstone/v1alpha1/types.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage v1alpha1\n\nimport (\n\tcorev1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\n// +genclient\n// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n\n// EtcdCluster is the Schema for the etcdclusters API\ntype EtcdCluster struct {\n\tmetav1.TypeMeta   `json:\",inline\"`\n\tmetav1.ObjectMeta `json:\"metadata,omitempty\" protobuf:\"bytes,1,opt,name=metadata\"`\n\n\tSpec   EtcdClusterSpec   `json:\"spec,omitempty\" protobuf:\"bytes,2,opt,name=spec\"`\n\tStatus EtcdClusterStatus `json:\"status,omitempty\" protobuf:\"bytes,3,opt,name=status\"`\n}\n\ntype EtcdClusterPhase string\n\nconst (\n\tEtcdClusterInit      EtcdClusterPhase = \"Initing\"\n\tEtcdCluterCreating   EtcdClusterPhase = \"Creating\"\n\tEtcdClusterRunning   EtcdClusterPhase = \"Running\"\n\tEtcdClusterUpdating  EtcdClusterPhase = \"Updating\"\n\tEtcdClusterDeleteing EtcdClusterPhase = \"Deleting\"\n\tEtcdClusterDeleted   EtcdClusterPhase = \"Deleted\"\n\tEtcdClusterUnknown   EtcdClusterPhase = \"Unknown\"   // connection refused or other errors\n\tEtcdClusterUnhealthy EtcdClusterPhase = \"UnHealthy\" // node health check returns unhealthy\n)\n\ntype EtcdClusterConditionType string\n\nconst (\n\tEtcdClusterConditionCreate EtcdClusterConditionType = \"Create\"\n\tEtcdClusterConditionImport EtcdClusterConditionType = \"Import\"\n\tEtcdClusterConditionUpdate EtcdClusterConditionType = \"Update\"\n\tEtcdClusterConditionDelete EtcdClusterConditionType = \"Delete\"\n)\n\n// EtcdClusterCondition contains condition information for a EtcdCluster.\ntype EtcdClusterCondition struct {\n\t// Type of EtcdCluster condition.\n\tType EtcdClusterConditionType `json:\"type\" protobuf:\"bytes,1,opt,name=type,casttype=EtcdClusterPhase\"`\n\t// Status of the condition, one of True, False, Unknown.\n\tStatus corev1.ConditionStatus `json:\"status\" protobuf:\"bytes,2,opt,name=status,casttype=k8s.io/api/core/v1.ConditionStatus\"`\n\t// Last time we got an update on a given condition.\n\t// +optional\n\tStartTime metav1.Time `json:\"startTime,omitempty\" protobuf:\"bytes,3,opt,name=startTime\"`\n\t// Last time the condition transit from one status to another.\n\t// +optional\n\tEndTime metav1.Time `json:\"endTime,omitempty\" protobuf:\"bytes,4,opt,name=endTime\"`\n\t// (brief) reason for the condition's last transition.\n\t// +optional\n\tReason string `json:\"reason,omitempty\" protobuf:\"bytes,5,opt,name=reason\"`\n\t// Human readable message indicating details about last transition.\n\t// +optional\n\tMessage string `json:\"message,omitempty\" protobuf:\"bytes,6,opt,name=message\"`\n}\n\ntype EtcdClusterType string\n\nconst (\n\tEtcdClusterKstone   EtcdClusterType = \"kstone-etcd-operator\"\n\tEtcdClusterImported EtcdClusterType = \"imported\"\n)\n\n// EtcdClusterSpec defines the desired state of EtcdCluster\ntype EtcdClusterSpec struct {\n\tName        string `json:\"name\" protobuf:\"bytes,1,opt,name=name\"`               // etcd cluster name，uniqueKey\n\tDescription string `json:\"description\" protobuf:\"bytes,2,opt,name=description\"` // etcd description\n\n\tAuthConfig AuthConfig `json:\"authConfig,omitempty\" protobuf:\"bytes,3,opt,name=authConfig\"` // tls config\n\n\tTotalCpu uint   `json:\"totalCpu\" protobuf:\"varint,4,opt,name=totalCpu\"` // single node's cpu, unit: Core\n\tTotalMem uint   `json:\"totalMem\" protobuf:\"varint,5,opt,name=totalMem\"` // single node's mem, unit: GiB\n\tDiskType string `json:\"diskType\" protobuf:\"bytes,6,opt,name=diskType\"`  // disk type, CLOUD_SSD/CLOUD_PREMIUM/CLOUD_BASIC\n\tDiskSize uint   `json:\"diskSize\" protobuf:\"varint,7,opt,name=diskSize\"` // single node's disk size, unit: GB\n\tSize     uint   `json:\"size\"  protobuf:\"varint,8,opt,name=size\"`        // etcd cluster member count: support 1, 3, 5, 7\n\n\tAffinity   corev1.Affinity `json:\"affinity,omitempty\" protobuf:\"bytes,9,opt,name=affinity\"`\n\tArgs       []string        `json:\"args,omitempty\" protobuf:\"bytes,10,rep,name=args\"`\n\tEnv        []corev1.EnvVar `json:\"env,omitempty\" protobuf:\"bytes,11,rep,name=env\"`               // etcd environment variables\n\tVersion    string          `json:\"version\" protobuf:\"bytes,12,opt,name=version\"`                 // etcd version\n\tRepository string          `json:\"repository,omitempty\" protobuf:\"bytes,13,opt,name=repository\"` // etcd image\n\n\tClusterType EtcdClusterType `json:\"clusterType\" protobuf:\"bytes,14,opt,name=clusterType,casttype=EtcdClusterType\"` // ClusterType specifies the etcd cluster provider.\n}\n\n// AuthConfig defines tls\ntype AuthConfig struct {\n\tEnableTLS bool     `json:\"enableTLS,omitempty\" protobuf:\"varint,1,opt,name=enableTLS\"`\n\tSAN       []string `json:\"san,omitempty\" protobuf:\"bytes,2,rep,name=san\"`\n\tTLSSecret string   `json:\"tlsSecret,omitempty\" protobuf:\"bytes,3,opt,name=tlsSecret\"`\n}\n\ntype KStoneFeature string\n\nconst (\n\tKStoneFeatureAnno                      = \"featureGates\"\n\tKStoneFeatureMonitor     KStoneFeature = \"monitor\"\n\tKStoneFeatureBackup      KStoneFeature = \"backup\"\n\tKStoneFeatureHealthy     KStoneFeature = \"healthy\"\n\tKStoneFeatureConsistency KStoneFeature = \"consistency\"\n\tKStoneFeatureRequest     KStoneFeature = \"request\"\n\tKStoneFeatureAlarm       KStoneFeature = \"alarm\"\n\tKStoneFeatureBackupCheck KStoneFeature = \"backupcheck\"\n)\n\n// EtcdClusterStatus defines the actual state of EtcdCluster.\ntype EtcdClusterStatus struct {\n\tConditions         []EtcdClusterCondition   `json:\"conditions,omitempty\" protobuf:\"bytes,1,rep,name=conditions\"`\n\tPhase              EtcdClusterPhase         `json:\"phase\" protobuf:\"bytes,2,opt,name=phase,casttype=EtcdClusterPhase\"`\n\tMembers            []MemberStatus           `json:\"members,omitempty\" protobuf:\"bytes,3,rep,name=members\"`\n\tFeatureGatesStatus map[KStoneFeature]string `json:\"featureGatesStatus,omitempty\" protobuf:\"bytes,4,rep,name=featureGatesStatus,castkey=KStoneFeature\"`\n\tServiceName        string                   `json:\"serviceName,omitempty\" protobuf:\"bytes,5,opt,name=serviceName\"`\n}\n\ntype MemberPhase string\n\nconst (\n\tMemberPhaseUnStarted MemberPhase = \"UnStarted\" // etcd member list return unstarted\n\tMemberPhaseUnKnown   MemberPhase = \"UnKnown\"   // endpoint can not be connected\n\tMemberPhaseRunning   MemberPhase = \"Running\"   // health check returns healthy\n\tMemberPhaseUnHealthy MemberPhase = \"UnHealthy\" // health check returns unhealthy\n)\n\ntype EtcdMemberRole string\n\nconst (\n\tEtcdMemberLearner EtcdMemberRole = \"Learner\"\n\t// kstone can get the list of etcd members, but cannot connect to the endpoint.\n\tEtcdMemberUnKnown  EtcdMemberRole = \"UnKnown\"\n\tEtcdMemberFollower EtcdMemberRole = \"Follower\"\n\tEtcdMemberLeader   EtcdMemberRole = \"Leader\"\n)\n\ntype MemberStatus struct {\n\tName               string         `json:\"name\" protobuf:\"bytes,1,opt,name=name\"`\n\tMemberId           string         `json:\"memberId\" protobuf:\"bytes,2,opt,name=memberId\"`\n\tStatus             MemberPhase    `json:\"status\" protobuf:\"bytes,3,opt,name=status,casttype=MemberPhase\"`\n\tVersion            string         `json:\"version\" protobuf:\"bytes,4,opt,name=version\"`\n\tEndpoint           string         `json:\"endpoint\" protobuf:\"bytes,5,opt,name=endpoint\"`\n\tPort               string         `json:\"port\" protobuf:\"bytes,6,opt,name=port\"`\n\tClientUrl          string         `json:\"clientUrl\" protobuf:\"bytes,7,opt,name=clientUrl\"`\n\tExtensionClientUrl string         `json:\"extensionClientUrl\" protobuf:\"bytes,8,opt,name=extensionClientUrl\"`\n\tRole               EtcdMemberRole `json:\"role\" protobuf:\"bytes,9,opt,name=role,casttype=EtcdMemberRole\"`\n\tErrors             []string       `json:\"errors,omitempty\" protobuf:\"bytes,10,rep,name=errors\"`\n}\n\n// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n\n// EtcdClusterList contains a list of EtcdCluster\ntype EtcdClusterList struct {\n\tmetav1.TypeMeta `json:\",inline\"`\n\tmetav1.ListMeta `json:\"metadata,omitempty\" protobuf:\"bytes,1,opt,name=metadata\"`\n\tItems           []EtcdCluster `json:\"items\" protobuf:\"bytes,2,rep,name=items\"`\n}\n\n// +genclient\n// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n// +k8s:defaulter-gen=TypeMeta\n\n// EtcdInspection is a specification for a EtcdInspection resource\ntype EtcdInspection struct {\n\tmetav1.TypeMeta   `json:\",inline\"`\n\tmetav1.ObjectMeta `json:\"metadata,omitempty\" protobuf:\"bytes,1,opt,name=metadata\"`\n\n\tSpec   EtcdInspectionSpec   `json:\"spec,omitempty\" protobuf:\"bytes,2,opt,name=spec\"`\n\tStatus EtcdInspectionStatus `json:\"status,omitempty\" protobuf:\"bytes,3,opt,name=status\"`\n}\n\n// EtcdInspectionSpec is the spec for a EtcdInspectionSpec resource\ntype EtcdInspectionSpec struct {\n\tClusterName        string `json:\"clusterName\" protobuf:\"bytes,1,opt,name=clusterName\"`\n\tInspectionType     string `json:\"inspectionType\" protobuf:\"bytes,2,opt,name=inspectionType\"`\n\tInspectionProvider string `json:\"inspectionProvider,omitempty\" protobuf:\"bytes,3,opt,name=inspectionProvider\"`\n\tIntervalInSecond   int    `json:\"intervalInSecond,omitempty\" protobuf:\"varint,4,opt,name=intervalInSecond\"`\n}\n\n// EtcdInspectionRecord is the status record for a EtcdInspectionRecord resource\ntype EtcdInspectionRecord struct {\n\t// Last time we got an update on a given condition.\n\t// +optional\n\tStartTime metav1.Time `json:\"startTime,omitempty\" protobuf:\"bytes,1,opt,name=startTime\"`\n\t// Last time the condition transit from one status to another.\n\t// +optional\n\tEndTime metav1.Time `json:\"endTime,omitempty\" protobuf:\"bytes,2,opt,name=endTime\"`\n\t// (brief) reason for the condition's last transition.\n\t// +optional\n\tReason string `json:\"reason,omitempty\" protobuf:\"bytes,3,opt,name=reason\"`\n\t// Human readable message indicating details about last transition.\n\t// +optional\n\tMessage string `json:\"message,omitempty\" protobuf:\"bytes,4,opt,name=message\"`\n}\n\n// EtcdInspectionStatus is the status for a EtcdInspectionStatus resource\ntype EtcdInspectionStatus struct {\n\tReason          string                 `json:\"reason,omitempty\" protobuf:\"bytes,1,opt,name=reason\"`\n\tMessage         string                 `json:\"message,omitempty\" protobuf:\"bytes,2,opt,name=message\"`\n\tRecords         []EtcdInspectionRecord `json:\"records,omitempty\" protobuf:\"bytes,3,rep,name=records\"`\n\tLastUpdatedTime metav1.Time            `json:\"lastUpdatedTime,omitempty\" protobuf:\"bytes,4,opt,name=lastUpdatedTime\"`\n}\n\n// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n\n// EtcdInspectionList is a list of EtcdInspection resources\ntype EtcdInspectionList struct {\n\tmetav1.TypeMeta `json:\",inline\"`\n\tmetav1.ListMeta `json:\"metadata\" protobuf:\"bytes,1,opt,name=metadata\"`\n\n\tItems []EtcdInspection `json:\"items\" protobuf:\"bytes,2,rep,name=items\"`\n}\n"
  },
  {
    "path": "pkg/apis/kstone/v1alpha1/zz_generated.deepcopy.go",
    "content": "// +build !ignore_autogenerated\n\n/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by deepcopy-gen. DO NOT EDIT.\n\npackage v1alpha1\n\nimport (\n\tv1 \"k8s.io/api/core/v1\"\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n)\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *AuthConfig) DeepCopyInto(out *AuthConfig) {\n\t*out = *in\n\tif in.SAN != nil {\n\t\tin, out := &in.SAN, &out.SAN\n\t\t*out = make([]string, len(*in))\n\t\tcopy(*out, *in)\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthConfig.\nfunc (in *AuthConfig) DeepCopy() *AuthConfig {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(AuthConfig)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdCluster) DeepCopyInto(out *EtcdCluster) {\n\t*out = *in\n\tout.TypeMeta = in.TypeMeta\n\tin.ObjectMeta.DeepCopyInto(&out.ObjectMeta)\n\tin.Spec.DeepCopyInto(&out.Spec)\n\tin.Status.DeepCopyInto(&out.Status)\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdCluster.\nfunc (in *EtcdCluster) DeepCopy() *EtcdCluster {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdCluster)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.\nfunc (in *EtcdCluster) DeepCopyObject() runtime.Object {\n\tif c := in.DeepCopy(); c != nil {\n\t\treturn c\n\t}\n\treturn nil\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdClusterCondition) DeepCopyInto(out *EtcdClusterCondition) {\n\t*out = *in\n\tin.StartTime.DeepCopyInto(&out.StartTime)\n\tin.EndTime.DeepCopyInto(&out.EndTime)\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdClusterCondition.\nfunc (in *EtcdClusterCondition) DeepCopy() *EtcdClusterCondition {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdClusterCondition)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdClusterList) DeepCopyInto(out *EtcdClusterList) {\n\t*out = *in\n\tout.TypeMeta = in.TypeMeta\n\tin.ListMeta.DeepCopyInto(&out.ListMeta)\n\tif in.Items != nil {\n\t\tin, out := &in.Items, &out.Items\n\t\t*out = make([]EtcdCluster, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdClusterList.\nfunc (in *EtcdClusterList) DeepCopy() *EtcdClusterList {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdClusterList)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.\nfunc (in *EtcdClusterList) DeepCopyObject() runtime.Object {\n\tif c := in.DeepCopy(); c != nil {\n\t\treturn c\n\t}\n\treturn nil\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdClusterSpec) DeepCopyInto(out *EtcdClusterSpec) {\n\t*out = *in\n\tin.AuthConfig.DeepCopyInto(&out.AuthConfig)\n\tin.Affinity.DeepCopyInto(&out.Affinity)\n\tif in.Args != nil {\n\t\tin, out := &in.Args, &out.Args\n\t\t*out = make([]string, len(*in))\n\t\tcopy(*out, *in)\n\t}\n\tif in.Env != nil {\n\t\tin, out := &in.Env, &out.Env\n\t\t*out = make([]v1.EnvVar, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdClusterSpec.\nfunc (in *EtcdClusterSpec) DeepCopy() *EtcdClusterSpec {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdClusterSpec)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdClusterStatus) DeepCopyInto(out *EtcdClusterStatus) {\n\t*out = *in\n\tif in.Conditions != nil {\n\t\tin, out := &in.Conditions, &out.Conditions\n\t\t*out = make([]EtcdClusterCondition, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n\tif in.Members != nil {\n\t\tin, out := &in.Members, &out.Members\n\t\t*out = make([]MemberStatus, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n\tif in.FeatureGatesStatus != nil {\n\t\tin, out := &in.FeatureGatesStatus, &out.FeatureGatesStatus\n\t\t*out = make(map[KStoneFeature]string, len(*in))\n\t\tfor key, val := range *in {\n\t\t\t(*out)[key] = val\n\t\t}\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdClusterStatus.\nfunc (in *EtcdClusterStatus) DeepCopy() *EtcdClusterStatus {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdClusterStatus)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdInspection) DeepCopyInto(out *EtcdInspection) {\n\t*out = *in\n\tout.TypeMeta = in.TypeMeta\n\tin.ObjectMeta.DeepCopyInto(&out.ObjectMeta)\n\tout.Spec = in.Spec\n\tin.Status.DeepCopyInto(&out.Status)\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdInspection.\nfunc (in *EtcdInspection) DeepCopy() *EtcdInspection {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdInspection)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.\nfunc (in *EtcdInspection) DeepCopyObject() runtime.Object {\n\tif c := in.DeepCopy(); c != nil {\n\t\treturn c\n\t}\n\treturn nil\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdInspectionList) DeepCopyInto(out *EtcdInspectionList) {\n\t*out = *in\n\tout.TypeMeta = in.TypeMeta\n\tin.ListMeta.DeepCopyInto(&out.ListMeta)\n\tif in.Items != nil {\n\t\tin, out := &in.Items, &out.Items\n\t\t*out = make([]EtcdInspection, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdInspectionList.\nfunc (in *EtcdInspectionList) DeepCopy() *EtcdInspectionList {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdInspectionList)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.\nfunc (in *EtcdInspectionList) DeepCopyObject() runtime.Object {\n\tif c := in.DeepCopy(); c != nil {\n\t\treturn c\n\t}\n\treturn nil\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdInspectionRecord) DeepCopyInto(out *EtcdInspectionRecord) {\n\t*out = *in\n\tin.StartTime.DeepCopyInto(&out.StartTime)\n\tin.EndTime.DeepCopyInto(&out.EndTime)\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdInspectionRecord.\nfunc (in *EtcdInspectionRecord) DeepCopy() *EtcdInspectionRecord {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdInspectionRecord)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdInspectionSpec) DeepCopyInto(out *EtcdInspectionSpec) {\n\t*out = *in\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdInspectionSpec.\nfunc (in *EtcdInspectionSpec) DeepCopy() *EtcdInspectionSpec {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdInspectionSpec)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdInspectionStatus) DeepCopyInto(out *EtcdInspectionStatus) {\n\t*out = *in\n\tif in.Records != nil {\n\t\tin, out := &in.Records, &out.Records\n\t\t*out = make([]EtcdInspectionRecord, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n\tin.LastUpdatedTime.DeepCopyInto(&out.LastUpdatedTime)\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdInspectionStatus.\nfunc (in *EtcdInspectionStatus) DeepCopy() *EtcdInspectionStatus {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdInspectionStatus)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *MemberStatus) DeepCopyInto(out *MemberStatus) {\n\t*out = *in\n\tif in.Errors != nil {\n\t\tin, out := &in.Errors, &out.Errors\n\t\t*out = make([]string, len(*in))\n\t\tcopy(*out, *in)\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemberStatus.\nfunc (in *MemberStatus) DeepCopy() *MemberStatus {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(MemberStatus)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n"
  },
  {
    "path": "pkg/apis/kstone/v1alpha1/zz_generated.defaults.go",
    "content": "// +build !ignore_autogenerated\n\n/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by defaulter-gen. DO NOT EDIT.\n\npackage v1alpha1\n\nimport (\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n)\n\n// RegisterDefaults adds defaulters functions to the given scheme.\n// Public to allow building arbitrary schemes.\n// All generated defaulters are covering - they call all nested defaulters.\nfunc RegisterDefaults(scheme *runtime.Scheme) error {\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/apis/kstone/v1alpha2/doc.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// +k8s:deepcopy-gen=package\n// +groupName=kstone.tkestack.io\n\n// Package v1alpha2 is the v1alpha2 version of the API.\npackage v1alpha2\n"
  },
  {
    "path": "pkg/apis/kstone/v1alpha2/register.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage v1alpha2\n\nimport (\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\n\tplatform \"tkestack.io/kstone/pkg/apis/kstone\"\n)\n\n// SchemeGroupVersion is group version used to register these objects\nvar SchemeGroupVersion = schema.GroupVersion{Group: platform.GroupName, Version: \"v1alpha2\"}\n\n// Kind takes an unqualified kind and returns back a Group qualified GroupKind\nfunc Kind(kind string) schema.GroupKind {\n\treturn SchemeGroupVersion.WithKind(kind).GroupKind()\n}\n\n// Resource takes an unqualified resource and returns a Group qualified GroupResource\nfunc Resource(resource string) schema.GroupResource {\n\treturn SchemeGroupVersion.WithResource(resource).GroupResource()\n}\n\nvar (\n\t// SchemeBuilder initializes a scheme builder\n\tSchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)\n\t// AddToScheme is a global function that registers this API group & version to a scheme\n\tAddToScheme = SchemeBuilder.AddToScheme\n)\n\n// Adds the list of known types to Scheme.\nfunc addKnownTypes(scheme *runtime.Scheme) error {\n\tscheme.AddKnownTypes(SchemeGroupVersion,\n\t\t&EtcdCluster{},\n\t\t&EtcdClusterList{},\n\t\t&EtcdInspection{},\n\t\t&EtcdInspectionList{},\n\t)\n\tmetav1.AddToGroupVersion(scheme, SchemeGroupVersion)\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/apis/kstone/v1alpha2/types.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage v1alpha2\n\nimport (\n\tcorev1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\n// +genclient\n// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n\n// EtcdCluster is the Schema for the etcdclusters API\ntype EtcdCluster struct {\n\tmetav1.TypeMeta   `json:\",inline\"`\n\tmetav1.ObjectMeta `json:\"metadata,omitempty\" protobuf:\"bytes,1,opt,name=metadata\"`\n\n\tSpec   EtcdClusterSpec   `json:\"spec,omitempty\" protobuf:\"bytes,2,opt,name=spec\"`\n\tStatus EtcdClusterStatus `json:\"status,omitempty\" protobuf:\"bytes,3,opt,name=status\"`\n}\n\ntype EtcdClusterPhase string\n\nconst (\n\tEtcdClusterInit      EtcdClusterPhase = \"Initing\"\n\tEtcdCluterCreating   EtcdClusterPhase = \"Creating\"\n\tEtcdClusterRunning   EtcdClusterPhase = \"Running\"\n\tEtcdClusterUpdating  EtcdClusterPhase = \"Updating\"\n\tEtcdClusterDeleteing EtcdClusterPhase = \"Deleting\"\n\tEtcdClusterDeleted   EtcdClusterPhase = \"Deleted\"\n\tEtcdClusterUnknown   EtcdClusterPhase = \"Unknown\"   // connection refused or other errors\n\tEtcdClusterUnhealthy EtcdClusterPhase = \"UnHealthy\" // node health check returns unhealthy\n)\n\ntype EtcdClusterConditionType string\n\nconst (\n\tEtcdClusterConditionCreate EtcdClusterConditionType = \"Create\"\n\tEtcdClusterConditionImport EtcdClusterConditionType = \"Import\"\n\tEtcdClusterConditionUpdate EtcdClusterConditionType = \"Update\"\n\tEtcdClusterConditionDelete EtcdClusterConditionType = \"Delete\"\n)\n\n// EtcdClusterCondition contains condition information for a EtcdCluster.\ntype EtcdClusterCondition struct {\n\t// Type of EtcdCluster condition.\n\tType EtcdClusterConditionType `json:\"type\" protobuf:\"bytes,1,opt,name=type,casttype=EtcdClusterPhase\"`\n\t// Status of the condition, one of True, False, Unknown.\n\tStatus corev1.ConditionStatus `json:\"status\" protobuf:\"bytes,2,opt,name=status,casttype=k8s.io/api/core/v1.ConditionStatus\"`\n\t// Last time we got an update on a given condition.\n\t// +optional\n\tStartTime metav1.Time `json:\"startTime,omitempty\" protobuf:\"bytes,3,opt,name=startTime\"`\n\t// Last time the condition transit from one status to another.\n\t// +optional\n\tEndTime metav1.Time `json:\"endTime,omitempty\" protobuf:\"bytes,4,opt,name=endTime\"`\n\t// (brief) reason for the condition's last transition.\n\t// +optional\n\tReason string `json:\"reason,omitempty\" protobuf:\"bytes,5,opt,name=reason\"`\n\t// Human readable message indicating details about last transition.\n\t// +optional\n\tMessage string `json:\"message,omitempty\" protobuf:\"bytes,6,opt,name=message\"`\n}\n\ntype EtcdClusterType string\n\nconst (\n\tEtcdClusterKstone   EtcdClusterType = \"kstone-etcd-operator\"\n\tEtcdClusterImported EtcdClusterType = \"imported\"\n)\n\ntype EtcdStorageBackend string\n\nconst (\n\tEtcdStorageV2 EtcdStorageBackend = \"v2\"\n\tEtcdStorageV3 EtcdStorageBackend = \"v3\"\n)\n\n// EtcdClusterSpec defines the desired state of EtcdCluster\ntype EtcdClusterSpec struct {\n\tName        string `json:\"name\" protobuf:\"bytes,1,opt,name=name\"`               // etcd cluster name，uniqueKey\n\tDescription string `json:\"description\" protobuf:\"bytes,2,opt,name=description\"` // etcd description\n\n\tAuthConfig AuthConfig `json:\"authConfig,omitempty\" protobuf:\"bytes,3,opt,name=authConfig\"` // tls config\n\n\tDiskType string `json:\"diskType\" protobuf:\"bytes,4,opt,name=diskType\"`  // disk type, CLOUD_SSD/CLOUD_PREMIUM/CLOUD_BASIC\n\tDiskSize uint   `json:\"diskSize\" protobuf:\"varint,5,opt,name=diskSize\"` // single node's disk size, unit: GB\n\tSize     uint   `json:\"size\"  protobuf:\"varint,6,opt,name=size\"`        // etcd cluster member count: support 1, 3, 5, 7\n\n\tAffinity       corev1.Affinity `json:\"affinity,omitempty\" protobuf:\"bytes,7,opt,name=affinity\"`\n\tArgs           []string        `json:\"args,omitempty\" protobuf:\"bytes,8,rep,name=args\"`\n\tEnv            []corev1.EnvVar `json:\"env,omitempty\" protobuf:\"bytes,9,rep,name=env\"` // etcd environment variables\n\tStorageBackend string          `json:\"storageBackend\" protobuf:\"bytes,7,opt,name=storageBackend\"`\n\tVersion        string          `json:\"version\" protobuf:\"bytes,10,opt,name=version\"`                 // etcd version\n\tRepository     string          `json:\"repository,omitempty\" protobuf:\"bytes,11,opt,name=repository\"` // etcd image\n\n\tClusterType EtcdClusterType `json:\"clusterType\" protobuf:\"bytes,12,opt,name=clusterType,casttype=EtcdClusterType\"` // ClusterType specifies the etcd cluster provider.\n\n\tResources corev1.ResourceRequirements `json:\"resources,omitempty\" protobuf:\"bytes,13,opt,name=resources\"` // Resources specifies requests and limits\n\t// If specified, the pod's tolerations.\n\t// +optional\n\tTolerations []corev1.Toleration `json:\"tolerations,omitempty\"`\n}\n\n// AuthConfig defines tls\ntype AuthConfig struct {\n\tEnableTLS bool     `json:\"enableTLS,omitempty\" protobuf:\"varint,1,opt,name=enableTLS\"`\n\tSAN       []string `json:\"san,omitempty\" protobuf:\"bytes,2,rep,name=san\"`\n\tTLSSecret string   `json:\"tlsSecret,omitempty\" protobuf:\"bytes,3,opt,name=tlsSecret\"`\n}\n\ntype KStoneFeature string\n\nconst (\n\tKStoneFeatureAnno                      = \"featureGates\"\n\tKStoneFeatureMonitor     KStoneFeature = \"monitor\"\n\tKStoneFeatureBackup      KStoneFeature = \"backup\"\n\tKStoneFeatureHealthy     KStoneFeature = \"healthy\"\n\tKStoneFeatureConsistency KStoneFeature = \"consistency\"\n\tKStoneFeatureRequest     KStoneFeature = \"request\"\n\tKStoneFeatureAlarm       KStoneFeature = \"alarm\"\n\tKStoneFeatureBackupCheck KStoneFeature = \"backupcheck\"\n)\n\n// EtcdClusterStatus defines the actual state of EtcdCluster.\ntype EtcdClusterStatus struct {\n\tConditions         []EtcdClusterCondition   `json:\"conditions,omitempty\" protobuf:\"bytes,1,rep,name=conditions\"`\n\tPhase              EtcdClusterPhase         `json:\"phase\" protobuf:\"bytes,2,opt,name=phase,casttype=EtcdClusterPhase\"`\n\tMembers            []MemberStatus           `json:\"members,omitempty\" protobuf:\"bytes,3,rep,name=members\"`\n\tFeatureGatesStatus map[KStoneFeature]string `json:\"featureGatesStatus,omitempty\" protobuf:\"bytes,4,rep,name=featureGatesStatus,castkey=KStoneFeature\"`\n\tServiceName        string                   `json:\"serviceName,omitempty\" protobuf:\"bytes,5,opt,name=serviceName\"`\n}\n\ntype MemberPhase string\n\nconst (\n\tMemberPhaseUnStarted MemberPhase = \"UnStarted\" // etcd member list return unstarted\n\tMemberPhaseUnKnown   MemberPhase = \"UnKnown\"   // endpoint can not be connected\n\tMemberPhaseRunning   MemberPhase = \"Running\"   // health check returns healthy\n\tMemberPhaseUnHealthy MemberPhase = \"UnHealthy\" // health check returns unhealthy\n)\n\ntype EtcdMemberRole string\n\nconst (\n\tEtcdMemberLearner EtcdMemberRole = \"Learner\"\n\t// kstone can get the list of etcd members, but cannot connect to the endpoint.\n\tEtcdMemberUnKnown  EtcdMemberRole = \"UnKnown\"\n\tEtcdMemberFollower EtcdMemberRole = \"Follower\"\n\tEtcdMemberLeader   EtcdMemberRole = \"Leader\"\n)\n\ntype MemberStatus struct {\n\tName               string         `json:\"name\" protobuf:\"bytes,1,opt,name=name\"`\n\tMemberId           string         `json:\"memberId\" protobuf:\"bytes,2,opt,name=memberId\"`\n\tStatus             MemberPhase    `json:\"status\" protobuf:\"bytes,3,opt,name=status,casttype=MemberPhase\"`\n\tVersion            string         `json:\"version\" protobuf:\"bytes,4,opt,name=version\"`\n\tEndpoint           string         `json:\"endpoint\" protobuf:\"bytes,5,opt,name=endpoint\"`\n\tPort               string         `json:\"port\" protobuf:\"bytes,6,opt,name=port\"`\n\tClientUrl          string         `json:\"clientUrl\" protobuf:\"bytes,7,opt,name=clientUrl\"`\n\tExtensionClientUrl string         `json:\"extensionClientUrl\" protobuf:\"bytes,8,opt,name=extensionClientUrl\"`\n\tRole               EtcdMemberRole `json:\"role\" protobuf:\"bytes,9,opt,name=role,casttype=EtcdMemberRole\"`\n\tErrors             []string       `json:\"errors,omitempty\" protobuf:\"bytes,10,rep,name=errors\"`\n}\n\n// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n\n// EtcdClusterList contains a list of EtcdCluster\ntype EtcdClusterList struct {\n\tmetav1.TypeMeta `json:\",inline\"`\n\tmetav1.ListMeta `json:\"metadata,omitempty\" protobuf:\"bytes,1,opt,name=metadata\"`\n\tItems           []EtcdCluster `json:\"items\" protobuf:\"bytes,2,rep,name=items\"`\n}\n\n// +genclient\n// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n// +k8s:defaulter-gen=TypeMeta\n\n// EtcdInspection is a specification for a EtcdInspection resource\ntype EtcdInspection struct {\n\tmetav1.TypeMeta   `json:\",inline\"`\n\tmetav1.ObjectMeta `json:\"metadata,omitempty\" protobuf:\"bytes,1,opt,name=metadata\"`\n\n\tSpec   EtcdInspectionSpec   `json:\"spec,omitempty\" protobuf:\"bytes,2,opt,name=spec\"`\n\tStatus EtcdInspectionStatus `json:\"status,omitempty\" protobuf:\"bytes,3,opt,name=status\"`\n}\n\n// EtcdInspectionSpec is the spec for a EtcdInspectionSpec resource\ntype EtcdInspectionSpec struct {\n\tClusterName        string `json:\"clusterName\" protobuf:\"bytes,1,opt,name=clusterName\"`\n\tInspectionType     string `json:\"inspectionType\" protobuf:\"bytes,2,opt,name=inspectionType\"`\n\tInspectionProvider string `json:\"inspectionProvider,omitempty\" protobuf:\"bytes,3,opt,name=inspectionProvider\"`\n\tIntervalInSecond   int    `json:\"intervalInSecond,omitempty\" protobuf:\"varint,4,opt,name=intervalInSecond\"`\n}\n\n// EtcdInspectionRecord is the status record for a EtcdInspectionRecord resource\ntype EtcdInspectionRecord struct {\n\t// Last time we got an update on a given condition.\n\t// +optional\n\tStartTime metav1.Time `json:\"startTime,omitempty\" protobuf:\"bytes,1,opt,name=startTime\"`\n\t// Last time the condition transit from one status to another.\n\t// +optional\n\tEndTime metav1.Time `json:\"endTime,omitempty\" protobuf:\"bytes,2,opt,name=endTime\"`\n\t// (brief) reason for the condition's last transition.\n\t// +optional\n\tReason string `json:\"reason,omitempty\" protobuf:\"bytes,3,opt,name=reason\"`\n\t// Human readable message indicating details about last transition.\n\t// +optional\n\tMessage string `json:\"message,omitempty\" protobuf:\"bytes,4,opt,name=message\"`\n}\n\n// EtcdInspectionStatus is the status for a EtcdInspectionStatus resource\ntype EtcdInspectionStatus struct {\n\tReason          string                 `json:\"reason,omitempty\" protobuf:\"bytes,1,opt,name=reason\"`\n\tMessage         string                 `json:\"message,omitempty\" protobuf:\"bytes,2,opt,name=message\"`\n\tRecords         []EtcdInspectionRecord `json:\"records,omitempty\" protobuf:\"bytes,3,rep,name=records\"`\n\tLastUpdatedTime metav1.Time            `json:\"lastUpdatedTime,omitempty\" protobuf:\"bytes,4,opt,name=lastUpdatedTime\"`\n}\n\n// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n\n// EtcdInspectionList is a list of EtcdInspection resources\ntype EtcdInspectionList struct {\n\tmetav1.TypeMeta `json:\",inline\"`\n\tmetav1.ListMeta `json:\"metadata\" protobuf:\"bytes,1,opt,name=metadata\"`\n\n\tItems []EtcdInspection `json:\"items\" protobuf:\"bytes,2,rep,name=items\"`\n}\n"
  },
  {
    "path": "pkg/apis/kstone/v1alpha2/zz_generated.deepcopy.go",
    "content": "// +build !ignore_autogenerated\n\n/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by deepcopy-gen. DO NOT EDIT.\n\npackage v1alpha2\n\nimport (\n\tv1 \"k8s.io/api/core/v1\"\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n)\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *AuthConfig) DeepCopyInto(out *AuthConfig) {\n\t*out = *in\n\tif in.SAN != nil {\n\t\tin, out := &in.SAN, &out.SAN\n\t\t*out = make([]string, len(*in))\n\t\tcopy(*out, *in)\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthConfig.\nfunc (in *AuthConfig) DeepCopy() *AuthConfig {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(AuthConfig)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdCluster) DeepCopyInto(out *EtcdCluster) {\n\t*out = *in\n\tout.TypeMeta = in.TypeMeta\n\tin.ObjectMeta.DeepCopyInto(&out.ObjectMeta)\n\tin.Spec.DeepCopyInto(&out.Spec)\n\tin.Status.DeepCopyInto(&out.Status)\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdCluster.\nfunc (in *EtcdCluster) DeepCopy() *EtcdCluster {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdCluster)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.\nfunc (in *EtcdCluster) DeepCopyObject() runtime.Object {\n\tif c := in.DeepCopy(); c != nil {\n\t\treturn c\n\t}\n\treturn nil\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdClusterCondition) DeepCopyInto(out *EtcdClusterCondition) {\n\t*out = *in\n\tin.StartTime.DeepCopyInto(&out.StartTime)\n\tin.EndTime.DeepCopyInto(&out.EndTime)\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdClusterCondition.\nfunc (in *EtcdClusterCondition) DeepCopy() *EtcdClusterCondition {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdClusterCondition)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdClusterList) DeepCopyInto(out *EtcdClusterList) {\n\t*out = *in\n\tout.TypeMeta = in.TypeMeta\n\tin.ListMeta.DeepCopyInto(&out.ListMeta)\n\tif in.Items != nil {\n\t\tin, out := &in.Items, &out.Items\n\t\t*out = make([]EtcdCluster, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdClusterList.\nfunc (in *EtcdClusterList) DeepCopy() *EtcdClusterList {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdClusterList)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.\nfunc (in *EtcdClusterList) DeepCopyObject() runtime.Object {\n\tif c := in.DeepCopy(); c != nil {\n\t\treturn c\n\t}\n\treturn nil\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdClusterSpec) DeepCopyInto(out *EtcdClusterSpec) {\n\t*out = *in\n\tin.AuthConfig.DeepCopyInto(&out.AuthConfig)\n\tin.Affinity.DeepCopyInto(&out.Affinity)\n\tif in.Args != nil {\n\t\tin, out := &in.Args, &out.Args\n\t\t*out = make([]string, len(*in))\n\t\tcopy(*out, *in)\n\t}\n\tif in.Env != nil {\n\t\tin, out := &in.Env, &out.Env\n\t\t*out = make([]v1.EnvVar, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n\tin.Resources.DeepCopyInto(&out.Resources)\n\tif in.Tolerations != nil {\n\t\tin, out := &in.Tolerations, &out.Tolerations\n\t\t*out = make([]v1.Toleration, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdClusterSpec.\nfunc (in *EtcdClusterSpec) DeepCopy() *EtcdClusterSpec {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdClusterSpec)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdClusterStatus) DeepCopyInto(out *EtcdClusterStatus) {\n\t*out = *in\n\tif in.Conditions != nil {\n\t\tin, out := &in.Conditions, &out.Conditions\n\t\t*out = make([]EtcdClusterCondition, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n\tif in.Members != nil {\n\t\tin, out := &in.Members, &out.Members\n\t\t*out = make([]MemberStatus, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n\tif in.FeatureGatesStatus != nil {\n\t\tin, out := &in.FeatureGatesStatus, &out.FeatureGatesStatus\n\t\t*out = make(map[KStoneFeature]string, len(*in))\n\t\tfor key, val := range *in {\n\t\t\t(*out)[key] = val\n\t\t}\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdClusterStatus.\nfunc (in *EtcdClusterStatus) DeepCopy() *EtcdClusterStatus {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdClusterStatus)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdInspection) DeepCopyInto(out *EtcdInspection) {\n\t*out = *in\n\tout.TypeMeta = in.TypeMeta\n\tin.ObjectMeta.DeepCopyInto(&out.ObjectMeta)\n\tout.Spec = in.Spec\n\tin.Status.DeepCopyInto(&out.Status)\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdInspection.\nfunc (in *EtcdInspection) DeepCopy() *EtcdInspection {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdInspection)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.\nfunc (in *EtcdInspection) DeepCopyObject() runtime.Object {\n\tif c := in.DeepCopy(); c != nil {\n\t\treturn c\n\t}\n\treturn nil\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdInspectionList) DeepCopyInto(out *EtcdInspectionList) {\n\t*out = *in\n\tout.TypeMeta = in.TypeMeta\n\tin.ListMeta.DeepCopyInto(&out.ListMeta)\n\tif in.Items != nil {\n\t\tin, out := &in.Items, &out.Items\n\t\t*out = make([]EtcdInspection, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdInspectionList.\nfunc (in *EtcdInspectionList) DeepCopy() *EtcdInspectionList {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdInspectionList)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.\nfunc (in *EtcdInspectionList) DeepCopyObject() runtime.Object {\n\tif c := in.DeepCopy(); c != nil {\n\t\treturn c\n\t}\n\treturn nil\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdInspectionRecord) DeepCopyInto(out *EtcdInspectionRecord) {\n\t*out = *in\n\tin.StartTime.DeepCopyInto(&out.StartTime)\n\tin.EndTime.DeepCopyInto(&out.EndTime)\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdInspectionRecord.\nfunc (in *EtcdInspectionRecord) DeepCopy() *EtcdInspectionRecord {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdInspectionRecord)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdInspectionSpec) DeepCopyInto(out *EtcdInspectionSpec) {\n\t*out = *in\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdInspectionSpec.\nfunc (in *EtcdInspectionSpec) DeepCopy() *EtcdInspectionSpec {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdInspectionSpec)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdInspectionStatus) DeepCopyInto(out *EtcdInspectionStatus) {\n\t*out = *in\n\tif in.Records != nil {\n\t\tin, out := &in.Records, &out.Records\n\t\t*out = make([]EtcdInspectionRecord, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n\tin.LastUpdatedTime.DeepCopyInto(&out.LastUpdatedTime)\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdInspectionStatus.\nfunc (in *EtcdInspectionStatus) DeepCopy() *EtcdInspectionStatus {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdInspectionStatus)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *MemberStatus) DeepCopyInto(out *MemberStatus) {\n\t*out = *in\n\tif in.Errors != nil {\n\t\tin, out := &in.Errors, &out.Errors\n\t\t*out = make([]string, len(*in))\n\t\tcopy(*out, *in)\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemberStatus.\nfunc (in *MemberStatus) DeepCopy() *MemberStatus {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(MemberStatus)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n"
  },
  {
    "path": "pkg/apis/kstone/v1alpha2/zz_generated.defaults.go",
    "content": "// +build !ignore_autogenerated\n\n/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by defaulter-gen. DO NOT EDIT.\n\npackage v1alpha2\n\nimport (\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n)\n\n// RegisterDefaults adds defaulters functions to the given scheme.\n// Public to allow building arbitrary schemes.\n// All generated defaulters are covering - they call all nested defaulters.\nfunc RegisterDefaults(scheme *runtime.Scheme) error {\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/authentication/authenticator/authenticator.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage authenticator\n\nimport (\n\t\"sync\"\n\n\t\"github.com/gin-gonic/gin\"\n\n\t\"tkestack.io/kstone/cmd/kstone-api/config\"\n\t\"tkestack.io/kstone/pkg/authentication\"\n)\n\nconst (\n\tProviderName = \"generic\"\n)\n\nvar (\n\tonce     sync.Once\n\tinstance *Authenticator\n)\n\ntype Authenticator struct{}\n\nfunc init() {\n\tauthentication.RegisterAuthenticatorFactory(ProviderName,\n\t\tfunc(ctx *authentication.AuthenticatorContext) (authentication.Request, error) {\n\t\t\treturn initAuthenticatorInstance(ctx)\n\t\t},\n\t)\n}\n\nfunc initAuthenticatorInstance(ctx *authentication.AuthenticatorContext) (*Authenticator, error) {\n\tonce.Do(func() {\n\t\tinstance = &Authenticator{}\n\t})\n\treturn instance, nil\n}\n\n// AuthenticateRequest authenticates the request using custom authenticator.Request objects.\nfunc (a *Authenticator) AuthenticateRequest(ctx *gin.Context) (*authentication.Response, bool, error) {\n\tauthenticator, err := authentication.GetAuthenticatorProvider(config.Cfg.Authenticator, &authentication.AuthenticatorContext{})\n\tif err != nil {\n\t\treturn authentication.UnauthenticatedResponse(), false, err\n\t}\n\treturn authenticator.AuthenticateRequest(ctx)\n}\n"
  },
  {
    "path": "pkg/authentication/authenticator/bearertoken/bearertoken.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage bearertoken\n\nimport (\n\t\"context\"\n\t\"sync\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"k8s.io/klog/v2\"\n\n\t\"tkestack.io/kstone/cmd/kstone-api/config\"\n\t\"tkestack.io/kstone/pkg/authentication\"\n)\n\nconst (\n\tProviderName = \"bearertoken\"\n)\n\nvar (\n\tauthContextOnce sync.Once\n\tauthenticator   *Authenticator\n)\n\ntype Authenticator struct{}\n\nfunc init() {\n\tauthentication.RegisterAuthenticatorFactory(ProviderName,\n\t\tfunc(ctx *authentication.AuthenticatorContext) (authentication.Request, error) {\n\t\t\treturn initAuthenticatorInstance(ctx)\n\t\t},\n\t)\n}\n\nfunc initAuthenticatorInstance(ctx *authentication.AuthenticatorContext) (*Authenticator, error) {\n\tauthContextOnce.Do(func() {\n\t\tauthenticator = &Authenticator{}\n\t})\n\n\treturn authenticator, nil\n}\n\nfunc (a *Authenticator) AuthenticateRequest(ctx *gin.Context) (*authentication.Response, bool, error) {\n\tkey, err := authentication.GetPrivateKey()\n\tif err != nil {\n\t\treturn authentication.InternalServerErrorResponse(authentication.UserUnknown, err.Error()), false, err\n\t}\n\tc := &authentication.TokenContext{\n\t\tSignMethod: authentication.SignMethodRS256,\n\t\tPrivateKey: key,\n\t}\n\tt, err := authentication.GetTokenProvider(config.Cfg.Token, c)\n\tif err != nil {\n\t\tklog.Errorf(\"login error: %v\", err)\n\t\treturn authentication.InternalServerErrorResponse(authentication.UserUnknown, err.Error()), false, err\n\t}\n\treturn t.AuthenticateToken(context.TODO(), ctx.GetHeader(authentication.JWTTokenKey))\n}\n"
  },
  {
    "path": "pkg/authentication/helper.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage authentication\n\nimport (\n\t\"io/ioutil\"\n\n\t\"golang.org/x/crypto/bcrypt\"\n)\n\nconst (\n\tJWTTokenKey = \"kstone-api-jwt\"\n\n\tSignMethodRS256 = \"RS256\"\n\n\tDataSuccess      = \"success\"\n\tDataUnauthorized = \"failed to authenticate user\"\n\tUserUnknown      = \"unknown\"\n\n\tDefaultKeyPath         = \"/app/certs/private.key\"\n\tDefaultKstoneNamespace = \"kstone\"\n\tDefaultUsername        = \"admin\"\n\tDefaultPassword        = \"adm1n@kstone.io\"\n)\n\n// Response is the struct returned by authenticator interfaces\ntype Response struct {\n\tUsername      string `json:\"username\"`\n\tResetPassword bool   `json:\"reset_password\"`\n\tToken         string `json:\"token\"`\n\tMessage       string `json:\"message\"`\n}\n\nvar DefaultConfigMapName = \"kstone-api-user\"\n\nfunc SetAuthConfigMapName(name string) {\n\tDefaultConfigMapName = name\n}\n\nfunc SuccessResponse(username string, message string) *Response {\n\treturn &Response{\n\t\tUsername: username,\n\t\tMessage:  message,\n\t}\n}\n\nfunc SuccessTokenResponse(username string, token string) *Response {\n\treturn &Response{\n\t\tUsername: username,\n\t\tToken:    token,\n\t}\n}\n\nfunc SuccessResetPasswordResponse(username string, token string) *Response {\n\treturn &Response{\n\t\tUsername:      username,\n\t\tToken:         token,\n\t\tResetPassword: true,\n\t}\n}\n\nfunc UnauthenticatedResponse() *Response {\n\treturn &Response{\n\t\tUsername: UserUnknown,\n\t\tMessage:  DataUnauthorized,\n\t}\n}\n\nfunc InternalServerErrorResponse(username string, message string) *Response {\n\treturn &Response{\n\t\tUsername: username,\n\t\tMessage:  message,\n\t}\n}\n\nfunc GetPrivateKey() (string, error) {\n\tkey, err := ioutil.ReadFile(DefaultKeyPath)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn string(key), nil\n}\n\nfunc GeneratePasswordHash(password string) (string, error) {\n\tph, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn string(ph), nil\n}\n\nfunc IsDefaultUser(username, password string) bool {\n\treturn username == DefaultUsername && password == DefaultPassword\n}\n\nfunc CheckPassword(hashedPassword, password string) error {\n\treturn bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))\n}\n"
  },
  {
    "path": "pkg/authentication/interfaces.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage authentication\n\nimport (\n\t\"context\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\n// Token checks a string value against a backing authentication store and\n// returns a Response or an error if the token could not be checked.\ntype Token interface {\n\tAuthenticateToken(ctx context.Context, token string) (*Response, bool, error)\n}\n\n// TokenGenerator generates tokens\ntype TokenGenerator interface {\n\tGenerateToken(ctx context.Context, username string, password string) (string, error)\n}\n\n// Request attempts to extract authentication information from a request and\n// returns a Response or an error if the request could not be checked.\ntype Request interface {\n\tAuthenticateRequest(ctx *gin.Context) (*Response, bool, error)\n}\n\ntype TokenContext struct {\n\tSignMethod string\n\tPrivateKey string\n\tTTL        string\n}\n\ntype AuthenticatorContext struct{}\n"
  },
  {
    "path": "pkg/authentication/plugins.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage authentication\n\nimport (\n\t\"errors\"\n\t\"sync\"\n\n\t\"k8s.io/klog/v2\"\n)\n\nvar (\n\tmutex                  sync.Mutex\n\tTokenProviders         = make(map[string]TokenFactory)\n\tAuthenticatorProviders = make(map[string]AuthenticatorFactory)\n)\n\ntype TokenFactory func(cfg *TokenContext) (Token, error)\ntype AuthenticatorFactory func(cfg *AuthenticatorContext) (Request, error)\n\n// RegisterTokenFactory registers the specified token provider\nfunc RegisterTokenFactory(name string, factory TokenFactory) {\n\tmutex.Lock()\n\tdefer mutex.Unlock()\n\n\tif _, found := TokenProviders[name]; found {\n\t\tklog.V(2).Infof(\"token provider:%s was registered twice\", name)\n\t}\n\n\tklog.V(2).Infof(\"token provider:%s\", name)\n\tTokenProviders[name] = factory\n}\n\n// RegisterAuthenticatorFactory registers the specified authenticator provider\nfunc RegisterAuthenticatorFactory(name string, factory AuthenticatorFactory) {\n\tmutex.Lock()\n\tdefer mutex.Unlock()\n\n\tif _, found := AuthenticatorProviders[name]; found {\n\t\tklog.V(2).Infof(\"authenticator provider:%s was registered twice\", name)\n\t}\n\n\tklog.V(2).Infof(\"authenticator provider:%s\", name)\n\tAuthenticatorProviders[name] = factory\n}\n\n// GetTokenProvider gets the specified token provider\nfunc GetTokenProvider(name string, ctx *TokenContext) (Token, error) {\n\tmutex.Lock()\n\tdefer mutex.Unlock()\n\tf, found := TokenProviders[name]\n\n\tklog.V(1).Infof(\"get token name %s,status:%t\", name, found)\n\tif !found {\n\t\treturn nil, errors.New(\"fatal error,token provider not found\")\n\t}\n\treturn f(ctx)\n}\n\n// GetAuthenticatorProvider gets the specified authenticator provider\nfunc GetAuthenticatorProvider(name string, ctx *AuthenticatorContext) (Request, error) {\n\tmutex.Lock()\n\tdefer mutex.Unlock()\n\tf, found := AuthenticatorProviders[name]\n\n\tklog.V(1).Infof(\"get token name %s,status:%t\", name, found)\n\tif !found {\n\t\treturn nil, errors.New(\"fatal error,token provider not found\")\n\t}\n\treturn f(ctx)\n}\n"
  },
  {
    "path": "pkg/authentication/providers/providers.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage providers\n\nimport (\n\t// import jwt token provider\n\t_ \"tkestack.io/kstone/pkg/authentication/token/jwt\"\n\n\t// import generic authenticator provider\n\t_ \"tkestack.io/kstone/pkg/authentication/authenticator\"\n\t// import bearer token authenticator provider\n\t_ \"tkestack.io/kstone/pkg/authentication/authenticator/bearertoken\"\n)\n"
  },
  {
    "path": "pkg/authentication/request/request.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage request\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"io/ioutil\"\n\t\"strings\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"k8s.io/klog/v2\"\n\n\t\"tkestack.io/kstone/pkg/authentication\"\n\t\"tkestack.io/kstone/pkg/authentication/authenticator\"\n\t\"tkestack.io/kstone/pkg/authentication/token/jwt\"\n)\n\nfunc LoginRequest(ctx *gin.Context) (*authentication.Response, bool, error) {\n\tusername, password, err := getUser(ctx)\n\tif err != nil {\n\t\tklog.Errorf(\"get user error: %v\", err)\n\t\treturn authentication.UnauthenticatedResponse(), false, err\n\t}\n\n\tstore := authentication.GetDefaultStoreInstance()\n\tuser, err := store.UserGet(username)\n\tif err != nil {\n\t\tklog.Errorf(\"get store user error: %v\", err)\n\t\treturn authentication.UnauthenticatedResponse(), false, err\n\t}\n\n\tif err := authentication.CheckPassword(user.HashedPassword, password); err != nil {\n\t\tklog.Errorf(\"check password error: %v\", err)\n\t\treturn authentication.UnauthenticatedResponse(), false, errors.New(authentication.DataUnauthorized)\n\t}\n\n\ttoken, err := jwt.GenerateToken(username, user.HashedPassword)\n\tif err != nil {\n\t\tklog.Errorf(\"generate token error: %v\", err)\n\t\treturn nil, false, err\n\t}\n\n\tif authentication.IsDefaultUser(username, password) {\n\t\treturn authentication.SuccessResetPasswordResponse(username, token), true, nil\n\t}\n\n\treturn authentication.SuccessTokenResponse(username, token), true, nil\n}\n\nfunc MiddlewareRequest(ctx *gin.Context) (*authentication.Response, bool, error) {\n\ta, err := authentication.GetAuthenticatorProvider(authenticator.ProviderName, &authentication.AuthenticatorContext{})\n\tif err != nil {\n\t\tklog.Errorf(\"get authenticator error: %v\", err)\n\t\treturn authentication.InternalServerErrorResponse(authentication.UserUnknown, err.Error()), false, err\n\t}\n\treturn a.AuthenticateRequest(ctx)\n}\n\nfunc UserListRequest(ctx *gin.Context) (*authentication.Response, error) {\n\tvar usernames []string\n\tstore := authentication.GetDefaultStoreInstance()\n\tusers, err := store.UserList()\n\tif err != nil {\n\t\tklog.Errorf(\"list store users error: %v\", err)\n\t\treturn authentication.UnauthenticatedResponse(), err\n\t}\n\tfor _, u := range users {\n\t\tusernames = append(usernames, u.Name)\n\t}\n\n\treturn authentication.SuccessResponse(\"\", strings.Join(usernames, \",\")), nil\n}\n\nfunc UserUpdateRequest(ctx *gin.Context) (*authentication.Response, error) {\n\tusername, password, err := getUser(ctx)\n\tif err != nil {\n\t\tklog.Errorf(\"get user error: %v\", err)\n\t\treturn authentication.InternalServerErrorResponse(username, err.Error()), err\n\t}\n\tstore := authentication.GetDefaultStoreInstance()\n\tpasswordHash, err := authentication.GeneratePasswordHash(password)\n\tif err != nil {\n\t\tklog.Errorf(\"generate password hash error: %v\", err)\n\t\treturn authentication.InternalServerErrorResponse(username, err.Error()), err\n\t}\n\tif err := store.UserChangePassword(username, passwordHash); err != nil {\n\t\treturn authentication.InternalServerErrorResponse(username, err.Error()), err\n\t}\n\treturn authentication.SuccessResponse(username, authentication.DataSuccess), nil\n}\n\nfunc UserAddRequest(ctx *gin.Context) (*authentication.Response, error) {\n\tusername, password, err := getUser(ctx)\n\tif err != nil {\n\t\tklog.Errorf(\"get user error: %v\", err)\n\t\treturn authentication.InternalServerErrorResponse(username, err.Error()), err\n\t}\n\tstore := authentication.GetDefaultStoreInstance()\n\thashedPassword, err := authentication.GeneratePasswordHash(password)\n\tif err != nil {\n\t\tklog.Errorf(\"generate password hash error: %v\", err)\n\t\treturn authentication.InternalServerErrorResponse(username, err.Error()), err\n\t}\n\tif err := store.UserAdd(authentication.User{Name: username, HashedPassword: hashedPassword}); err != nil {\n\t\treturn authentication.InternalServerErrorResponse(username, err.Error()), err\n\t}\n\treturn authentication.SuccessResponse(username, authentication.DataSuccess), nil\n}\n\nfunc UserDeleteRequest(ctx *gin.Context) (*authentication.Response, error) {\n\tusername, _, err := getUser(ctx)\n\tif err != nil {\n\t\tklog.Errorf(\"get user error: %v\", err)\n\t\treturn authentication.InternalServerErrorResponse(username, err.Error()), err\n\t}\n\tstore := authentication.GetDefaultStoreInstance()\n\tif err := store.UserDelete(username); err != nil {\n\t\treturn authentication.InternalServerErrorResponse(username, err.Error()), err\n\t}\n\treturn authentication.SuccessResponse(username, authentication.DataSuccess), nil\n}\n\nfunc getUser(ctx *gin.Context) (username string, password string, err error) {\n\tbody, err := ioutil.ReadAll(ctx.Request.Body)\n\tif err != nil {\n\t\treturn \"\", \"\", err\n\t}\n\n\trequestMap := make(map[string]string)\n\tif err := json.Unmarshal(body, &requestMap); err != nil {\n\t\treturn \"\", \"\", err\n\t}\n\n\tif requestMap[\"username\"] == \"\" {\n\t\treturn \"\", \"\", errors.New(\"username is empty\")\n\t}\n\n\treturn requestMap[\"username\"], requestMap[\"password\"], nil\n}\n"
  },
  {
    "path": "pkg/authentication/store.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage authentication\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"sync\"\n\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\n\t\"tkestack.io/kstone/pkg/controllers/util\"\n)\n\nvar (\n\tonce     sync.Once\n\tinstance *DefaultStore\n)\n\n// Store gets and updates users\ntype Store interface {\n\t// UserGet gets a user\n\tUserGet(username string) (*User, error)\n\t// UserAdd adds a user\n\tUserAdd(user User) error\n\t// UserDelete deletes a user\n\tUserDelete(username string) error\n\t// UserList lists users\n\tUserList() ([]*User, error)\n\t// UserChangePassword changes a password of a user\n\tUserChangePassword(username, password string) error\n}\n\ntype User struct {\n\tName           string\n\tHashedPassword string\n\tExtraInfo      map[string]interface{}\n}\n\ntype DefaultStore struct {\n\tkubeCli kubernetes.Interface\n}\n\nfunc GetDefaultStoreInstance() *DefaultStore {\n\tonce.Do(func() {\n\t\tinstance = &DefaultStore{\n\t\t\tkubeCli: util.NewSimpleClientBuilder(\"\").ClientOrDie(),\n\t\t}\n\t})\n\treturn instance\n}\n\nfunc (s *DefaultStore) UserGet(username string) (*User, error) {\n\tcm, err := s.kubeCli.CoreV1().ConfigMaps(DefaultKstoneNamespace).Get(context.TODO(), DefaultConfigMapName, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\thashedPassword, ok := cm.Data[username]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"failed to get user %s, user not exists\", username)\n\t}\n\treturn &User{\n\t\tName:           username,\n\t\tHashedPassword: hashedPassword,\n\t}, err\n}\n\nfunc (s *DefaultStore) UserAdd(user User) error {\n\tcm, err := s.kubeCli.CoreV1().ConfigMaps(DefaultKstoneNamespace).Get(context.TODO(), DefaultConfigMapName, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn err\n\t}\n\t_, ok := cm.Data[user.Name]\n\tif ok {\n\t\treturn fmt.Errorf(\"failed to add user %s, user already exists\", user.Name)\n\t}\n\tcm.Data[user.Name] = user.HashedPassword\n\tif _, err := s.kubeCli.CoreV1().ConfigMaps(DefaultKstoneNamespace).Update(context.TODO(), cm, metav1.UpdateOptions{}); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc (s *DefaultStore) UserDelete(username string) error {\n\tcm, err := s.kubeCli.CoreV1().ConfigMaps(DefaultKstoneNamespace).Get(context.TODO(), DefaultConfigMapName, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn err\n\t}\n\t_, ok := cm.Data[username]\n\tif !ok {\n\t\treturn fmt.Errorf(\"failed to delete user %s, user not exists\", username)\n\t}\n\tif len(cm.Data) == 1 {\n\t\treturn fmt.Errorf(\"failed to delete user %s, only one user remains\", username)\n\t}\n\tdelete(cm.Data, username)\n\tif _, err := s.kubeCli.CoreV1().ConfigMaps(DefaultKstoneNamespace).Update(context.TODO(), cm, metav1.UpdateOptions{}); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc (s *DefaultStore) UserList() ([]*User, error) {\n\tvar userList []*User\n\tcm, err := s.kubeCli.CoreV1().ConfigMaps(DefaultKstoneNamespace).Get(context.TODO(), DefaultConfigMapName, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfor u, p := range cm.Data {\n\t\tuserList = append(userList, &User{\n\t\t\tName:           u,\n\t\t\tHashedPassword: p,\n\t\t})\n\t}\n\treturn userList, nil\n}\n\nfunc (s *DefaultStore) UserChangePassword(username, password string) error {\n\tcm, err := s.kubeCli.CoreV1().ConfigMaps(DefaultKstoneNamespace).Get(context.TODO(), DefaultConfigMapName, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn err\n\t}\n\t_, ok := cm.Data[username]\n\tif !ok {\n\t\treturn fmt.Errorf(\"failed to change password for user %s, user not exists\", username)\n\t}\n\tcm.Data[username] = password\n\tif _, err := s.kubeCli.CoreV1().ConfigMaps(DefaultKstoneNamespace).Update(context.TODO(), cm, metav1.UpdateOptions{}); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/authentication/token/jwt/generator.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage jwt\n\nimport (\n\t\"context\"\n\t\"crypto/rsa\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/golang-jwt/jwt\"\n\t\"k8s.io/klog/v2\"\n)\n\nvar (\n\ttokenOnce      sync.Once\n\ttokenGenerator *TokenGenerator\n)\n\ntype TokenGenerator struct {\n\tsignMethod jwt.SigningMethod\n\tkey        interface{}\n\tttl        time.Duration\n}\n\nfunc NewTokenGenerator(ttl, privateKey, signMethod string) (*TokenGenerator, error) {\n\tvar err error\n\ttokenOnce.Do(func() {\n\t\tvar duration time.Duration\n\t\tvar key *rsa.PrivateKey\n\t\tif ttl == \"\" {\n\t\t\tduration = defaultTTL\n\t\t} else {\n\t\t\tduration, err = time.ParseDuration(ttl)\n\t\t}\n\n\t\tkey, err = jwt.ParseRSAPrivateKeyFromPEM([]byte(privateKey))\n\t\ttokenGenerator = &TokenGenerator{\n\t\t\tsignMethod: jwt.GetSigningMethod(signMethod),\n\t\t\tttl:        duration,\n\t\t\tkey:        key,\n\t\t}\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn tokenGenerator, nil\n}\n\nfunc (t *TokenGenerator) GenerateToken(ctx context.Context, username string, password string) (string, error) {\n\ttk := jwt.NewWithClaims(t.signMethod,\n\t\tjwt.MapClaims{\n\t\t\t\"username\": username,\n\t\t\t\"password\": password,\n\t\t\t\"exp\":      time.Now().Add(t.ttl).Unix(),\n\t\t})\n\n\ttoken, err := tk.SignedString(t.key)\n\tif err != nil {\n\t\tklog.Infof(\"failed to sign a JWT token for user %s, error is: %v\", username, err)\n\t\treturn \"\", err\n\t}\n\treturn token, err\n}\n"
  },
  {
    "path": "pkg/authentication/token/jwt/jwt.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage jwt\n\nimport (\n\t\"context\"\n\t\"crypto/rsa\"\n\t\"errors\"\n\t\"fmt\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/golang-jwt/jwt\"\n\t\"k8s.io/klog/v2\"\n\n\t\"tkestack.io/kstone/pkg/authentication\"\n)\n\nconst (\n\tProviderName = \"jwt\"\n)\n\nvar (\n\t// defaultTTL will be used when a 'ttl' is not specified\n\tdefaultTTL = 24 * time.Hour\n\tonce       sync.Once\n\tinstance   *TokenAuthenticator\n)\n\ntype TokenAuthenticator struct {\n\tsignMethod jwt.SigningMethod\n\tkey        interface{}\n\tttl        time.Duration\n}\n\ntype authInfo struct {\n\tusername string\n\tpassword string\n}\n\nfunc init() {\n\tauthentication.RegisterTokenFactory(ProviderName,\n\t\tfunc(ctx *authentication.TokenContext) (authentication.Token, error) {\n\t\t\treturn initTokenInstance(ctx)\n\t\t},\n\t)\n}\n\nfunc initTokenInstance(ctx *authentication.TokenContext) (*TokenAuthenticator, error) {\n\tvar err error\n\tonce.Do(func() {\n\t\tvar duration time.Duration\n\t\tvar key *rsa.PrivateKey\n\t\tif ctx.TTL == \"\" {\n\t\t\tduration = defaultTTL\n\t\t} else {\n\t\t\tduration, err = time.ParseDuration(ctx.TTL)\n\t\t}\n\n\t\tkey, err = jwt.ParseRSAPrivateKeyFromPEM([]byte(ctx.PrivateKey))\n\t\tinstance = &TokenAuthenticator{\n\t\t\tsignMethod: jwt.GetSigningMethod(ctx.SignMethod),\n\t\t\tttl:        duration,\n\t\t\tkey:        key,\n\t\t}\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn instance, nil\n}\n\nfunc (a *TokenAuthenticator) AuthenticateToken(ctx context.Context, token string) (*authentication.Response, bool, error) {\n\tinfo, err := a.info(token)\n\tif err != nil {\n\t\treturn authentication.UnauthenticatedResponse(), false, err\n\t}\n\n\tstore := authentication.GetDefaultStoreInstance()\n\tuser, err := store.UserGet(info.username)\n\tif err != nil {\n\t\tklog.Errorf(\"get user error: %v\", err)\n\t\treturn authentication.UnauthenticatedResponse(), false, errors.New(authentication.DataUnauthorized)\n\t}\n\tif info.username != user.Name || info.password != user.HashedPassword {\n\t\treturn authentication.UnauthenticatedResponse(), false, fmt.Errorf(\"incorrect username or password\")\n\t}\n\n\treturn authentication.SuccessResponse(info.username, authentication.DataSuccess), true, nil\n}\n\nfunc (a *TokenAuthenticator) info(token string) (*authInfo, error) {\n\tparsed, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {\n\t\tif token.Method.Alg() != a.signMethod.Alg() {\n\t\t\treturn nil, errors.New(\"invalid signing method\")\n\t\t}\n\t\tswitch k := a.key.(type) {\n\t\tcase *rsa.PrivateKey:\n\t\t\treturn &k.PublicKey, nil\n\t\tdefault:\n\t\t\treturn nil, errors.New(\"invalid private key\")\n\t\t}\n\t})\n\n\tif err != nil {\n\t\tklog.Errorf(\"failed to parse a JWT token: %s, error: %v\", token, err)\n\t\treturn nil, err\n\t}\n\n\tclaims, ok := parsed.Claims.(jwt.MapClaims)\n\tif !parsed.Valid || !ok || claims[\"username\"] == nil || claims[\"password\"] == nil {\n\t\tklog.Errorf(\"invalid JWT token: %s\", token)\n\t\treturn nil, fmt.Errorf(\"invalid JWT token: %s\", token)\n\t}\n\treturn &authInfo{\n\t\tusername: claims[\"username\"].(string),\n\t\tpassword: claims[\"password\"].(string),\n\t}, err\n}\n\nfunc GenerateToken(username, hashedPassword string) (string, error) {\n\tkey, err := authentication.GetPrivateKey()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tt, err := NewTokenGenerator(\"\", key, authentication.SignMethodRS256)\n\tif err != nil {\n\t\tklog.Errorf(\"new token generator error: %v\", err)\n\t\treturn \"\", err\n\t}\n\n\treturn t.GenerateToken(context.TODO(), username, hashedPassword)\n}\n"
  },
  {
    "path": "pkg/backup/backup.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage backup\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\n\tbackupapiv2 \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\tapiYaml \"k8s.io/apimachinery/pkg/runtime/serializer/yaml\"\n\t\"k8s.io/client-go/dynamic\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/klog/v2\"\n\t\"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil\"\n\t\"sigs.k8s.io/yaml\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/controllers/util\"\n\t\"tkestack.io/kstone/pkg/etcd\"\n\tplatformscheme \"tkestack.io/kstone/pkg/generated/clientset/versioned/scheme\"\n)\n\ntype Config struct {\n\tStorageType              backupapiv2.BackupStorageType `json:\"storageType\"`\n\tStoragePolicy            *backupapiv2.BackupPolicy     `json:\"backupPolicy,omitempty\"`\n\tbackupapiv2.BackupSource `json:\",inline\"`\n}\n\ntype Server struct {\n\tcli     dynamic.Interface\n\tkubeCli kubernetes.Interface\n}\n\nconst (\n\tAnnoBackupConfig = \"backup\"\n\tBackupGroup      = \"etcd.database.coreos.com\"\n\tBackupVersion    = \"v1beta2\"\n\tBackupResource   = \"etcdbackups\"\n\tBackupKind       = \"EtcdBackup\"\n)\n\nvar (\n\tBackupSchema = schema.GroupVersionResource{\n\t\tGroup:    BackupGroup,\n\t\tVersion:  BackupVersion,\n\t\tResource: BackupResource,\n\t}\n\tbackupSchemaKind = schema.GroupVersionKind{\n\t\tGroup:   BackupGroup,\n\t\tVersion: BackupVersion,\n\t\tKind:    BackupKind,\n\t}\n)\n\n// NewBackupServer generates backup provider\nfunc NewBackupServer(clientBuilder util.ClientBuilder) (*Server, error) {\n\tcli, err := dynamic.NewForConfig(clientBuilder.ConfigOrDie())\n\tif err != nil {\n\t\tklog.Errorf(\"failed to init backup client,err is %v\", err)\n\t\treturn nil, err\n\t}\n\n\treturn &Server{\n\t\tcli:     cli,\n\t\tkubeCli: clientBuilder.ClientOrDie(),\n\t}, err\n}\n\n// encodeBackupObj encodes backup object\nfunc (bak *Server) encodeBackupObj(obj *unstructured.Unstructured) (*backupapiv2.EtcdBackup, error) {\n\tdata, err := obj.MarshalJSON()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar newBackup backupapiv2.EtcdBackup\n\tif err := json.Unmarshal(data, &newBackup); err != nil {\n\t\treturn nil, err\n\t}\n\treturn &newBackup, nil\n}\n\n// decodeBackupObj decodes backup object\nfunc (bak *Server) decodeBackupObj(backup *backupapiv2.EtcdBackup) (*unstructured.Unstructured, error) {\n\tdata, err := json.Marshal(backup)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"transfer json failed, err is %v\", err)\n\t}\n\tyml, er := yaml.JSONToYAML(data)\n\tif er != nil {\n\t\treturn nil, fmt.Errorf(\"transfer yaml failed, err is %v\", err)\n\t}\n\tdecoder := apiYaml.NewDecodingSerializer(unstructured.UnstructuredJSONScheme)\n\tobj := &unstructured.Unstructured{}\n\tif _, _, err := decoder.Decode(yml, &backupSchemaKind, obj); err != nil {\n\t\treturn nil, err\n\t}\n\treturn obj, nil\n}\n\n// CreateEtcdBackupByYaml creates etcd backup by yaml\nfunc (bak *Server) CreateEtcdBackupByYaml(backup *backupapiv2.EtcdBackup) error {\n\tobj, err := bak.decodeBackupObj(backup)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"decode backup failed, err is %v\", err)\n\t}\n\t_, err = bak.cli.Resource(BackupSchema).\n\t\tNamespace(backup.Namespace).\n\t\tCreate(context.TODO(), obj, metav1.CreateOptions{})\n\tif err != nil && !apierrors.IsAlreadyExists(err) {\n\t\treturn fmt.Errorf(\"create etcdbackup failed, err is %v\", err)\n\t}\n\treturn nil\n}\n\n// GetEtcdBackup gets etcd backup\nfunc (bak *Server) GetEtcdBackup(name, namespace string) (*backupapiv2.EtcdBackup, error) {\n\tobj, err := bak.cli.Resource(BackupSchema).Namespace(namespace).Get(context.TODO(), name, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn bak.encodeBackupObj(obj)\n}\n\n// DeleteEtcdBackup deletes etcd backup\nfunc (bak *Server) DeleteEtcdBackup(name, namespace string) error {\n\terr := bak.cli.Resource(BackupSchema).Namespace(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{})\n\tif err != nil && !apierrors.IsNotFound(err) {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// UpdateEtcdBackup updates etcd backup\nfunc (bak *Server) UpdateEtcdBackup(backup *backupapiv2.EtcdBackup) (*backupapiv2.EtcdBackup, error) {\n\tobj, err := bak.decodeBackupObj(backup)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"decode backup failed, err is %v\", err)\n\t}\n\n\toldObj, err := bak.cli.Resource(BackupSchema).\n\t\tNamespace(backup.Namespace).\n\t\tGet(context.TODO(), backup.GetName(), metav1.GetOptions{})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tobj.SetResourceVersion(oldObj.GetResourceVersion())\n\tobj, err = bak.cli.Resource(BackupSchema).\n\t\tNamespace(backup.Namespace).\n\t\tUpdate(context.TODO(), obj, metav1.UpdateOptions{})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn bak.encodeBackupObj(obj)\n}\n\n// parseBackupConfig parses backup config\nfunc (bak *Server) parseBackupConfig(cluster *kstonev1alpha2.EtcdCluster) (*Config, string, error) {\n\tannotations := cluster.ObjectMeta.Annotations\n\tif annotations == nil {\n\t\tannotations = make(map[string]string)\n\t}\n\n\tstrCfg, found := annotations[AnnoBackupConfig]\n\tif !found {\n\t\tklog.Errorf(\n\t\t\t\"not found backup config, annotation key %s not exists, namespace is %s, name is %s\",\n\t\t\tAnnoBackupConfig,\n\t\t\tcluster.Namespace,\n\t\t\tcluster.Name,\n\t\t)\n\t\treturn nil, \"\", errors.New(\"backup config not found\")\n\t}\n\n\tsecretName := \"\"\n\tsecretName, found = annotations[util.ClusterTLSSecretName]\n\tif strings.Contains(secretName, \"/\") {\n\t\tsecretName = strings.Split(secretName, \"/\")[1]\n\t}\n\n\t// If enables tls and secretName cannot be empty\n\tauthConfig := cluster.Spec.AuthConfig\n\tif authConfig.EnableTLS && !found {\n\t\tklog.Errorf(\"tlsEnabled cluster no secret, namespace is %s, name is %s\", cluster.Namespace, cluster.Name)\n\t\treturn nil, \"\", errors.New(\"secretName not found\")\n\t}\n\n\tcfg := &Config{}\n\terr := json.Unmarshal([]byte(strCfg), cfg)\n\tif err != nil {\n\t\tklog.Errorf(\n\t\t\t\"failed to parse backup config, namespace is %s, name is %s, err is %v\",\n\t\t\tcluster.Namespace,\n\t\t\tcluster.Name,\n\t\t\terr,\n\t\t)\n\t\treturn nil, \"\", errors.New(\"backup config parse failed\")\n\t}\n\treturn cfg, secretName, nil\n}\n\n// initEtcdBackup generates etcd backup\nfunc (bak *Server) initEtcdBackup(cluster *kstonev1alpha2.EtcdCluster) (*backupapiv2.EtcdBackup, error) {\n\tbackupCfg, secretName, err := bak.parseBackupConfig(cluster)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tbackup := &backupapiv2.EtcdBackup{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tKind:       BackupKind,\n\t\t\tAPIVersion: BackupGroup + \"/\" + BackupVersion,\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      cluster.Name,\n\t\t\tNamespace: cluster.Namespace,\n\t\t\tLabels:    cluster.ObjectMeta.Labels,\n\t\t},\n\t\tSpec: backupapiv2.BackupSpec{\n\t\t\tEtcdEndpoints: []string{cluster.Status.ServiceName},\n\t\t\tStorageType:   backupCfg.StorageType,\n\t\t\t//ClientTLSSecret: secretName,\n\t\t\t//InsecureSkipVerify: true,\n\t\t\tBackupPolicy: backupCfg.StoragePolicy,\n\t\t\tBackupSource: backupCfg.BackupSource,\n\t\t\t//BasicAuthSecret: secretName,\n\t\t},\n\t}\n\t//load secretConfig\n\tclientConfigGetter := etcd.NewClientConfigSecretGetter(util.NewSimpleClientBuilder(\"\"))\n\tklog.Infof(\"secretName: %s\", secretName)\n\tpath := fmt.Sprintf(\"%s/%s\", cluster.Namespace, cluster.Name)\n\tconfig, err := clientConfigGetter.New(path, secretName)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get cluster, namespace is %s, name is %s, err is %v\", cluster.Namespace, cluster.Name, err)\n\t\treturn nil, err\n\t}\n\tif config.Username != \"\" {\n\t\tbackup.Spec.BasicAuthSecret = secretName\n\t}\n\tif config.CaCert != \"\" {\n\t\tbackup.Spec.ClientTLSSecret = secretName\n\t\tbackup.Spec.InsecureSkipVerify = true\n\t}\n\n\treturn backup, nil\n}\n\n// Equal checks whether the backup resource needs to be updated\nfunc (bak *Server) Equal(cluster *kstonev1alpha2.EtcdCluster) bool {\n\tnamespace, name := cluster.Namespace, cluster.Name\n\n\tbackup, err := bak.GetEtcdBackup(name, namespace)\n\tif err != nil {\n\t\treturn apierrors.IsNotFound(err)\n\t}\n\n\tnewBackup, err := bak.initEtcdBackup(cluster)\n\tif err != nil {\n\t\tklog.Errorf(\"init etcd backup failed, namespace is %s, name is %s, err is %v\", namespace, name, err)\n\t\treturn false\n\t}\n\n\treturn !reflect.DeepEqual(backup, &newBackup)\n}\n\n// CheckEqualIfDisabled checks whether the backup resource is not found if it is disabled\nfunc (bak *Server) CheckEqualIfDisabled(cluster *kstonev1alpha2.EtcdCluster) bool {\n\tif _, err := bak.GetEtcdBackup(cluster.Name, cluster.Namespace); apierrors.IsNotFound(err) {\n\t\treturn true\n\t}\n\treturn false\n}\n\n// CheckEqualIfEnabled checks whether the backup resource is equal if it is enabled\nfunc (bak *Server) CheckEqualIfEnabled(cluster *kstonev1alpha2.EtcdCluster) bool {\n\tnamespace, name := cluster.Namespace, cluster.Name\n\tbackup, err := bak.GetEtcdBackup(name, namespace)\n\tif err != nil && apierrors.IsNotFound(err) {\n\t\treturn false\n\t}\n\n\tnewBackup, err := bak.initEtcdBackup(cluster)\n\tif err != nil {\n\t\tklog.Errorf(\"init etcd backup failed, namespace is %s, name is %s, err is %v\", namespace, name, err)\n\t\treturn false\n\t}\n\n\treturn reflect.DeepEqual(backup, &newBackup)\n}\n\n// CleanBackup cleans the etcdbackup if it is disabled.\nfunc (bak *Server) CleanBackup(cluster *kstonev1alpha2.EtcdCluster) error {\n\terr := bak.DeleteEtcdBackup(cluster.Name, cluster.Namespace)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to delete etcd backup, namespace is %s, name is %s, err is %v\", cluster.Namespace, cluster.Name, err)\n\t}\n\treturn err\n}\n\n// SyncBackup synchronizes the etcdbackup if it is enabled.\nfunc (bak *Server) SyncBackup(cluster *kstonev1alpha2.EtcdCluster) error {\n\tnamespace, name := cluster.Namespace, cluster.Name\n\tnewBackup, err := bak.initEtcdBackup(cluster)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to init etcd backup, namespace is %s, name is %s, err is %v\", namespace, name, err)\n\t\treturn err\n\t}\n\terr = controllerutil.SetOwnerReference(cluster, newBackup, platformscheme.Scheme)\n\tif err != nil {\n\t\tklog.Errorf(\"set reference failed, err is %s, backup is %s\", newBackup.Name)\n\t\treturn err\n\t}\n\t_, err = bak.GetEtcdBackup(name, namespace)\n\tif err != nil && !apierrors.IsNotFound(err) {\n\t\tklog.Errorf(\"failed to get etcd backup, namespace is %s, name is %s, err is %v\", namespace, name, err)\n\t\treturn err\n\t}\n\tif apierrors.IsNotFound(err) {\n\t\terr = bak.CreateEtcdBackupByYaml(newBackup)\n\t\tif err != nil {\n\t\t\tklog.Errorf(\"failed to create etcd backup, namespace is %s, name is %s, err is %v\", namespace, name, err)\n\t\t}\n\t\treturn err\n\t}\n\t_, err = bak.UpdateEtcdBackup(newBackup)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to update etcd backup, namespace is %s, name is %s, err is %v\", namespace, name, err)\n\t}\n\treturn err\n}\n"
  },
  {
    "path": "pkg/backup/plugins.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage backup\n\nimport (\n\t\"errors\"\n\t\"sync\"\n\n\tklog \"k8s.io/klog/v2\"\n)\n\nvar (\n\tmutex     sync.Mutex\n\tProviders = make(map[string]Factory)\n)\n\ntype Factory func(cfg *StorageConfig) (Storage, error)\n\n// RegisterBackupStorageFactory registers the specified backup storage provider\nfunc RegisterBackupStorageFactory(name string, factory Factory) {\n\tmutex.Lock()\n\tdefer mutex.Unlock()\n\n\tif _, found := Providers[name]; found {\n\t\tklog.V(2).Infof(\"backup storage provider:%s was registered twice\", name)\n\t}\n\n\tklog.V(2).Infof(\"register backup storage provider:%s\", name)\n\tProviders[name] = factory\n}\n\n// GetBackupStorageProvider gets the specified backup storage provider\nfunc GetBackupStorageProvider(name string, config *StorageConfig) (Storage, error) {\n\tmutex.Lock()\n\tdefer mutex.Unlock()\n\tf, found := Providers[name]\n\n\tklog.V(1).Infof(\"get provider name %s,status:%t\", name, found)\n\tif !found {\n\t\treturn nil, errors.New(\"fatal error,backup storage provider not found\")\n\t}\n\treturn f(config)\n}\n"
  },
  {
    "path": "pkg/backup/providers/cos/cos.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage cos\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\ttencentCOS \"github.com/tencentyun/cos-go-sdk-v5\"\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/klog/v2\"\n\n\t\"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/backup\"\n\tfeatureutil \"tkestack.io/kstone/pkg/featureprovider/util\"\n)\n\nconst (\n\tProviderName = string(v1beta2.BackupStorageTypeCOS)\n)\n\ntype StorageCOS struct {\n\tkubeCli kubernetes.Interface\n}\n\nfunc init() {\n\tbackup.RegisterBackupStorageFactory(ProviderName, func(config *backup.StorageConfig) (backup.Storage, error) {\n\t\treturn NewCOSBackupProvider(config), nil\n\t})\n}\n\nfunc NewCOSBackupProvider(config *backup.StorageConfig) backup.Storage {\n\treturn &StorageCOS{\n\t\tkubeCli: config.KubeCli,\n\t}\n}\n\nfunc (c *StorageCOS) List(cluster *v1alpha2.EtcdCluster) (interface{}, error) {\n\t// get backup config\n\tbackupConfig, err := backup.GetBackupConfig(cluster)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get backup config,cluster %s,err is %v\", cluster.Name, err)\n\t\treturn nil, err\n\t}\n\tklog.V(3).Infof(\"backup config is %v\", backupConfig)\n\n\tsecret, err := c.kubeCli.CoreV1().Secrets(cluster.Namespace).Get(context.TODO(), backupConfig.COS.COSSecret, v1.GetOptions{})\n\tif err != nil {\n\t\tklog.Errorf(err.Error())\n\t\treturn nil, err\n\t}\n\n\tsecretID := string(secret.Data[\"secret-id\"])\n\tsecretKey := string(secret.Data[\"secret-key\"])\n\n\tklog.Info(secretID)\n\tklog.Info(secretKey)\n\n\tcosPath := backupConfig.COS.Path\n\tif !strings.Contains(cosPath, \"https://\") {\n\t\tcosPath = fmt.Sprintf(\"https://%s\", cosPath)\n\t}\n\n\tu, _ := url.Parse(cosPath)\n\tb := &tencentCOS.BaseURL{BucketURL: u}\n\tclient := tencentCOS.NewClient(b, &http.Client{\n\t\tTransport: &tencentCOS.AuthorizationTransport{\n\t\t\tSecretID:  secretID,\n\t\t\tSecretKey: secretKey,\n\t\t},\n\t})\n\n\tresult, _, err := client.Bucket.Get(context.Background(), &tencentCOS.BucketGetOptions{\n\t\tPrefix: strings.TrimLeft(b.BucketURL.Path, \"/\"),\n\t})\n\tif err != nil {\n\t\tklog.Errorf(err.Error())\n\t\treturn nil, err\n\t}\n\n\treturn result.Contents, nil\n}\n\nfunc (c *StorageCOS) Stat(objects interface{}) (int, error) {\n\tcosObjects, ok := objects.([]tencentCOS.Object)\n\tif !ok {\n\t\treturn 0, errors.New(\"can not decode objects to COS objects\")\n\t}\n\tbackupFiles := 0\n\tfor i := len(cosObjects) - 1; i >= 0; i-- {\n\t\tlastModifiedTime, err := time.Parse(\"2006-01-02T15:04:05Z\", cosObjects[i].LastModified)\n\t\tif err != nil {\n\t\t\treturn 0, errors.New(\"can not parse COS time\")\n\t\t}\n\t\ttimeElapse := int64(time.Since(lastModifiedTime).Seconds())\n\t\tif timeElapse > featureutil.OneDaySeconds {\n\t\t\tbreak\n\t\t}\n\t\tbackupFiles++\n\t}\n\treturn backupFiles, nil\n}\n"
  },
  {
    "path": "pkg/backup/providers/providers.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage providers\n\nimport (\n\t// import cos provider\n\t_ \"tkestack.io/kstone/pkg/backup/providers/cos\"\n\t// import s3 provider\n\t_ \"tkestack.io/kstone/pkg/backup/providers/s3\"\n)\n"
  },
  {
    "path": "pkg/backup/providers/s3/clientwrapper.go",
    "content": "package s3\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"path\"\n\n\t\"github.com/aws/aws-sdk-go/aws/session\"\n\tawsS3 \"github.com/aws/aws-sdk-go/service/s3\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n)\n\nconst (\n\ttmpdir = \"/tmp\"\n)\n\n// ClientS3Wrapper is a wrapper for S3 client that provides cleanup functionality.\ntype ClientS3Wrapper struct {\n\tS3        *awsS3.S3\n\tconfigDir string\n}\n\n// NewClientFromSecret returns a S3 client based on given k8s secret containing aws credentials.\nfunc NewClientFromSecret(kubecli kubernetes.Interface, namespace, endpoint, awsSecret string, forcePathStyle bool) (w *ClientS3Wrapper, err error) {\n\tdefer func() {\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"new S3 client failed: %v\", err)\n\t\t}\n\t}()\n\tw = &ClientS3Wrapper{}\n\tw.configDir, err = ioutil.TempDir(tmpdir, \"\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create aws config dir: (%v)\", err)\n\t}\n\tso, err := setupAWSConfig(kubecli, namespace, awsSecret, endpoint, w.configDir, forcePathStyle)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to setup aws config: (%v)\", err)\n\t}\n\tsess, err := session.NewSessionWithOptions(*so)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"new AWS session failed: %v\", err)\n\t}\n\tw.S3 = awsS3.New(sess)\n\treturn w, nil\n}\n\n// Close cleans up all intermediate resources for creating S3 client.\nfunc (w *ClientS3Wrapper) Close() {\n\tos.RemoveAll(w.configDir)\n}\n\n// setupAWSConfig setup local AWS config/credential files from Kubernetes aws secret.\nfunc setupAWSConfig(kubecli kubernetes.Interface, ns, secret, endpoint, configDir string, forcePathStyle bool) (*session.Options, error) {\n\toptions := &session.Options{}\n\toptions.SharedConfigState = session.SharedConfigEnable\n\n\t// empty string defaults to aws\n\toptions.Config.Endpoint = &endpoint\n\n\toptions.Config.S3ForcePathStyle = &forcePathStyle\n\n\tse, err := kubecli.CoreV1().Secrets(ns).Get(context.TODO(), secret, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"setup AWS config failed: get k8s secret failed: %v\", err)\n\t}\n\n\tcreds := se.Data[\"credentials\"]\n\tif len(creds) != 0 {\n\t\tcredsFile := path.Join(configDir, \"credentials\")\n\t\terr = ioutil.WriteFile(credsFile, creds, 0600)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"setup AWS config failed: write credentials file failed: %v\", err)\n\t\t}\n\t\toptions.SharedConfigFiles = append(options.SharedConfigFiles, credsFile)\n\t}\n\n\tconfig := se.Data[\"config\"]\n\tif len(config) != 0 {\n\t\tconfigFile := path.Join(configDir, \"config\")\n\t\terr = ioutil.WriteFile(configFile, config, 0600)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"setup AWS config failed: write config file failed: %v\", err)\n\t\t}\n\t\toptions.SharedConfigFiles = append(options.SharedConfigFiles, configFile)\n\t}\n\n\treturn options, nil\n}\n"
  },
  {
    "path": "pkg/backup/providers/s3/s3.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage s3\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"strings\"\n\t\"time\"\n\n\tawsS3 \"github.com/aws/aws-sdk-go/service/s3\"\n\t\"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/klog/v2\"\n\n\t\"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/backup\"\n\tfeatureutil \"tkestack.io/kstone/pkg/featureprovider/util\"\n)\n\nconst (\n\tProviderName = string(v1beta2.BackupStorageTypeS3)\n)\n\ntype StorageS3 struct {\n\tkubeCli kubernetes.Interface\n}\n\nfunc init() {\n\tbackup.RegisterBackupStorageFactory(ProviderName, func(config *backup.StorageConfig) (backup.Storage, error) {\n\t\treturn NewS3BackupProvider(config), nil\n\t})\n}\n\nfunc NewS3BackupProvider(config *backup.StorageConfig) backup.Storage {\n\treturn &StorageS3{\n\t\tkubeCli: config.KubeCli,\n\t}\n}\n\nfunc (c *StorageS3) List(cluster *v1alpha2.EtcdCluster) (interface{}, error) {\n\t// get backup config\n\tbackupConfig, err := backup.GetBackupConfig(cluster)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get backup config,cluster %s,err is %v\", cluster.Name, err)\n\t\treturn nil, err\n\t}\n\tklog.V(3).Infof(\"backup config is %v\", backupConfig)\n\n\tsecret, err := c.kubeCli.CoreV1().Secrets(cluster.Namespace).Get(context.TODO(), backupConfig.S3.AWSSecret, v1.GetOptions{})\n\tif err != nil {\n\t\tklog.Errorf(err.Error())\n\t\treturn nil, err\n\t}\n\n\tbucket := strings.Split(backupConfig.S3.Path, \"/\")\n\tif len(bucket) < 1 {\n\t\terr = fmt.Errorf(\"s3.path=%s, not valid, bucket not set\", backupConfig.S3.Path)\n\t\tklog.Errorf(err.Error())\n\t\treturn nil, err\n\t}\n\n\tcli, err := NewClientFromSecret(c.kubeCli, cluster.Namespace, backupConfig.S3.Endpoint, backupConfig.S3.AWSSecret, backupConfig.S3.ForcePathStyle)\n\tif err != nil {\n\t\tklog.Errorf(err.Error())\n\t\treturn nil, err\n\t}\n\tdefer cli.Close()\n\n\tklog.Info(fmt.Sprintf(\"secret name: %s, data: %v\", secret.Name, secret.Data))\n\n\ti := 0\n\tvar resultObjs []*awsS3.Object\n\terr = cli.S3.ListObjectsPages(&awsS3.ListObjectsInput{\n\t\tBucket: &bucket[0],\n\t}, func(p *awsS3.ListObjectsOutput, last bool) (shouldContinue bool) {\n\t\ti++\n\t\tresultObjs = append(resultObjs, p.Contents...)\n\t\treturn true\n\t})\n\tif err != nil {\n\t\tklog.Errorf(\"failed to list objects, error: %s\", err.Error())\n\t\treturn nil, err\n\t}\n\tklog.Infof(\"Total Page %d\", i)\n\n\treturn resultObjs, nil\n}\n\nfunc (c *StorageS3) Stat(objects interface{}) (int, error) {\n\ts3Objects, ok := objects.([]*awsS3.Object)\n\tif !ok {\n\t\treturn 0, errors.New(\"can not decode objects to S3 objects\")\n\t}\n\tbackupFiles := 0\n\tfor i := len(s3Objects) - 1; i >= 0; i-- {\n\t\tlastModifiedTime := *s3Objects[i].LastModified\n\t\ttimeElapse := int64(time.Since(lastModifiedTime).Seconds())\n\t\tif timeElapse > featureutil.OneDaySeconds {\n\t\t\tbreak\n\t\t}\n\t\tbackupFiles++\n\t}\n\treturn backupFiles, nil\n}\n"
  },
  {
    "path": "pkg/backup/storage.go",
    "content": "package backup\n\nimport (\n\t\"k8s.io/client-go/kubernetes\"\n\n\t\"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n)\n\n// Storage is an abstract, pluggable interface for etcd backup storage.\ntype Storage interface {\n\t// List gets all backup files from object storage.\n\tList(cluster *v1alpha2.EtcdCluster) (interface{}, error)\n\n\t// Stat counts the number of backup file in the last day.\n\tStat(objects interface{}) (int, error)\n}\n\ntype StorageConfig struct {\n\tKubeCli kubernetes.Interface\n}\n"
  },
  {
    "path": "pkg/backup/util.go",
    "content": "package backup\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\n\tklog \"k8s.io/klog/v2\"\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n)\n\nfunc GetBackupConfig(cluster *kstonev1alpha2.EtcdCluster) (*Config, error) {\n\tvar err error\n\tcfg, found := cluster.Annotations[AnnoBackupConfig]\n\tif !found {\n\t\terr = fmt.Errorf(\n\t\t\t\"backup config not found, annotation key %s not exists, namespace is %s, name is %s\",\n\t\t\tAnnoBackupConfig,\n\t\t\tcluster.Namespace,\n\t\t\tcluster.Name,\n\t\t)\n\t\tklog.Errorf(\"failed to get backup config,cluster %s,err is %v\", cluster.Name, err)\n\t\treturn nil, err\n\t}\n\n\tbackupConfig := &Config{}\n\terr = json.Unmarshal([]byte(cfg), backupConfig)\n\tif err != nil {\n\t\tklog.Errorf(err.Error())\n\t\treturn nil, err\n\t}\n\treturn backupConfig, nil\n}\n"
  },
  {
    "path": "pkg/clusterprovider/etcdcluster.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage clusterprovider\n\nimport (\n\t\"k8s.io/client-go/dynamic\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/controllers/util\"\n\t\"tkestack.io/kstone/pkg/etcd\"\n)\n\n// Cluster is an abstract, pluggable interface for etcd clusters.\ntype Cluster interface {\n\n\t// BeforeCreate does some things before creating the cluster\n\tBeforeCreate(cluster *kstonev1alpha2.EtcdCluster) error\n\t// Create creates the cluster\n\tCreate(cluster *kstonev1alpha2.EtcdCluster) error\n\t// AfterCreate does some things after creating the cluster\n\tAfterCreate(cluster *kstonev1alpha2.EtcdCluster) error\n\n\t// BeforeUpdate does some things before updating the cluster\n\tBeforeUpdate(cluster *kstonev1alpha2.EtcdCluster) error\n\t// Update updates the cluster\n\tUpdate(cluster *kstonev1alpha2.EtcdCluster) error\n\t// AfterUpdate does some things after updating the cluster\n\tAfterUpdate(cluster *kstonev1alpha2.EtcdCluster) error\n\n\t// BeforeDelete does some things before deleting the cluster\n\tBeforeDelete(cluster *kstonev1alpha2.EtcdCluster) error\n\t// Delete deletes the cluster\n\tDelete(cluster *kstonev1alpha2.EtcdCluster) error\n\t// AfterDelete does some things after deleting the cluster\n\tAfterDelete(cluster *kstonev1alpha2.EtcdCluster) error\n\n\t// Equal checks whether the cluster needs to be updated\n\tEqual(cluster *kstonev1alpha2.EtcdCluster) (bool, error)\n\n\t// Status gets the cluster status\n\tStatus(config *etcd.ClientConfig, cluster *kstonev1alpha2.EtcdCluster) (kstonev1alpha2.EtcdClusterStatus, error)\n}\n\ntype ClusterContext struct {\n\tClientbuilder util.ClientBuilder\n\tClient        dynamic.Interface\n}\n"
  },
  {
    "path": "pkg/clusterprovider/helper.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage clusterprovider\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\t\"k8s.io/klog/v2\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/etcd\"\n\tversionClient \"tkestack.io/kstone/pkg/etcd/client\"\n\t_ \"tkestack.io/kstone/pkg/etcd/client/versions\" // import etcd client including v2 and v3\n)\n\ntype EtcdAlarm struct {\n\tMemberID  uint64\n\tAlarmType string\n}\n\n// GetStorageMemberEndpoints get member of cluster status\nfunc GetStorageMemberEndpoints(cluster *kstonev1alpha2.EtcdCluster) []string {\n\tmembers := cluster.Status.Members\n\tendpoints := make([]string, 0)\n\tif len(members) == 0 {\n\t\treturn endpoints\n\t}\n\n\tfor _, m := range members {\n\t\tendpoints = append(endpoints, m.ExtensionClientUrl)\n\t}\n\treturn endpoints\n}\n\n// populateExtensionCientURLMap generate extensionClientURLs map\nfunc populateExtensionCientURLMap(extensionClientURLs string) (map[string]string, error) {\n\turlMap := make(map[string]string)\n\tif extensionClientURLs == \"\" {\n\t\treturn nil, nil\n\t}\n\titems := strings.Split(extensionClientURLs, \",\")\n\tfor i := 0; i < len(items); i++ {\n\t\teps := strings.Split(items[i], \"->\")\n\t\tif len(eps) == 2 {\n\t\t\turlMap[eps[0]] = eps[1]\n\t\t} else {\n\t\t\treturn urlMap, fmt.Errorf(\"invalid extensionClientURLs %s\", items[i])\n\t\t}\n\t}\n\treturn urlMap, nil\n}\n\n// GetRuntimeEtcdMembers get members of etcd\nfunc GetRuntimeEtcdMembers(\n\tstorageBackend string,\n\tendpoints []string,\n\textensionClientURLs string,\n\tconfig *etcd.ClientConfig) ([]kstonev1alpha2.MemberStatus, error) {\n\tetcdMembers := make([]kstonev1alpha2.MemberStatus, 0)\n\n\tconfig.Endpoints = endpoints\n\tversioned, err := versionClient.GetEtcdClientProvider(kstonev1alpha2.EtcdStorageBackend(storageBackend),\n\t\t&versionClient.VersionContext{Config: config})\n\tif err != nil {\n\t\tklog.Errorf(\"failed get etcd version, err is %v\", err)\n\t\treturn etcdMembers, err\n\t}\n\n\tdefer versioned.Close()\n\n\tmemberRsp, err := versioned.MemberList()\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get member list, endpoints is %s,err is %v\", endpoints, err)\n\t\treturn etcdMembers, err\n\t}\n\n\textensionClientURLMap, err := populateExtensionCientURLMap(extensionClientURLs)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to populate extension clientURL,err is %v\", err)\n\t\treturn etcdMembers, err\n\t}\n\n\tfor _, m := range memberRsp {\n\t\t// parse url\n\t\tif m.ClientURLs == nil {\n\t\t\tcontinue\n\t\t}\n\t\titems := strings.Split(m.ClientURLs[0], \":\")\n\t\tendPoint := strings.TrimPrefix(items[1], \"//\")\n\n\t\textensionClientURL := m.ClientURLs[0]\n\t\tif extensionClientURLs != \"\" {\n\t\t\tvar ep string\n\t\t\tif strings.HasPrefix(m.ClientURLs[0], \"https://\") {\n\t\t\t\tep = strings.TrimPrefix(m.ClientURLs[0], \"https://\")\n\t\t\t\tif _, ok := extensionClientURLMap[ep]; ok {\n\t\t\t\t\textensionClientURL = \"https://\" + extensionClientURLMap[ep]\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tep = strings.TrimPrefix(m.ClientURLs[0], \"http://\")\n\t\t\t\tif _, ok := extensionClientURLMap[ep]; ok {\n\t\t\t\t\textensionClientURL = \"http://\" + extensionClientURLMap[ep]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// default info\n\t\tmemberVersion, memberStatus, memberRole := \"\", kstonev1alpha2.MemberPhaseUnStarted, kstonev1alpha2.EtcdMemberUnKnown\n\t\tvar errors []string\n\t\tstatusRsp, err := versioned.Status(extensionClientURL)\n\t\tif err == nil && statusRsp != nil {\n\t\t\tmemberStatus = kstonev1alpha2.MemberPhaseRunning\n\t\t\tmemberVersion = statusRsp.Version\n\t\t\tif statusRsp.IsLearner {\n\t\t\t\tmemberRole = kstonev1alpha2.EtcdMemberLearner\n\t\t\t} else if statusRsp.Leader == m.ID {\n\t\t\t\tmemberRole = kstonev1alpha2.EtcdMemberLeader\n\t\t\t} else {\n\t\t\t\tmemberRole = kstonev1alpha2.EtcdMemberFollower\n\t\t\t}\n\t\t} else {\n\t\t\tklog.Errorf(\"failed to get member %s status,err is %v\", extensionClientURL, err)\n\t\t\terrors = append(errors, err.Error())\n\t\t}\n\n\t\tetcdMembers = append(etcdMembers, kstonev1alpha2.MemberStatus{\n\t\t\tName:               m.Name,\n\t\t\tMemberId:           m.ID,\n\t\t\tClientUrl:          m.ClientURLs[0],\n\t\t\tExtensionClientUrl: extensionClientURL,\n\t\t\tRole:               memberRole,\n\t\t\tStatus:             memberStatus,\n\t\t\tEndpoint:           endPoint,\n\t\t\tPort:               items[2],\n\t\t\tVersion:            memberVersion,\n\t\t\tErrors:             errors,\n\t\t})\n\t}\n\n\treturn etcdMembers, nil\n}\n\n// GetEtcdClusterMemberStatus check healthy of cluster and member\nfunc GetEtcdClusterMemberStatus(\n\tmembers []kstonev1alpha2.MemberStatus,\n\tconfig *etcd.ClientConfig) ([]kstonev1alpha2.MemberStatus, kstonev1alpha2.EtcdClusterPhase) {\n\tclusterStatus := kstonev1alpha2.EtcdClusterRunning\n\tnewMembers := make([]kstonev1alpha2.MemberStatus, 0)\n\tfor _, m := range members {\n\t\thealthy, err := etcd.MemberHealthy(m.ExtensionClientUrl, config)\n\t\tif err != nil {\n\t\t\tm.Status = kstonev1alpha2.MemberPhaseUnKnown\n\t\t} else {\n\t\t\tif healthy {\n\t\t\t\tm.Status = kstonev1alpha2.MemberPhaseRunning\n\t\t\t} else {\n\t\t\t\tm.Status = kstonev1alpha2.MemberPhaseUnHealthy\n\t\t\t}\n\t\t}\n\n\t\tif m.Status != kstonev1alpha2.MemberPhaseRunning && clusterStatus == kstonev1alpha2.EtcdClusterRunning {\n\t\t\tclusterStatus = kstonev1alpha2.EtcdClusterUnhealthy\n\t\t}\n\n\t\tnewMembers = append(newMembers, m)\n\t}\n\n\treturn newMembers, clusterStatus\n}\n\n// GetEtcdAlarms get alarm list of etcd\nfunc GetEtcdAlarms(\n\tendpoints []string,\n\tconfig *etcd.ClientConfig) ([]EtcdAlarm, error) {\n\tetcdAlarms := make([]EtcdAlarm, 0)\n\n\tconfig.Endpoints = endpoints\n\n\tclient, err := etcd.NewClientv3(config)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get new etcd clientv3, err is %v \", err)\n\t\treturn etcdAlarms, err\n\t}\n\tdefer client.Close()\n\n\talarmRsp, err := etcd.AlarmList(client)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get alarm list, err is %v\", err)\n\t\treturn etcdAlarms, err\n\t}\n\n\tfor _, a := range alarmRsp.Alarms {\n\t\tetcdAlarms = append(etcdAlarms, EtcdAlarm{\n\t\t\tMemberID:  a.MemberID,\n\t\t\tAlarmType: a.Alarm.String(),\n\t\t})\n\t}\n\treturn etcdAlarms, nil\n}\n"
  },
  {
    "path": "pkg/clusterprovider/plugins.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage clusterprovider\n\nimport (\n\t\"errors\"\n\t\"sync\"\n\n\t\"k8s.io/klog/v2\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n)\n\ntype EtcdFactory func(cluster *ClusterContext) (Cluster, error)\n\nvar (\n\tmutex     sync.Mutex\n\tproviders = make(map[kstonev1alpha2.EtcdClusterType]EtcdFactory)\n)\n\n// RegisterEtcdClusterFactory registers the specified cluster provider\nfunc RegisterEtcdClusterFactory(name kstonev1alpha2.EtcdClusterType, factory EtcdFactory) {\n\tmutex.Lock()\n\tdefer mutex.Unlock()\n\n\tif _, found := providers[name]; found {\n\t\tklog.V(2).Infof(\"etcdcluster provider %s was registered twice\", name)\n\t}\n\n\tklog.V(2).Infof(\"register etcdCluster provider %s\", name)\n\tproviders[name] = factory\n}\n\n// GetEtcdClusterProvider gets the specified cluster provider\nfunc GetEtcdClusterProvider(\n\tname kstonev1alpha2.EtcdClusterType,\n\tctx *ClusterContext,\n) (Cluster, error) {\n\tmutex.Lock()\n\tdefer mutex.Unlock()\n\tf, found := providers[name]\n\n\tklog.V(1).Infof(\"get provider name %s,status:%t\", name, found)\n\tif !found {\n\t\treturn nil, errors.New(\"fatal error,etcd cluster provider not found\")\n\t}\n\treturn f(ctx)\n}\n"
  },
  {
    "path": "pkg/clusterprovider/providers/imported/cluster.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage imported\n\nimport (\n\t\"sync\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/clusterprovider\"\n\t\"tkestack.io/kstone/pkg/controllers/util\"\n\t\"tkestack.io/kstone/pkg/etcd\"\n)\n\nconst (\n\tAnnoImportedURI = \"importedAddr\"\n)\n\nvar (\n\tonce     sync.Once\n\tinstance *EtcdClusterImported\n)\n\n// EtcdClusterImported is the etcd cluster imported from kstone-dashboard\ntype EtcdClusterImported struct {\n\tname kstonev1alpha2.EtcdClusterType\n\tctx  *clusterprovider.ClusterContext\n}\n\n// init registers an imported etcd cluster provider\nfunc init() {\n\tclusterprovider.RegisterEtcdClusterFactory(\n\t\tkstonev1alpha2.EtcdClusterImported,\n\t\tfunc(ctx *clusterprovider.ClusterContext) (clusterprovider.Cluster, error) {\n\t\t\treturn initEtcdClusterImportedInstance(ctx)\n\t\t},\n\t)\n}\n\nfunc initEtcdClusterImportedInstance(ctx *clusterprovider.ClusterContext) (clusterprovider.Cluster, error) {\n\tonce.Do(func() {\n\t\tinstance = &EtcdClusterImported{\n\t\t\tname: kstonev1alpha2.EtcdClusterImported,\n\t\t\tctx: &clusterprovider.ClusterContext{\n\t\t\t\tClientbuilder: ctx.Clientbuilder,\n\t\t\t\tClient:        ctx.Clientbuilder.DynamicClientOrDie(),\n\t\t\t},\n\t\t}\n\t})\n\treturn instance, nil\n}\n\nfunc (c *EtcdClusterImported) BeforeCreate(cluster *kstonev1alpha2.EtcdCluster) error {\n\treturn nil\n}\n\nfunc (c *EtcdClusterImported) Create(cluster *kstonev1alpha2.EtcdCluster) error {\n\treturn nil\n}\n\nfunc (c *EtcdClusterImported) AfterCreate(cluster *kstonev1alpha2.EtcdCluster) error {\n\treturn nil\n}\n\nfunc (c *EtcdClusterImported) BeforeUpdate(cluster *kstonev1alpha2.EtcdCluster) error {\n\treturn nil\n}\n\nfunc (c *EtcdClusterImported) Update(cluster *kstonev1alpha2.EtcdCluster) error {\n\treturn nil\n}\n\nfunc (c *EtcdClusterImported) AfterUpdate(cluster *kstonev1alpha2.EtcdCluster) error {\n\treturn nil\n}\n\nfunc (c *EtcdClusterImported) BeforeDelete(cluster *kstonev1alpha2.EtcdCluster) error {\n\treturn nil\n}\n\nfunc (c *EtcdClusterImported) Delete(cluster *kstonev1alpha2.EtcdCluster) error {\n\treturn nil\n}\n\nfunc (c *EtcdClusterImported) AfterDelete(cluster *kstonev1alpha2.EtcdCluster) error {\n\treturn nil\n}\n\nfunc (c *EtcdClusterImported) Equal(cluster *kstonev1alpha2.EtcdCluster) (bool, error) {\n\treturn true, nil\n}\n\n// Status gets the imported etcd cluster status\nfunc (c *EtcdClusterImported) Status(config *etcd.ClientConfig, cluster *kstonev1alpha2.EtcdCluster) (kstonev1alpha2.EtcdClusterStatus, error) {\n\tstatus := cluster.Status\n\n\tannotations := cluster.ObjectMeta.Annotations\n\tif annotations == nil {\n\t\tannotations = make(map[string]string)\n\t}\n\n\tendpoints := clusterprovider.GetStorageMemberEndpoints(cluster)\n\n\tif len(endpoints) == 0 {\n\t\tif addr, found := annotations[AnnoImportedURI]; found {\n\t\t\tendpoints = append(endpoints, addr)\n\t\t\tstatus.ServiceName = addr\n\t\t} else {\n\t\t\tstatus.Phase = kstonev1alpha2.EtcdClusterUnknown\n\t\t\treturn status, nil\n\t\t}\n\t}\n\n\tmembers, err := clusterprovider.GetRuntimeEtcdMembers(\n\t\tcluster.Spec.StorageBackend,\n\t\tendpoints,\n\t\tcluster.Annotations[util.ClusterExtensionClientURL],\n\t\tconfig,\n\t)\n\tif err != nil && len(members) == 0 {\n\t\tstatus.Phase = kstonev1alpha2.EtcdClusterUnknown\n\t\treturn status, err\n\t}\n\n\tstatus.Members, status.Phase = clusterprovider.GetEtcdClusterMemberStatus(members, config)\n\treturn status, err\n}\n"
  },
  {
    "path": "pkg/clusterprovider/providers/kstone/kstone.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage kstone\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\n\tcorev1 \"k8s.io/api/core/v1\"\n\t\"k8s.io/apimachinery/pkg/api/errors\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\t\"k8s.io/klog/v2\"\n\t\"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/clusterprovider\"\n\t\"tkestack.io/kstone/pkg/controllers/util\"\n\t\"tkestack.io/kstone/pkg/etcd\"\n\tplatformscheme \"tkestack.io/kstone/pkg/generated/clientset/versioned/scheme\"\n)\n\nconst (\n\tproviderName              = kstonev1alpha2.EtcdClusterKstone\n\tAnnoImportedURI           = \"importedAddr\"\n\tdefaultEmptyResourceValue = \"0\"\n)\n\nvar (\n\tonce     sync.Once\n\tinstance *EtcdClusterKstone\n)\n\n// EtcdClusterKstone is responsible for synchronizing kstone.tkestack.io/etcdcluster to kstone-etcd-operator\ntype EtcdClusterKstone struct {\n\tname kstonev1alpha2.EtcdClusterType\n\tctx  *clusterprovider.ClusterContext\n}\n\n// init registers a kstone etcd cluster(generated by kstone-etcd-provider) provider\nfunc init() {\n\tclusterprovider.RegisterEtcdClusterFactory(\n\t\tproviderName,\n\t\tfunc(cluster *clusterprovider.ClusterContext) (clusterprovider.Cluster, error) {\n\t\t\treturn initEtcdClusterKstoneInstance(cluster)\n\t\t},\n\t)\n}\n\nfunc initEtcdClusterKstoneInstance(ctx *clusterprovider.ClusterContext) (clusterprovider.Cluster, error) {\n\tonce.Do(func() {\n\t\tinstance = &EtcdClusterKstone{\n\t\t\tname: kstonev1alpha2.EtcdClusterKstone,\n\t\t\tctx: &clusterprovider.ClusterContext{\n\t\t\t\tClientbuilder: ctx.Clientbuilder,\n\t\t\t\tClient:        ctx.Clientbuilder.DynamicClientOrDie(),\n\t\t\t},\n\t\t}\n\t})\n\treturn instance, nil\n}\n\nfunc (c *EtcdClusterKstone) BeforeCreate(cluster *kstonev1alpha2.EtcdCluster) error {\n\treturn nil\n}\n\n// Create creates an etcd cluster\nfunc (c *EtcdClusterKstone) Create(cluster *kstonev1alpha2.EtcdCluster) error {\n\tetcdRes := schema.GroupVersionResource{Group: \"etcd.tkestack.io\", Version: \"v1alpha1\", Resource: \"etcdclusters\"}\n\tetcdcluster := map[string]interface{}{\n\t\t\"apiVersion\": \"etcd.tkestack.io/v1alpha1\",\n\t\t\"kind\":       \"EtcdCluster\",\n\t\t\"metadata\": map[string]interface{}{\n\t\t\t\"name\":        cluster.Name,\n\t\t\t\"namespace\":   cluster.Namespace,\n\t\t\t\"annotations\": cluster.Annotations,\n\t\t},\n\t\t\"spec\": c.generateEtcdSpec(cluster),\n\t}\n\n\tetcdclusterRequest := &unstructured.Unstructured{\n\t\tObject: etcdcluster,\n\t}\n\n\terr := controllerutil.SetOwnerReference(cluster, etcdclusterRequest, platformscheme.Scheme)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t_, err = c.ctx.Client.Resource(etcdRes).\n\t\tNamespace(cluster.Namespace).\n\t\tCreate(context.TODO(), etcdclusterRequest, metav1.CreateOptions{})\n\tif err != nil && !errors.IsAlreadyExists(err) {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n// AfterCreate handles etcdcluster after created\nfunc (c *EtcdClusterKstone) AfterCreate(cluster *kstonev1alpha2.EtcdCluster) error {\n\tif cluster.Annotations[\"scheme\"] == \"https\" {\n\t\tcluster.Annotations[\"certName\"] = fmt.Sprintf(\"%s/%s-etcd-client-cert\", cluster.Namespace, cluster.Name)\n\t}\n\n\tcluster.Annotations[\"importedAddr\"] = fmt.Sprintf(\n\t\t\"%s://%s-etcd.%s.svc.cluster.local:2379\",\n\t\tcluster.Annotations[\"scheme\"],\n\t\tcluster.Name,\n\t\tcluster.Namespace,\n\t)\n\t// update extClientURL\n\textClientURL := \"\"\n\tfor i := 0; i < int(cluster.Spec.Size); i++ {\n\t\tkey := fmt.Sprintf(\"%s-etcd-%d:2379\", cluster.Name, i)\n\t\tvalue := fmt.Sprintf(\n\t\t\t\"%s-etcd-%d.%s-etcd-headless.%s.svc.cluster.local:2379\",\n\t\t\tcluster.Name,\n\t\t\ti,\n\t\t\tcluster.Name,\n\t\t\tcluster.Namespace,\n\t\t)\n\t\tif i < int(cluster.Spec.Size)-1 {\n\t\t\textClientURL += fmt.Sprintf(\"%s->%s,\", key, value)\n\t\t} else {\n\t\t\textClientURL += fmt.Sprintf(\"%s->%s\", key, value)\n\t\t}\n\t}\n\tcluster.Annotations[\"extClientURL\"] = extClientURL\n\treturn nil\n}\n\n// BeforeUpdate handles etcdcluster before updated\nfunc (c *EtcdClusterKstone) BeforeUpdate(cluster *kstonev1alpha2.EtcdCluster) error {\n\treturn nil\n}\n\n// Update updates cluster of kstone-etcd-operator\nfunc (c *EtcdClusterKstone) Update(cluster *kstonev1alpha2.EtcdCluster) error {\n\tetcdRes := schema.GroupVersionResource{Group: \"etcd.tkestack.io\", Version: \"v1alpha1\", Resource: \"etcdclusters\"}\n\tetcd, err := c.ctx.Client.Resource(etcdRes).\n\t\tNamespace(cluster.Namespace).\n\t\tGet(context.TODO(), cluster.Name, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = c.updateEtcdSpec(etcd, cluster)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t_, updateErr := c.ctx.Client.Resource(etcdRes).\n\t\tNamespace(cluster.Namespace).\n\t\tUpdate(context.TODO(), etcd, metav1.UpdateOptions{})\n\tif updateErr != nil {\n\t\tklog.Error(updateErr.Error())\n\t\treturn updateErr\n\t}\n\treturn nil\n}\n\n// Equal checks etcdcluster, if not equal, sync etcdclusters.etcd.tkestack.io\n// if equal, nothing to do\nfunc (c *EtcdClusterKstone) Equal(cluster *kstonev1alpha2.EtcdCluster) (bool, error) {\n\tetcdRes := schema.GroupVersionResource{Group: \"etcd.tkestack.io\", Version: \"v1alpha1\", Resource: \"etcdclusters\"}\n\tetcd, err := c.ctx.Client.Resource(etcdRes).\n\t\tNamespace(cluster.Namespace).\n\t\tGet(context.TODO(), cluster.Name, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn true, err\n\t}\n\n\toldSize, _, _ := unstructured.NestedInt64(etcd.Object, \"spec\", \"size\")\n\tif int64(cluster.Spec.Size) != oldSize {\n\t\tklog.Info(\"size is different\")\n\t\treturn false, nil\n\t}\n\n\toldVersion, _, _ := unstructured.NestedString(etcd.Object, \"spec\", \"version\")\n\tif strings.TrimLeft(oldVersion, \"v\") != strings.TrimLeft(cluster.Spec.Version, \"v\") {\n\t\tklog.Info(\"version is different\")\n\t\treturn false, nil\n\t}\n\n\toldStorage, _, _ := unstructured.NestedString(\n\t\tetcd.Object,\n\t\t\"spec\",\n\t\t\"template\",\n\t\t\"persistentVolumeClaimSpec\",\n\t\t\"resources\",\n\t\t\"requests\",\n\t\t\"storage\",\n\t)\n\tif strings.TrimRight(oldStorage, \"Gi\") != strconv.Itoa(int(cluster.Spec.DiskSize)) {\n\t\tklog.Info(\"storage is different\")\n\t\treturn false, nil\n\t}\n\n\tif !c.resourceEqual(cluster, etcd) {\n\t\treturn false, nil\n\t}\n\n\toldEnvObject, _, _ := unstructured.NestedSlice(etcd.Object, \"spec\", \"template\", \"env\")\n\toldEnv := make([]corev1.EnvVar, 0)\n\toldEnvBytes, err := json.Marshal(oldEnvObject)\n\tif err != nil {\n\t\treturn true, err\n\t}\n\terr = json.Unmarshal(oldEnvBytes, &oldEnv)\n\tif err != nil {\n\t\treturn true, err\n\t}\n\tif len(oldEnv) == 0 && len(cluster.Spec.Env) == 0 {\n\t\treturn true, nil\n\t}\n\tif !reflect.DeepEqual(oldEnv, cluster.Spec.Env) {\n\t\tklog.Info(\"env is different\")\n\t\treturn false, nil\n\t}\n\n\treturn true, nil\n}\n\n// AfterUpdate handles etcdcluster after updated\nfunc (c *EtcdClusterKstone) AfterUpdate(cluster *kstonev1alpha2.EtcdCluster) error {\n\treturn nil\n}\n\n// BeforeDelete handles etcdcluster before deleted\nfunc (c *EtcdClusterKstone) BeforeDelete(cluster *kstonev1alpha2.EtcdCluster) error {\n\treturn nil\n}\n\n// Delete handles delete\nfunc (c *EtcdClusterKstone) Delete(cluster *kstonev1alpha2.EtcdCluster) error {\n\treturn nil\n}\n\n// AfterDelete handles etcdcluster after deleted\nfunc (c *EtcdClusterKstone) AfterDelete(cluster *kstonev1alpha2.EtcdCluster) error {\n\treturn nil\n}\n\n// Status checks etcd member and returns new status\nfunc (c *EtcdClusterKstone) Status(config *etcd.ClientConfig, cluster *kstonev1alpha2.EtcdCluster) (kstonev1alpha2.EtcdClusterStatus, error) {\n\tvar phase kstonev1alpha2.EtcdClusterPhase\n\n\tstatus := cluster.Status\n\n\tannotations := cluster.Annotations\n\tif annotations == nil {\n\t\tannotations = make(map[string]string)\n\t}\n\n\t// endpoints\n\tendpoints := clusterprovider.GetStorageMemberEndpoints(cluster)\n\n\tif len(endpoints) == 0 {\n\t\tif addr, found := annotations[AnnoImportedURI]; found {\n\t\t\tendpoints = append(endpoints, addr)\n\t\t\tstatus.ServiceName = addr\n\t\t} else {\n\t\t\tstatus.Phase = kstonev1alpha2.EtcdCluterCreating\n\t\t\treturn status, nil\n\t\t}\n\t}\n\n\tmembers, err := clusterprovider.GetRuntimeEtcdMembers(\n\t\tcluster.Spec.StorageBackend,\n\t\tendpoints,\n\t\tcluster.Annotations[util.ClusterExtensionClientURL],\n\t\tconfig,\n\t)\n\tif err != nil || len(members) == 0 || int(cluster.Spec.Size) != len(members) {\n\t\tif status.Phase == kstonev1alpha2.EtcdClusterRunning {\n\t\t\tstatus.Phase = kstonev1alpha2.EtcdClusterUnknown\n\t\t}\n\t\treturn status, err\n\t}\n\n\tstatus.Members, phase = clusterprovider.GetEtcdClusterMemberStatus(members, config)\n\tif status.Phase == kstonev1alpha2.EtcdClusterRunning || phase != kstonev1alpha2.EtcdClusterUnknown {\n\t\tstatus.Phase = phase\n\t}\n\treturn status, err\n}\n\n// updateEtcdSpec update spec\nfunc (c *EtcdClusterKstone) updateEtcdSpec(etcd *unstructured.Unstructured, cluster *kstonev1alpha2.EtcdCluster) error {\n\tnewSpec := c.generateEtcdSpec(cluster)\n\n\tspec, found, err := unstructured.NestedMap(etcd.Object, \"spec\")\n\tif err != nil || !found || spec == nil {\n\t\treturn fmt.Errorf(\"get spec error\")\n\t}\n\n\tif err = unstructured.SetNestedField(etcd.Object, newSpec, \"spec\"); err != nil {\n\t\tklog.Error(err.Error())\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n// generateEtcdSpec generate spec with etcdcluster\nfunc (c *EtcdClusterKstone) generateEtcdSpec(cluster *kstonev1alpha2.EtcdCluster) map[string]interface{} {\n\textraServerCertSANsStr := cluster.Annotations[\"extraServerCertSANs\"]\n\textraServerCertSANList := make([]interface{}, 0)\n\tfor _, certSAN := range strings.Split(extraServerCertSANsStr, \",\") {\n\t\ttemp := strings.TrimSpace(certSAN)\n\t\tif temp == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\textraServerCertSANList = append(extraServerCertSANList, temp)\n\t}\n\tif len(extraServerCertSANList) == 0 {\n\t\textraServerCertSANList = nil\n\t}\n\n\tlabels := make(map[string]interface{}, len(cluster.Labels))\n\tfor k, v := range cluster.Labels {\n\t\tlabels[k] = v\n\t}\n\tannotations := make(map[string]interface{}, len(cluster.Annotations))\n\tfor k, v := range cluster.Annotations {\n\t\tannotations[k] = v\n\t}\n\tenv := make([]interface{}, 0)\n\tenvBytes, _ := json.Marshal(cluster.Spec.Env)\n\t_ = json.Unmarshal(envBytes, &env)\n\n\tpersistentVolumeClaimSpec := map[string]interface{}{\n\t\t\"accessModes\": []interface{}{\n\t\t\t\"ReadWriteOnce\",\n\t\t},\n\t\t\"resources\": map[string]interface{}{\n\t\t\t\"requests\": map[string]interface{}{\n\t\t\t\t\"storage\": fmt.Sprintf(\"%dGi\", cluster.Spec.DiskSize),\n\t\t\t},\n\t\t},\n\t}\n\n\tif cluster.Spec.DiskType != \"\" {\n\t\tpersistentVolumeClaimSpec[\"storageClassName\"] = cluster.Spec.DiskType\n\t}\n\n\tspec := map[string]interface{}{\n\t\t\"size\":    int64(cluster.Spec.Size),\n\t\t\"version\": cluster.Spec.Version,\n\t\t\"template\": map[string]interface{}{\n\t\t\t\"extraArgs\": []interface{}{\n\t\t\t\t\"logger=zap\",\n\t\t\t},\n\t\t\t\"labels\":                    labels,\n\t\t\t\"annotations\":               annotations,\n\t\t\t\"env\":                       env,\n\t\t\t\"persistentVolumeClaimSpec\": persistentVolumeClaimSpec,\n\t\t},\n\t}\n\n\tresources := make(map[string]interface{})\n\tif cluster.Spec.Resources.Limits != nil {\n\t\tresources[\"limits\"] = map[string]interface{}{\n\t\t\t\"cpu\":    cluster.Spec.Resources.Limits.Cpu().String(),\n\t\t\t\"memory\": cluster.Spec.Resources.Limits.Memory().String(),\n\t\t}\n\t}\n\tif cluster.Spec.Resources.Requests != nil {\n\t\tresources[\"requests\"] = map[string]interface{}{\n\t\t\t\"cpu\":    cluster.Spec.Resources.Requests.Cpu().String(),\n\t\t\t\"memory\": cluster.Spec.Resources.Requests.Memory().String(),\n\t\t}\n\t}\n\n\tspec[\"template\"].(map[string]interface{})[\"resources\"] = resources\n\n\tif cluster.Annotations[\"scheme\"] == \"https\" {\n\t\tautoTLSCert := map[string]interface{}{\n\t\t\t\"autoGenerateClientCert\": true,\n\t\t\t\"autoGeneratePeerCert\":   true,\n\t\t\t\"autoGenerateServerCert\": true,\n\t\t\t\"extraServerCertSANs\":    extraServerCertSANList,\n\t\t}\n\t\tif cluster.Spec.AuthConfig.TLSSecret != \"\" {\n\t\t\tautoTLSCert[\"externalCASecret\"] = cluster.Spec.AuthConfig.TLSSecret\n\t\t}\n\n\t\tspec[\"secure\"] = map[string]interface{}{\n\t\t\t\"tls\": map[string]interface{}{\n\t\t\t\t\"autoTLSCert\": autoTLSCert,\n\t\t\t},\n\t\t}\n\t\tspec[\"template\"].(map[string]interface{})[\"extraArgs\"] = []interface{}{\n\t\t\t\"logger=zap\",\n\t\t\t\"client-cert-auth=true\",\n\t\t}\n\t}\n\n\tif cluster.Annotations[\"repository\"] != \"\" {\n\t\tspec[\"repository\"] = cluster.Annotations[\"repository\"]\n\t}\n\n\t// TODO: Use struct to replace\n\taffinity := make(map[string]interface{})\n\taffinityBytes, _ := json.Marshal(cluster.Spec.Affinity)\n\t_ = json.Unmarshal(affinityBytes, &affinity)\n\tif affinity != nil {\n\t\tspec[\"template\"].(map[string]interface{})[\"affinity\"] = affinity\n\t}\n\n\tif cluster.Spec.Tolerations != nil && len(cluster.Spec.Tolerations) > 0 {\n\t\ttolerations := make([]interface{}, 0)\n\t\ttolerationsBytes, _ := json.Marshal(cluster.Spec.Tolerations)\n\t\t_ = json.Unmarshal(tolerationsBytes, &tolerations)\n\t\tspec[\"template\"].(map[string]interface{})[\"tolerations\"] = tolerations\n\t}\n\n\treturn spec\n}\n\n// resourceEqual checks if old resource is equal to desired resource\n// Note that if Resources.Limits.Cpu or other resource is not exists,\n// kubernetes will check and return a default Quantity Object\n// So there will be no nil pointer panic\nfunc (c *EtcdClusterKstone) resourceEqual(cluster *kstonev1alpha2.EtcdCluster, etcd *unstructured.Unstructured) bool {\n\tresourceTypeNames := []corev1.ResourceName{corev1.ResourceRequestsCPU, corev1.ResourceRequestsMemory, corev1.ResourceLimitsCPU, corev1.ResourceLimitsMemory}\n\tfor _, resourceTypeName := range resourceTypeNames {\n\t\tr := strings.Split(string(resourceTypeName), \".\")\n\t\tresourceType, resourceName := r[0], r[1]\n\t\toldResource := c.getOldResource(etcd, resourceType, resourceName)\n\t\tdesiredResource := c.getDesiredResource(cluster, resourceTypeName)\n\t\tif oldResource != desiredResource {\n\t\t\tinfo := fmt.Sprintf(\"%s %s is different\", resourceName, resourceType)\n\t\t\tklog.Info(info)\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfunc (c *EtcdClusterKstone) getOldResource(etcd *unstructured.Unstructured, resourceType, resourceName string) string {\n\tresource, _, _ := unstructured.NestedString(etcd.Object, \"spec\", \"template\", \"resources\", resourceType, resourceName)\n\tif resource == \"\" {\n\t\tresource = defaultEmptyResourceValue\n\t}\n\treturn resource\n}\n\nfunc (c *EtcdClusterKstone) getDesiredResource(cluster *kstonev1alpha2.EtcdCluster, resourceTypeName corev1.ResourceName) string {\n\tswitch resourceTypeName {\n\tcase corev1.ResourceLimitsCPU:\n\t\treturn cluster.Spec.Resources.Limits.Cpu().String()\n\tcase corev1.ResourceLimitsMemory:\n\t\treturn cluster.Spec.Resources.Limits.Memory().String()\n\tcase corev1.ResourceRequestsCPU:\n\t\treturn cluster.Spec.Resources.Requests.Cpu().String()\n\tcase corev1.ResourceRequestsMemory:\n\t\treturn cluster.Spec.Resources.Requests.Memory().String()\n\t}\n\treturn \"\"\n}\n"
  },
  {
    "path": "pkg/clusterprovider/providers/providers.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage providers\n\nimport (\n\t_ \"tkestack.io/kstone/pkg/clusterprovider/providers/imported\" // import imported provider\n\t_ \"tkestack.io/kstone/pkg/clusterprovider/providers/kstone\"   // import kstone provider\n)\n"
  },
  {
    "path": "pkg/controllers/etcdcluster/etcdclusters_controller.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage etcdcluster\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"time\"\n\n\tcorev1 \"k8s.io/api/core/v1\"\n\t\"k8s.io/apimachinery/pkg/api/errors\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\tutilruntime \"k8s.io/apimachinery/pkg/util/runtime\"\n\t\"k8s.io/apimachinery/pkg/util/wait\"\n\tinformerscorev1 \"k8s.io/client-go/informers/core/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/client-go/kubernetes/scheme\"\n\ttypedcorev1 \"k8s.io/client-go/kubernetes/typed/core/v1\"\n\tlisterscorev1 \"k8s.io/client-go/listers/core/v1\"\n\t\"k8s.io/client-go/tools/cache\"\n\t\"k8s.io/client-go/tools/record\"\n\t\"k8s.io/client-go/util/workqueue\"\n\t\"k8s.io/klog/v2\"\n\n\t\"tkestack.io/kstone/pkg/clusterprovider\"\n\t_ \"tkestack.io/kstone/pkg/clusterprovider/providers\" // register cluster provider\n\t\"tkestack.io/kstone/pkg/controllers/util\"\n\t\"tkestack.io/kstone/pkg/etcd\"\n\t\"tkestack.io/kstone/pkg/featureprovider\"\n\n\t_ \"tkestack.io/kstone/pkg/featureprovider/providers\" // register feature provider\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\tfeatureutil \"tkestack.io/kstone/pkg/featureprovider/util\"\n\tclientset \"tkestack.io/kstone/pkg/generated/clientset/versioned\"\n\tplatformscheme \"tkestack.io/kstone/pkg/generated/clientset/versioned/scheme\"\n\tinformers \"tkestack.io/kstone/pkg/generated/informers/externalversions/kstone/v1alpha2\"\n\tlisters \"tkestack.io/kstone/pkg/generated/listers/kstone/v1alpha2\"\n)\n\n// ClusterController is the controller implementation for EtcdCluster resources\ntype ClusterController struct {\n\t// kubeclientset is a standard kubernetes clientset\n\tkubeclientset kubernetes.Interface\n\t// platformclientset is a clientset for our own API group\n\tplatformclientset clientset.Interface\n\n\tsecretLister listerscorev1.SecretLister\n\tsecretSynced cache.InformerSynced\n\n\tetcdclusterLister listers.EtcdClusterLister\n\tetcdclusterSynced cache.InformerSynced\n\n\t// To allow injection of syncEtcdCluster for testing.\n\tsyncHandler func(eKey string) error\n\n\t// workqueue is a rate limited work queue. This is used to queue work to be\n\t// processed instead of performing it as soon as a change happens. This\n\t// means we can ensure we only process a fixed amount of resources at a\n\t// time, and makes it easy to ensure we are never processing the same item\n\t// simultaneously in two different workers.\n\tworkqueue workqueue.RateLimitingInterface\n\t// recorder is an event recorder for recording Event resources to the\n\t// Kubernetes API.\n\trecorder record.EventRecorder\n\n\tclientbuilder util.ClientBuilder\n\n\tclientConfigGetter etcd.ClientConfigGetter\n}\n\n// NewEtcdclusterController returns a new etcdcluster controller\nfunc NewEtcdclusterController(\n\tclientbuilder util.ClientBuilder,\n\tkubeclientset kubernetes.Interface,\n\tplatformclientset clientset.Interface,\n\tsecretInformer informerscorev1.SecretInformer,\n\tetcdclusterInformer informers.EtcdClusterInformer) *ClusterController {\n\n\t// Create event broadcaster\n\t// Add kstone types to the default Kubernetes Scheme so Events can be\n\t// logged for kstone types.\n\tutilruntime.Must(platformscheme.AddToScheme(scheme.Scheme))\n\tklog.V(4).Info(\"Creating event broadcaster\")\n\teventBroadcaster := record.NewBroadcaster()\n\teventBroadcaster.StartStructuredLogging(0)\n\teventBroadcaster.StartRecordingToSink(&typedcorev1.EventSinkImpl{Interface: kubeclientset.CoreV1().Events(\"\")})\n\trecorder := eventBroadcaster.NewRecorder(\n\t\tscheme.Scheme,\n\t\tcorev1.EventSource{Component: util.ComponentEtcdClusterController},\n\t)\n\n\tcontroller := &ClusterController{\n\t\tclientbuilder:     clientbuilder,\n\t\tkubeclientset:     kubeclientset,\n\t\tplatformclientset: platformclientset,\n\t\tsecretLister:      secretInformer.Lister(),\n\t\tsecretSynced:      secretInformer.Informer().HasSynced,\n\t\tetcdclusterLister: etcdclusterInformer.Lister(),\n\t\tetcdclusterSynced: etcdclusterInformer.Informer().HasSynced,\n\t\tworkqueue:         workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), \"EtcdClusters\"),\n\t\trecorder:          recorder,\n\t}\n\n\tcontroller.syncHandler = controller.syncEtcdCluster\n\tcontroller.clientConfigGetter = etcd.NewClientConfigSecretCacheGetter(controller.secretLister)\n\n\tklog.Info(\"Setting up event handlers\")\n\t// Set up an event handler for when EtcdCluster resources change\n\tetcdclusterInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{\n\t\tAddFunc: controller.enqueueEtcdcluster,\n\t\tUpdateFunc: func(old, new interface{}) {\n\t\t\tcontroller.enqueueEtcdcluster(new)\n\t\t},\n\t})\n\n\treturn controller\n}\n\n// Run will set up the event handlers for types we are interested in, as well\n// as syncing informer caches and starting workers. It will block until stopCh\n// is closed, at which point it will shutdown the workqueue and wait for\n// workers to finish processing their current work items.\nfunc (c *ClusterController) Run(threadiness int, stopCh <-chan struct{}) error {\n\tdefer utilruntime.HandleCrash()\n\tdefer c.workqueue.ShutDown()\n\n\t// Start the informer factories to begin populating the informer caches\n\tklog.Info(\"Starting EtcdCluster controller\")\n\n\t// Wait for the caches to be synced before starting workers\n\tklog.Info(\"Waiting for informer caches to sync\")\n\tif ok := cache.WaitForCacheSync(stopCh, c.secretSynced, c.etcdclusterSynced); !ok {\n\t\treturn fmt.Errorf(\"failed to wait for caches to sync\")\n\t}\n\n\tklog.Info(\"Starting workers\")\n\t// Launch two workers to process EtcdCluster resources\n\tfor i := 0; i < threadiness; i++ {\n\t\tgo wait.Until(c.runWorker, time.Second, stopCh)\n\t}\n\n\tklog.Info(\"Started workers\")\n\t<-stopCh\n\tklog.Info(\"Shutting down workers\")\n\n\treturn nil\n}\n\n// runWorker is a long-running function that will continually call the\n// processNextWorkItem function in order to read and process a message on the\n// workqueue.\nfunc (c *ClusterController) runWorker() {\n\tfor c.processNextWorkItem() {\n\t}\n}\n\n// processNextWorkItem will read a single work item off the workqueue and\n// attempt to process it, by calling the syncHandler.\nfunc (c *ClusterController) processNextWorkItem() bool {\n\tobj, shutdown := c.workqueue.Get()\n\n\tif shutdown {\n\t\treturn false\n\t}\n\n\t// We wrap this block in a func so we can defer c.workqueue.Done.\n\terr := util.ProcessWorkQueue(c.workqueue, c.syncHandler, obj)\n\tif err != nil {\n\t\tutilruntime.HandleError(err)\n\t\treturn true\n\t}\n\n\treturn true\n}\n\n// syncEtcdCluster compares the actual state with the desired, and attempts to\n// converge the two. It then updates the Status block of the EtcdCluster resource\n// with the current status of the resource.\nfunc (c *ClusterController) syncEtcdCluster(key string) error {\n\t// Convert the namespace/name string into a distinct namespace and name\n\tnamespace, name, err := cache.SplitMetaNamespaceKey(key)\n\tif err != nil {\n\t\tutilruntime.HandleError(fmt.Errorf(\"invalid resource key: %s\", key))\n\t\treturn nil\n\t}\n\n\t// Get the EtcdCluster resource with this namespace/name\n\tetcdcluster, err := c.etcdclusterLister.EtcdClusters(namespace).Get(name)\n\tif err != nil {\n\t\t// The EtcdCluster resource may no longer exist, in which case we stop\n\t\t// processing.\n\t\tif errors.IsNotFound(err) {\n\t\t\tutilruntime.HandleError(fmt.Errorf(\"EtcdCluster '%s' in work queue no longer exists\", key))\n\t\t\treturn nil\n\t\t}\n\t\treturn err\n\t}\n\n\treturn c.reconcileEtcdCluster(etcdcluster.DeepCopy())\n}\n\n// updateEtcdClusterStatus\nfunc (c *ClusterController) updateEtcdClusterStatus(cluster *kstonev1alpha2.EtcdCluster) (\n\t*kstonev1alpha2.EtcdCluster,\n\terror,\n) {\n\t// NEVER modify objects from the store. It's a read-only, local cache.\n\t// You can use DeepCopy() to make a deep copy of original object and modify this copy\n\t// Or create a copy manually for better performance\n\t// clusterCopy := cluster.DeepCopy()\n\t// If the CustomResourceSubresources feature gate is not enabled,\n\t// we must use Update instead of UpdateStatus to update the Status block of the EtcdCluster resource.\n\t// UpdateStatus will not allow changes to the Spec of the resource,\n\t// which is ideal for ensuring nothing other than resource status has been updated.\n\tetcdcluster, err := c.platformclientset.KstoneV1alpha2().EtcdClusters(cluster.Namespace).\n\t\tUpdate(context.TODO(), cluster, metav1.UpdateOptions{})\n\tif err != nil {\n\t\treturn cluster, err\n\t}\n\treturn etcdcluster, nil\n}\n\n// enqueueEtcdcluster takes a EtcdCluster resource and converts it into a namespace/name\n// string which is then put onto the work queue. This method should *not* be\n// passed resources of any type other than EtcdCluster.\nfunc (c *ClusterController) enqueueEtcdcluster(obj interface{}) {\n\tvar key string\n\tvar err error\n\tif key, err = cache.MetaNamespaceKeyFunc(obj); err != nil {\n\t\tutilruntime.HandleError(err)\n\t\treturn\n\t}\n\tc.workqueue.Add(key)\n}\n\nfunc (c *ClusterController) handleClusterManagement(cluster *kstonev1alpha2.EtcdCluster) (\n\t*kstonev1alpha2.EtcdCluster,\n\terror,\n) {\n\t// Get cluster provider\n\tprovider, err := c.GetEtcdClusterProvider(cluster.Spec.ClusterType)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get cluster provider %s, err is %v, cluster is %s\",\n\t\t\tcluster.Spec.ClusterType, err, cluster.Name)\n\t\treturn cluster, err\n\t}\n\tnextAction, err := c.getDesiredAction(cluster, provider)\n\tif err != nil {\n\t\treturn cluster, err\n\t}\n\tswitch nextAction {\n\tcase kstonev1alpha2.EtcdCluterCreating:\n\t\tcluster, err = c.handleClusterCreate(cluster, provider)\n\tcase kstonev1alpha2.EtcdClusterUpdating:\n\t\tcluster, err = c.handleClusterUpdate(cluster, provider)\n\tdefault:\n\t\tcluster, err = c.handleClusterStatus(cluster, provider)\n\t}\n\t_, _ = c.updateEtcdClusterStatus(cluster)\n\tif err != nil {\n\t\tc.recorder.Eventf(\n\t\t\tcluster,\n\t\t\tcorev1.EventTypeWarning,\n\t\t\tstring(nextAction),\n\t\t\t\"failed to set cluster %s, err is %v, cluster is %s\",\n\t\t\tstring(nextAction),\n\t\t\terr,\n\t\t\tcluster.ClusterName,\n\t\t)\n\t\treturn cluster, err\n\t}\n\treturn cluster, nil\n}\n\nfunc (c *ClusterController) enabledFeatureGate(annotations map[string]string, name kstonev1alpha2.KStoneFeature) bool {\n\treturn featureutil.IsFeatureGateEnabled(annotations, name)\n}\n\n// handleClusterLabels updates EtcdCluster Resource labels.\nfunc (c *ClusterController) handleClusterLabels(\n\tcluster *kstonev1alpha2.EtcdCluster) (*kstonev1alpha2.EtcdCluster, error) {\n\tannotations := cluster.ObjectMeta.Annotations\n\tif annotations == nil {\n\t\tannotations = make(map[string]string)\n\t}\n\n\tlabels := cluster.ObjectMeta.Labels\n\tif labels == nil {\n\t\tlabels = make(map[string]string)\n\t}\n\tfor featureName := range featureprovider.EtcdFeatureProviders {\n\t\tlabels[featureName] = strconv.FormatBool(c.enabledFeatureGate(annotations, kstonev1alpha2.KStoneFeature(featureName)))\n\t}\n\n\tlabels[\"clusterType\"] = string(cluster.Spec.ClusterType)\n\tlabels[\"version\"] = cluster.Spec.Version\n\tif !reflect.DeepEqual(cluster.ObjectMeta.Labels, labels) {\n\t\tcluster.ObjectMeta.Labels = labels\n\t\treturn c.updateEtcdClusterStatus(cluster)\n\t}\n\treturn cluster, nil\n}\n\nfunc (c *ClusterController) handleClusterFeature(cluster *kstonev1alpha2.EtcdCluster) (\n\t*kstonev1alpha2.EtcdCluster,\n\terror) {\n\t// Check cluster status, ensure cluster is running\n\tif cluster.Status.Phase != kstonev1alpha2.EtcdClusterRunning || len(cluster.Status.Members) == 0 {\n\t\tklog.V(3).Infof(\"cluster status is not running, waiting\")\n\t\treturn cluster, nil\n\t}\n\n\tannotations := cluster.ObjectMeta.Annotations\n\tif annotations == nil {\n\t\tannotations = make(map[string]string)\n\t}\n\n\tif cluster.Status.FeatureGatesStatus == nil {\n\t\tcluster.Status.FeatureGatesStatus = make(map[kstonev1alpha2.KStoneFeature]string)\n\t}\n\tfor name := range featureprovider.EtcdFeatureProviders {\n\t\tfeatureName := kstonev1alpha2.KStoneFeature(name)\n\t\tfeature, err := c.GetFeatureProvider(name)\n\t\tif err != nil {\n\t\t\tklog.Errorf(\"failed to get feature %s provider,err is %v\", name, err)\n\t\t\tcontinue\n\t\t}\n\t\tif feature.Equal(cluster) {\n\t\t\tklog.V(4).Infof(\"skip feature %s,no changed, cluster is %s\", name, cluster.Name)\n\t\t\tcontinue\n\t\t}\n\t\terr = feature.Sync(cluster)\n\t\tif err != nil {\n\t\t\tklog.Errorf(\"failed to sync %s feature, err is %v, cluster is %s\", name, err, cluster.Name)\n\t\t\tcluster.Status.FeatureGatesStatus[featureName] = fmt.Sprintf(\"failed to sync %s feature, err is %v\", name, err)\n\t\t\tcontinue\n\t\t}\n\t\tif c.enabledFeatureGate(annotations, featureName) {\n\t\t\tcluster.Status.FeatureGatesStatus[featureName] = featureutil.FeatureStatusEnabled\n\t\t} else {\n\t\t\tcluster.Status.FeatureGatesStatus[featureName] = featureutil.FeatureStatusDisabled\n\t\t}\n\t}\n\treturn c.updateEtcdClusterStatus(cluster)\n}\n\nfunc (c *ClusterController) reconcileEtcdCluster(cluster *kstonev1alpha2.EtcdCluster) error {\n\t// Handle cluster Creation,Update operations\n\tcluster, err := c.handleClusterManagement(cluster)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to handle cluster management operations, err is %v, cluster is %s\", err, cluster.Name)\n\t\treturn err\n\t}\n\n\t// If cluster is not running, do not proceed to the next step\n\tif cluster.Status.Phase != kstonev1alpha2.EtcdClusterRunning {\n\t\tklog.Warningf(\"cluster %s is not ready\", cluster.Name)\n\t\treturn nil\n\t}\n\n\t// Handle cluster labels\n\tcluster, err = c.handleClusterLabels(cluster)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to handle cluster labels, err is %v, cluster is %s\", err, cluster.Name)\n\t\treturn err\n\t}\n\n\t// Handle cluster feature\n\tcluster, err = c.handleClusterFeature(cluster)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to handle cluster feature, err is %v, cluster is %s\", err, cluster.Name)\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (c *ClusterController) GetFeatureProvider(name string) (featureprovider.Feature, error) {\n\tctx := &featureprovider.FeatureContext{\n\t\tClientBuilder:      c.clientbuilder,\n\t\tClientConfigGetter: c.clientConfigGetter,\n\t}\n\tfeature, err := featureprovider.GetFeatureProvider(name, ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn feature, nil\n}\n\nfunc (c *ClusterController) GetEtcdClusterProvider(name kstonev1alpha2.EtcdClusterType) (clusterprovider.Cluster, error) {\n\tctx := &clusterprovider.ClusterContext{\n\t\tClientbuilder: c.clientbuilder,\n\t}\n\tcluster, err := clusterprovider.GetEtcdClusterProvider(name, ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn cluster, nil\n}\n\nfunc (c *ClusterController) getDesiredAction(\n\tcluster *kstonev1alpha2.EtcdCluster,\n\tprovider clusterprovider.Cluster,\n) (kstonev1alpha2.EtcdClusterPhase, error) {\n\tif len(cluster.Status.Conditions) == 0 {\n\t\treturn kstonev1alpha2.EtcdCluterCreating, nil\n\t}\n\n\tconditionIndex := len(cluster.Status.Conditions) - 1\n\tlastCondition := cluster.Status.Conditions[conditionIndex]\n\n\tswitch lastCondition.Type {\n\tcase kstonev1alpha2.EtcdClusterConditionCreate:\n\t\tif lastCondition.Status == corev1.ConditionFalse {\n\t\t\treturn kstonev1alpha2.EtcdCluterCreating, nil\n\t\t}\n\tcase kstonev1alpha2.EtcdClusterConditionUpdate:\n\t\tif lastCondition.Status == corev1.ConditionFalse {\n\t\t\treturn kstonev1alpha2.EtcdClusterUpdating, nil\n\t\t}\n\t}\n\n\tequal, err := provider.Equal(cluster)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to check if the cluster is equal, err is %v,cluster is %s\", err, cluster.Name)\n\t\treturn kstonev1alpha2.EtcdClusterUnknown, err\n\t}\n\tif !equal {\n\t\tklog.Infof(\"spec is different, need to update etcd, cluster is %s\", cluster.Name)\n\t\treturn kstonev1alpha2.EtcdClusterUpdating, nil\n\t}\n\n\treturn kstonev1alpha2.EtcdClusterRunning, nil\n}\n\nfunc (c *ClusterController) generateConditions(\n\tconditions []kstonev1alpha2.EtcdClusterCondition,\n\tphase kstonev1alpha2.EtcdClusterPhase,\n\tnextConditionType kstonev1alpha2.EtcdClusterConditionType,\n) []kstonev1alpha2.EtcdClusterCondition {\n\tconditionIndex := len(conditions) - 1\n\tif conditionIndex >= 0 {\n\t\tlastCondition := conditions[conditionIndex]\n\t\tif lastCondition.Status != corev1.ConditionTrue {\n\t\t\treturn conditions\n\t\t}\n\n\t\tif lastCondition.Type == nextConditionType {\n\t\t\tconditions = conditions[:conditionIndex]\n\t\t}\n\t}\n\n\tconditions = append(conditions, kstonev1alpha2.EtcdClusterCondition{\n\t\tType:      nextConditionType,\n\t\tStatus:    corev1.ConditionFalse,\n\t\tStartTime: metav1.Now(),\n\t})\n\n\treturn conditions\n}\n\nfunc (c *ClusterController) handleClusterCreate(\n\tcluster *kstonev1alpha2.EtcdCluster,\n\tprovider clusterprovider.Cluster,\n) (*kstonev1alpha2.EtcdCluster, error) {\n\tcluster.Status.Conditions = c.generateConditions(\n\t\tcluster.Status.Conditions,\n\t\tcluster.Status.Phase,\n\t\tkstonev1alpha2.EtcdClusterConditionCreate,\n\t)\n\tcluster.Status.Phase = kstonev1alpha2.EtcdCluterCreating\n\n\tconditionIndex := len(cluster.Status.Conditions) - 1\n\n\terr := provider.BeforeCreate(cluster)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to do something before create, err is %v, cluster is %s\", err, cluster.Name)\n\t\tcluster.Status.Conditions[conditionIndex].Reason = err.Error()\n\t\treturn cluster, err\n\t}\n\n\terr = provider.Create(cluster)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to create, err is %v, cluster is %s\", err, cluster.Name)\n\t\tcluster.Status.Conditions[conditionIndex].Reason = err.Error()\n\t\treturn cluster, err\n\t}\n\n\terr = provider.AfterCreate(cluster)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to do something after create, err is %v, cluster is %s\", err, cluster.Name)\n\t\tcluster.Status.Conditions[conditionIndex].Reason = err.Error()\n\t\treturn cluster, err\n\t}\n\n\tcluster.Status.Conditions[conditionIndex].Reason = \"\"\n\tcluster.Status.Conditions[conditionIndex].EndTime = metav1.Now()\n\tcluster.Status.Conditions[conditionIndex].Status = corev1.ConditionTrue\n\treturn cluster, nil\n}\n\nfunc (c *ClusterController) handleClusterUpdate(\n\tcluster *kstonev1alpha2.EtcdCluster,\n\tprovider clusterprovider.Cluster,\n) (*kstonev1alpha2.EtcdCluster, error) {\n\tcluster.Status.Conditions = c.generateConditions(\n\t\tcluster.Status.Conditions,\n\t\tcluster.Status.Phase,\n\t\tkstonev1alpha2.EtcdClusterConditionUpdate,\n\t)\n\tcluster.Status.Phase = kstonev1alpha2.EtcdClusterUpdating\n\tconditionIndex := len(cluster.Status.Conditions) - 1\n\n\terr := provider.BeforeUpdate(cluster)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to do something before update, err is %v, cluster is %s\", err, cluster.Name)\n\t\tcluster.Status.Conditions[conditionIndex].Reason = err.Error()\n\t\treturn cluster, err\n\t}\n\n\terr = provider.Update(cluster)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to update, err is %v, cluster is %s\", err, cluster.Name)\n\t\tcluster.Status.Conditions[conditionIndex].Reason = err.Error()\n\t\treturn cluster, err\n\t}\n\n\terr = provider.AfterUpdate(cluster)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to do something after update, err is %v, cluster is %s\", err, cluster.Name)\n\t\tcluster.Status.Conditions[conditionIndex].Reason = err.Error()\n\t\treturn cluster, err\n\t}\n\n\tcluster.Status.Conditions[conditionIndex].Reason = \"\"\n\tcluster.Status.Conditions[conditionIndex].EndTime = metav1.Now()\n\tcluster.Status.Conditions[conditionIndex].Status = corev1.ConditionTrue\n\treturn cluster, nil\n}\n\n// handleClusterStatus checks the status, if equal, updates status\n// if not equal, updates etcdclusters.etcd.tkestack.io\nfunc (c *ClusterController) handleClusterStatus(\n\tcluster *kstonev1alpha2.EtcdCluster,\n\tprovider clusterprovider.Cluster,\n) (*kstonev1alpha2.EtcdCluster, error) {\n\t// Check and update Cluster Status\n\tannotations := cluster.ObjectMeta.Annotations\n\tsecretName := \"\"\n\tif annotations != nil {\n\t\tif _, found := annotations[util.ClusterTLSSecretName]; found {\n\t\t\tsecretName = annotations[util.ClusterTLSSecretName]\n\t\t}\n\t}\n\tpath := fmt.Sprintf(\"%s/%s\", cluster.Namespace, cluster.Name)\n\tclientConfig, err := c.clientConfigGetter.New(path, secretName)\n\tif err != nil {\n\t\treturn cluster, err\n\t}\n\n\tstatus, err := provider.Status(clientConfig, cluster)\n\tif err != nil {\n\t\tc.recorder.Eventf(\n\t\t\tcluster,\n\t\t\tcorev1.EventTypeWarning,\n\t\t\tstring(util.EtcdClusterUpdateStatus),\n\t\t\t\"failed to get cluster status %v\",\n\t\t\terr,\n\t\t)\n\t}\n\tcluster.Status = status\n\n\treturn cluster, nil\n}\n"
  },
  {
    "path": "pkg/controllers/etcdinspection/etcdinspection_controller.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage etcdinspection\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/go-martini/martini\"\n\t\"github.com/prometheus/client_golang/prometheus/promhttp\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\t\"k8s.io/apimachinery/pkg/api/errors\"\n\tutilruntime \"k8s.io/apimachinery/pkg/util/runtime\"\n\t\"k8s.io/apimachinery/pkg/util/wait\"\n\tinformerscorev1 \"k8s.io/client-go/informers/core/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/client-go/kubernetes/scheme\"\n\ttypedcorev1 \"k8s.io/client-go/kubernetes/typed/core/v1\"\n\tlisterscorev1 \"k8s.io/client-go/listers/core/v1\"\n\t\"k8s.io/client-go/tools/cache\"\n\t\"k8s.io/client-go/tools/record\"\n\t\"k8s.io/client-go/util/workqueue\"\n\tklog \"k8s.io/klog/v2\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/etcd\"\n\t// register etcd cluster providers\n\t_ \"tkestack.io/kstone/pkg/clusterprovider/providers\"\n\t\"tkestack.io/kstone/pkg/controllers/util\"\n\t\"tkestack.io/kstone/pkg/featureprovider\"\n\t// register etcd feature providers\n\t_ \"tkestack.io/kstone/pkg/featureprovider/providers\"\n\tclientset \"tkestack.io/kstone/pkg/generated/clientset/versioned\"\n\tplatformscheme \"tkestack.io/kstone/pkg/generated/clientset/versioned/scheme\"\n\tinformers \"tkestack.io/kstone/pkg/generated/informers/externalversions/kstone/v1alpha2\"\n\tlisters \"tkestack.io/kstone/pkg/generated/listers/kstone/v1alpha2\"\n)\n\n// InspectionController is the controller implementation for etcdinspection resources\ntype InspectionController struct {\n\t// kubeclientset is a standard kubernetes clientset\n\tkubeclientset kubernetes.Interface\n\t// platformclientset is a clientset for our own API group\n\tplatformclientset clientset.Interface\n\n\tsecretLister listerscorev1.SecretLister\n\tsecretSynced cache.InformerSynced\n\n\tetcdinspectionLister listers.EtcdInspectionLister\n\tetcdinspectionSynced cache.InformerSynced\n\t// To allow injection of doClusterInspection for testing.\n\tsyncHandler func(eKey string) error\n\n\t// workqueue is a rate limited work queue. This is used to queue work to be\n\t// processed instead of performing it as soon as a change happens. This\n\t// means we can ensure we only process a fixed amount of resources at a\n\t// time, and makes it easy to ensure we are never processing the same item\n\t// simultaneously in two different workers.\n\tworkqueue workqueue.RateLimitingInterface\n\t// recorder is an event recorder for recording Event resources to the\n\t// Kubernetes API.\n\trecorder record.EventRecorder\n\n\tclientbuilder util.ClientBuilder\n\n\tclientConfigGetter etcd.ClientConfigGetter\n}\n\nfunc NewInspectionControllerMetric() http.Handler {\n\tm := martini.New()\n\tr := martini.NewRouter()\n\tr.Get(\"/health\", func() (int, string) {\n\t\treturn 200, \"ok\"\n\t})\n\tr.Get(\"/metrics\", promhttp.Handler())\n\tm.MapTo(r, (*martini.Routes)(nil))\n\tm.Action(r.Handle)\n\treturn m\n}\n\n// NewEtcdInspectionController returns a new etcdinspection controller\nfunc NewEtcdInspectionController(\n\tclientbuilder util.ClientBuilder,\n\tkubeclientset kubernetes.Interface,\n\tplatformclientset clientset.Interface,\n\tsecretInformer informerscorev1.SecretInformer,\n\tetcdinspectionInformer informers.EtcdInspectionInformer) *InspectionController {\n\n\t// Create event broadcaster\n\t// Add kstone types to the default Kubernetes Scheme so Events can be\n\t// logged for kstone types.\n\tutilruntime.Must(platformscheme.AddToScheme(scheme.Scheme))\n\tklog.V(4).Info(\"Creating event broadcaster\")\n\teventBroadcaster := record.NewBroadcaster()\n\teventBroadcaster.StartStructuredLogging(0)\n\teventBroadcaster.StartRecordingToSink(&typedcorev1.EventSinkImpl{Interface: kubeclientset.CoreV1().Events(\"\")})\n\trecorder := eventBroadcaster.NewRecorder(\n\t\tscheme.Scheme,\n\t\tcorev1.EventSource{Component: util.ComponentEtcdInspectionController},\n\t)\n\n\tcontroller := &InspectionController{\n\t\tclientbuilder:        clientbuilder,\n\t\tkubeclientset:        kubeclientset,\n\t\tplatformclientset:    platformclientset,\n\t\tsecretLister:         secretInformer.Lister(),\n\t\tsecretSynced:         secretInformer.Informer().HasSynced,\n\t\tetcdinspectionLister: etcdinspectionInformer.Lister(),\n\t\tetcdinspectionSynced: etcdinspectionInformer.Informer().HasSynced,\n\t\tworkqueue: workqueue.NewNamedRateLimitingQueue(\n\t\t\tworkqueue.DefaultControllerRateLimiter(),\n\t\t\t\"etcdinspections\",\n\t\t),\n\t\trecorder: recorder,\n\t}\n\tcontroller.syncHandler = controller.doClusterInspection\n\tcontroller.clientConfigGetter = etcd.NewClientConfigSecretCacheGetter(controller.secretLister)\n\n\tklog.Info(\"Setting up event handlers\")\n\t// Set up an event handler for when etcdinspection resources change\n\tetcdinspectionInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{\n\t\tAddFunc: controller.enqueueEtcdInspection,\n\t\tUpdateFunc: func(old, new interface{}) {\n\t\t\tcontroller.enqueueEtcdInspection(new)\n\t\t},\n\t})\n\n\treturn controller\n}\n\n// Run will set up the event handlers for types we are interested in, as well\n// as syncing informer caches and starting workers. It will block until stopCh\n// is closed, at which point it will shutdown the workqueue and wait for\n// workers to finish processing their current work items.\nfunc (c *InspectionController) Run(threadiness int, stopCh <-chan struct{}) error {\n\tdefer utilruntime.HandleCrash()\n\tdefer c.workqueue.ShutDown()\n\n\t// Start the informer factories to begin populating the informer caches\n\tklog.Info(\"Starting etcdinspection controller\")\n\n\t// Wait for the caches to be synced before starting workers\n\tklog.Info(\"Waiting for informer caches to sync\")\n\tif ok := cache.WaitForCacheSync(stopCh, c.secretSynced, c.etcdinspectionSynced); !ok {\n\t\treturn fmt.Errorf(\"failed to wait for caches to sync\")\n\t}\n\n\tklog.Info(\"Starting workers\")\n\t// Launch two workers to process etcdinspection resources\n\tfor i := 0; i < threadiness; i++ {\n\t\tgo wait.Until(c.runWorker, time.Second, stopCh)\n\t}\n\n\tgo func() {\n\t\terr := http.ListenAndServe(\":9090\", NewInspectionControllerMetric())\n\t\tif err != nil {\n\t\t\tklog.Errorf(\"listenAndServer error is %v\", err)\n\t\t}\n\t}()\n\n\tklog.Info(\"Started workers\")\n\t<-stopCh\n\tklog.Info(\"Shutting down workers\")\n\n\treturn nil\n}\n\n// runWorker is a long-running function that will continually call the\n// processNextWorkItem function in order to read and process a message on the\n// workqueue.\nfunc (c *InspectionController) runWorker() {\n\tfor c.processNextWorkItem() {\n\t}\n}\n\n// processNextWorkItem will read a single work item off the workqueue and\n// attempt to process it, by calling the syncHandler.\nfunc (c *InspectionController) processNextWorkItem() bool {\n\tobj, shutdown := c.workqueue.Get()\n\n\tif shutdown {\n\t\treturn false\n\t}\n\n\t// We wrap this block in a func so we can defer c.workqueue.Done.\n\terr := util.ProcessWorkQueue(c.workqueue, c.syncHandler, obj)\n\tif err != nil {\n\t\tutilruntime.HandleError(err)\n\t\treturn true\n\t}\n\n\treturn true\n}\n\nfunc (c *InspectionController) doClusterInspection(key string) error {\n\t// Convert the namespace/name string into a distinct namespace and name\n\tnamespace, name, err := cache.SplitMetaNamespaceKey(key)\n\tif err != nil {\n\t\tutilruntime.HandleError(fmt.Errorf(\"invalid resource key: %s\", key))\n\t\treturn nil\n\t}\n\n\t// Get the etcdinspection resource with this namespace/name\n\tetcdinspection, err := c.etcdinspectionLister.EtcdInspections(namespace).Get(name)\n\tif err != nil {\n\t\t// The etcdinspection resource may no longer exist, in which case we stop\n\t\t// processing.\n\t\tif errors.IsNotFound(err) {\n\t\t\tutilruntime.HandleError(fmt.Errorf(\"etcdinspection '%s' in work queue no longer exists\", key))\n\t\t\treturn nil\n\t\t}\n\t\treturn err\n\t}\n\n\treturn c.doInspectionTask(etcdinspection)\n}\n\n// enqueueEtcdInspection takes a etcdinspection resource and converts it into a namespace/name\n// string which is then put onto the work queue. This method should *not* be\n// passed resources of any type other than etcdinspection.\nfunc (c *InspectionController) enqueueEtcdInspection(obj interface{}) {\n\tvar key string\n\tvar err error\n\tif key, err = cache.MetaNamespaceKeyFunc(obj); err != nil {\n\t\tutilruntime.HandleError(err)\n\t\treturn\n\t}\n\tc.workqueue.Add(key)\n}\n\nfunc (c *InspectionController) GetInspectionFeatureProvider(name string) (featureprovider.Feature, error) {\n\tctx := &featureprovider.FeatureContext{\n\t\tClientBuilder:      c.clientbuilder,\n\t\tClientConfigGetter: c.clientConfigGetter,\n\t}\n\tfeature, err := featureprovider.GetFeatureProvider(name, ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn feature, nil\n}\n\nfunc (c *InspectionController) doInspectionTask(etcdinspection *kstonev1alpha2.EtcdInspection) error {\n\tinspectionType := etcdinspection.Spec.InspectionType\n\tfeature, err := c.GetInspectionFeatureProvider(inspectionType)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn feature.Do(etcdinspection)\n}\n"
  },
  {
    "path": "pkg/controllers/util/util.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage util\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/util/diff\"\n\tutilruntime \"k8s.io/apimachinery/pkg/util/runtime\"\n\t\"k8s.io/client-go/dynamic\"\n\tclientset \"k8s.io/client-go/kubernetes\"\n\tfake \"k8s.io/client-go/kubernetes/fake\"\n\trestclient \"k8s.io/client-go/rest\"\n\tcore \"k8s.io/client-go/testing\"\n\t\"k8s.io/client-go/util/workqueue\"\n\t\"k8s.io/klog/v2\"\n\n\t\"tkestack.io/kstone/pkg/k8s\"\n)\n\nconst (\n\tComponentEtcdClusterController    = \"etcdcluster-controller\"\n\tComponentEtcdInspectionController = \"etcdinspection-controller\"\n)\n\ntype EtcdClusterPhase string\n\nconst (\n\tEtcdClusterCreating     EtcdClusterPhase = \"EtcdClusterCreating\"\n\tEtcdClusterUpdating     EtcdClusterPhase = \"EtcdClusterUpdating\"\n\tEtcdClusterUpdateStatus EtcdClusterPhase = \"EtcdClusterUpdateStatus\"\n)\n\nconst (\n\tClusterTLSSecretName      = \"certName\"\n\tClusterExtensionClientURL = \"extClientURL\"\n)\n\ntype ClientBuilder interface {\n\tConfigOrDie() *restclient.Config\n\tClientOrDie() clientset.Interface\n\tDynamicClientOrDie() dynamic.Interface\n}\n\nfunc NewSimpleClientBuilder(kubeconfig string) ClientBuilder {\n\tbuilder := &simpleClientBuilder{\n\t\tkubeconfig: kubeconfig,\n\t}\n\treturn builder\n}\n\ntype simpleClientBuilder struct {\n\tkubeconfig string\n}\n\nfunc (s simpleClientBuilder) ConfigOrDie() *restclient.Config {\n\tcfg, err := k8s.GetClientConfig(s.kubeconfig)\n\tif err != nil {\n\t\tklog.Fatal(err)\n\t}\n\treturn cfg\n}\n\nfunc (s simpleClientBuilder) ClientOrDie() clientset.Interface {\n\tclientConfig := s.ConfigOrDie()\n\tclient, err := clientset.NewForConfig(clientConfig)\n\tif err != nil {\n\t\tklog.Fatal(err)\n\t}\n\treturn client\n}\n\nfunc (s simpleClientBuilder) DynamicClientOrDie() dynamic.Interface {\n\tclientConfig := s.ConfigOrDie()\n\tclient, err := dynamic.NewForConfig(clientConfig)\n\tif err != nil {\n\t\tklog.Fatal(err)\n\t}\n\treturn client\n}\n\nfunc NewFakeClientBuilder() ClientBuilder {\n\tbuilder := &fakeClientBuilder{\n\t\tclient: fake.NewSimpleClientset([]runtime.Object{}...),\n\t}\n\treturn builder\n}\n\ntype fakeClientBuilder struct {\n\tclient *fake.Clientset\n}\n\nfunc (f fakeClientBuilder) ConfigOrDie() *restclient.Config {\n\t// TODO: implement it and add controllers unit test\n\treturn nil\n}\n\nfunc (f fakeClientBuilder) ClientOrDie() clientset.Interface {\n\treturn f.client\n}\n\nfunc (f fakeClientBuilder) DynamicClientOrDie() dynamic.Interface {\n\t// TODO: implement it and add controllers unit test\n\treturn nil\n}\n\n// CheckAction verifies that expected and actual actions are equal and both have\n// same attached resources\nfunc CheckAction(expected, actual core.Action, t *testing.T) {\n\tif !(expected.Matches(actual.GetVerb(),\n\t\tactual.GetResource().Resource) && actual.GetSubresource() == expected.GetSubresource()) {\n\t\tt.Errorf(\"Expected\\n\\t%#v\\ngot\\n\\t%#v\", expected, actual)\n\t\treturn\n\t}\n\n\tif reflect.TypeOf(actual) != reflect.TypeOf(expected) {\n\t\tt.Errorf(\"Action has wrong type. Expected: %t. Got: %t\", expected, actual)\n\t\treturn\n\t}\n\n\tswitch a := actual.(type) {\n\tcase core.CreateActionImpl:\n\t\te, _ := expected.(core.CreateActionImpl)\n\t\texpObject := e.GetObject()\n\t\tobject := a.GetObject()\n\n\t\tif !reflect.DeepEqual(expObject, object) {\n\t\t\tt.Errorf(\"Action %s %s has wrong object\\nDiff:\\n %s\",\n\t\t\t\ta.GetVerb(), a.GetResource().Resource, diff.ObjectGoPrintSideBySide(expObject, object))\n\t\t}\n\tcase core.UpdateActionImpl:\n\t\te, _ := expected.(core.UpdateActionImpl)\n\t\texpObject := e.GetObject()\n\t\tobject := a.GetObject()\n\n\t\tif !reflect.DeepEqual(expObject, object) {\n\t\t\tt.Errorf(\"Action %s %s has wrong object\\nDiff:\\n %s\",\n\t\t\t\ta.GetVerb(), a.GetResource().Resource, diff.ObjectGoPrintSideBySide(expObject, object))\n\t\t}\n\tcase core.PatchActionImpl:\n\t\te, _ := expected.(core.PatchActionImpl)\n\t\texpPatch := e.GetPatch()\n\t\tpatch := a.GetPatch()\n\n\t\tif !reflect.DeepEqual(expPatch, patch) {\n\t\t\tt.Errorf(\"Action %s %s has wrong patch\\nDiff:\\n %s\",\n\t\t\t\ta.GetVerb(), a.GetResource().Resource, diff.ObjectGoPrintSideBySide(expPatch, patch))\n\t\t}\n\tdefault:\n\t\tt.Errorf(\"Uncaptured Action %s %s, you should explicitly add a case to capture it\",\n\t\t\tactual.GetVerb(), actual.GetResource().Resource)\n\t}\n}\n\n// ProcessWorkQueue handle item in queue, handle the result of syncHandler\nfunc ProcessWorkQueue(\n\tqueue workqueue.RateLimitingInterface,\n\tsyncHandler func(eKey string) error,\n\tobj interface{}) error {\n\tdefer queue.Done(obj)\n\tvar key string\n\tvar ok bool\n\n\tif key, ok = obj.(string); !ok {\n\t\tqueue.Forget(obj)\n\t\tutilruntime.HandleError(fmt.Errorf(\"expected string in workqueue but got %#v\", obj))\n\t\treturn nil\n\t}\n\tif err := syncHandler(key); err != nil {\n\t\tqueue.AddRateLimited(key)\n\t\treturn fmt.Errorf(\"error syncing '%s': %s, requeuing\", key, err.Error())\n\t}\n\tqueue.Forget(obj)\n\tklog.V(4).Infof(\"Successfully synced '%s'\", key)\n\treturn nil\n}\n\n// FilterInformerActions filters list and watch actions for testing resources.\n// Since list and watch don't change resource state we can filter it to lower\n// nose level in our tests.\nfunc FilterInformerActions(actions []core.Action, resourceName string) []core.Action {\n\tret := []core.Action{}\n\tfor _, action := range actions {\n\t\tif len(action.GetNamespace()) == 0 &&\n\t\t\t(action.Matches(\"list\", resourceName) ||\n\t\t\t\taction.Matches(\"watch\", resourceName)) {\n\t\t\tcontinue\n\t\t}\n\t\tret = append(ret, action)\n\t}\n\n\treturn ret\n}\n\nfunc CompareActions(t *testing.T, actions []core.Action, filteredActions []core.Action) {\n\tfor i, action := range filteredActions {\n\t\tt.Logf(\"client action id %d,action info %+v\", i, action)\n\t\tif len(actions) < i+1 {\n\t\t\tt.Errorf(\"%d unexpected filteredActions: %+v\", len(filteredActions)-len(actions), filteredActions[i:])\n\t\t\tbreak\n\t\t}\n\n\t\texpectedAction := actions[i]\n\t\tCheckAction(expectedAction, action, t)\n\t}\n\n\tif len(actions) > len(filteredActions) {\n\t\tt.Errorf(\n\t\t\t\"%d additional expected filteredActions:%+v\",\n\t\t\tlen(actions)-len(filteredActions),\n\t\t\tactions[len(filteredActions):],\n\t\t)\n\t}\n}\n"
  },
  {
    "path": "pkg/etcd/client/cleint.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage client\n\nimport (\n\t\"tkestack.io/kstone/pkg/etcd\"\n)\n\n// Member contains member info including v2 and v3\ntype Member struct {\n\tID         string\n\tName       string\n\tPeerURLs   []string\n\tClientURLs []string\n\tVersion    string\n\tIsLearner  bool\n\tLeader     string\n}\n\ntype VersionClient interface {\n\tMemberList() ([]Member, error)\n\tStatus(endpoint string) (*Member, error)\n\tClose()\n}\n\ntype VersionContext struct {\n\tConfig *etcd.ClientConfig\n}\n"
  },
  {
    "path": "pkg/etcd/client/version.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage client\n\nimport (\n\t\"errors\"\n\t\"sync\"\n\n\t\"k8s.io/klog/v2\"\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n)\n\ntype Factory func(cluster *VersionContext) (VersionClient, error)\n\nvar (\n\tmutex     sync.Mutex\n\tproviders = make(map[kstonev1alpha2.EtcdStorageBackend]Factory)\n)\n\n// RegisterEtcdClientFactory registers the specified etcd client\nfunc RegisterEtcdClientFactory(name kstonev1alpha2.EtcdStorageBackend, factory Factory) {\n\tmutex.Lock()\n\tdefer mutex.Unlock()\n\n\tif _, found := providers[name]; found {\n\t\tklog.V(2).Infof(\"etcdcluster provider %s was registered twice\", name)\n\t}\n\n\tklog.V(2).Infof(\"register etcdCluster provider %s\", name)\n\tproviders[name] = factory\n}\n\n// GetEtcdClientProvider gets the specified etcd client\nfunc GetEtcdClientProvider(\n\tname kstonev1alpha2.EtcdStorageBackend,\n\tctx *VersionContext,\n) (VersionClient, error) {\n\tmutex.Lock()\n\tdefer mutex.Unlock()\n\n\t// compatible with existing clusters\n\tif name == \"\" {\n\t\tname = kstonev1alpha2.EtcdStorageV3\n\t}\n\tf, found := providers[name]\n\n\tklog.V(1).Infof(\"get provider name %s,status:%t\", name, found)\n\tif !found {\n\t\treturn nil, errors.New(\"fatal error,etcd cluster provider not found\")\n\t}\n\treturn f(ctx)\n}\n"
  },
  {
    "path": "pkg/etcd/client/versions/providers.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage versions\n\nimport (\n\t_ \"tkestack.io/kstone/pkg/etcd/client/versions/v2\" // import etcd client of v2\n\t_ \"tkestack.io/kstone/pkg/etcd/client/versions/v3\" // import etcd client of v3\n)\n"
  },
  {
    "path": "pkg/etcd/client/versions/v2/client.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage v2\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net\"\n\t\"net/http\"\n\n\t\"github.com/coreos/etcd/pkg/transport\"\n\tclientv2 \"go.etcd.io/etcd/client/v2\"\n\tklog \"k8s.io/klog/v2\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/etcd\"\n\t\"tkestack.io/kstone/pkg/etcd/client\"\n)\n\ntype V2 struct {\n\tctx *client.VersionContext\n\tcli *clientv2.Client\n}\n\nfunc (c *V2) MemberList() ([]client.Member, error) {\n\tAPI := clientv2.NewMembersAPI(*c.cli)\n\trsp, err := API.List(context.Background())\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"load members err of endpoints:%s err:%s\",\n\t\t\tc.ctx.Config.Endpoints, err.Error())\n\t}\n\tmembers := make([]client.Member, 0)\n\tfor _, m := range rsp {\n\t\tmembers = append(members, client.Member{\n\t\t\tID:         m.ID,\n\t\t\tName:       m.Name,\n\t\t\tPeerURLs:   m.PeerURLs,\n\t\t\tClientURLs: m.ClientURLs,\n\t\t\tIsLearner:  false,\n\t\t})\n\t}\n\treturn members, nil\n}\n\nfunc (c *V2) Status(endpoint string) (*client.Member, error) {\n\tbackend, err := etcd.NewEtcdHealthCheckBackend(etcd.HealthCheckHTTP)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get version backend,method %s,err is %v\", etcd.HealthCheckHTTP, err)\n\t\treturn nil, err\n\t}\n\tconfig := c.ctx.Config\n\terr = backend.Init(config.CaCert, config.Cert, config.Key, endpoint)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to init version client,endpoint is %s,err is %v\", endpoint, err)\n\t\treturn nil, err\n\t}\n\tdefer backend.Close()\n\tvar version string\n\tversion, err = backend.Version()\n\tif err != nil {\n\t\tklog.Errorf(\"failed to version,endpoint is %s,err is %v\", endpoint, err)\n\t\treturn nil, err\n\t}\n\n\t//get leader & memberID\n\tstats, err := backend.Stats()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &client.Member{\n\t\tID:      stats.ID,\n\t\tName:    stats.Name,\n\t\tVersion: version,\n\t\tLeader:  stats.LeaderInfo.Leader,\n\t}, nil\n}\n\nfunc (c *V2) Close() {}\n\nfunc init() {\n\tclient.RegisterEtcdClientFactory(kstonev1alpha2.EtcdStorageV2,\n\t\tfunc(ctx *client.VersionContext) (client.VersionClient, error) {\n\t\t\treturn initClient(ctx)\n\t\t})\n}\n\nfunc newClientCfg(ctx *client.VersionContext) (*clientv2.Config, error) {\n\tconfig := ctx.Config\n\tcfg := &clientv2.Config{\n\t\tEndpoints: config.Endpoints,\n\t\tUsername:  config.Username,\n\t\tPassword:  config.Password,\n\t}\n\tvar cfgtls *transport.TLSInfo\n\ttlsinfo := transport.TLSInfo{}\n\tif ctx.Config.Cert != \"\" {\n\t\ttlsinfo.CertFile = config.Cert\n\t\tcfgtls = &tlsinfo\n\t}\n\n\tif config.Key != \"\" {\n\t\ttlsinfo.KeyFile = config.Key\n\t\tcfgtls = &tlsinfo\n\t}\n\n\tif config.CaCert != \"\" {\n\t\ttlsinfo.TrustedCAFile = config.CaCert\n\t\tcfgtls = &tlsinfo\n\t}\n\n\tif cfgtls != nil {\n\t\tclientTLS, err := cfgtls.ClientConfig()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tcfg.Transport = &http.Transport{\n\t\t\tDial: (&net.Dialer{\n\t\t\t\tTimeout:   config.DialKeepAliveTimeout,\n\t\t\t\tKeepAlive: config.DialKeepAliveTime,\n\t\t\t}).Dial,\n\t\t\tTLSHandshakeTimeout: config.DialTimeout,\n\t\t\tTLSClientConfig:     clientTLS,\n\t\t\tMaxIdleConnsPerHost: 1,\n\t\t\tDisableKeepAlives:   true,\n\t\t}\n\t}\n\treturn cfg, nil\n}\n\nfunc initClient(ctx *client.VersionContext) (client.VersionClient, error) {\n\tclient := &V2{\n\t\tctx: ctx,\n\t\tcli: nil,\n\t}\n\tcfg, err := newClientCfg(ctx)\n\tif err != nil {\n\t\tklog.Errorf(\"get new clientv2 cfg failed:%s\", err)\n\t\treturn nil, err\n\t}\n\n\tcli, err := clientv2.New(*cfg)\n\tif err != nil {\n\t\tklog.Errorf(\"create new clientv2 failed:%s\", err)\n\t\treturn nil, err\n\t}\n\tklog.V(2).Infof(\"init client ready of:%s\", ctx.Config.Endpoints)\n\tclient.cli = &cli\n\treturn client, nil\n}\n"
  },
  {
    "path": "pkg/etcd/client/versions/v3/client.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage v3\n\nimport (\n\t\"strconv\"\n\n\tclientv3 \"go.etcd.io/etcd/client/v3\"\n\t\"k8s.io/klog/v2\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/etcd\"\n\t\"tkestack.io/kstone/pkg/etcd/client\"\n)\n\ntype V3 struct {\n\tctx *client.VersionContext\n\tcli *clientv3.Client\n}\n\nfunc (c *V3) MemberList() ([]client.Member, error) {\n\tmembers := make([]client.Member, 0)\n\tmemberRsp, err := etcd.MemberList(c.cli)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get member list, endpoints is %s,err is %v\", c.ctx.Config.Endpoints, err)\n\t\treturn members, err\n\t}\n\tfor _, m := range memberRsp.Members {\n\t\tmembers = append(members, client.Member{\n\t\t\tID:         strconv.FormatUint(m.ID, 10),\n\t\t\tName:       m.Name,\n\t\t\tPeerURLs:   m.PeerURLs,\n\t\t\tClientURLs: m.ClientURLs,\n\t\t\tIsLearner:  m.IsLearner,\n\t\t})\n\t}\n\treturn members, nil\n}\n\nfunc (c *V3) Status(endpoint string) (*client.Member, error) {\n\tstatusRsp, err := etcd.Status(c.ctx.Config.Endpoints[0], c.cli)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &client.Member{\n\t\tVersion:   statusRsp.Version,\n\t\tIsLearner: statusRsp.IsLearner,\n\t\tLeader:    strconv.FormatUint(statusRsp.Leader, 10),\n\t}, nil\n}\n\nfunc (c *V3) Close() {\n\tc.cli.Close()\n}\n\nfunc init() {\n\tclient.RegisterEtcdClientFactory(kstonev1alpha2.EtcdStorageV3,\n\t\tfunc(ctx *client.VersionContext) (client.VersionClient, error) {\n\t\t\treturn initClient(ctx)\n\t\t})\n}\n\nfunc initClient(ctx *client.VersionContext) (client.VersionClient, error) {\n\tclient := &V3{\n\t\tctx: ctx,\n\t\tcli: nil,\n\t}\n\tvar err error\n\tclient.cli, err = etcd.NewClientv3(ctx.Config)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get new etcd clientv3,err is %v \", err)\n\t\treturn nil, err\n\t}\n\treturn client, nil\n}\n"
  },
  {
    "path": "pkg/etcd/client.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage etcd\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"strings\"\n\t\"time\"\n\n\tv1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n\tlisterscorev1 \"k8s.io/client-go/listers/core/v1\"\n\t\"k8s.io/klog/v2\"\n\n\t\"tkestack.io/kstone/pkg/controllers/util\"\n)\n\ntype ClientConfigGetter interface {\n\tNew(path string, sc string) (*ClientConfig, error)\n}\n\ntype ClientConfigSecret struct {\n\tkubeCli      kubernetes.Interface\n\tsecretLister listerscorev1.SecretLister\n\tsecretGetter func(t *ClientConfigSecret, namespace, secretName string) (*v1.Secret, error)\n}\n\ntype ClientConfig struct {\n\t// Endpoints is a list of URLs.\n\tEndpoints []string\n\n\t// DialTimeout is the timeout for failing to establish a connection.\n\tDialTimeout time.Duration\n\n\t// DialKeepAliveTime is the time after which client pings the server to see if\n\t// transport is alive.\n\tDialKeepAliveTime time.Duration\n\n\t// DialKeepAliveTimeout is the time that the client waits for a response for the\n\t// keep-alive probe. If the response is not received in this time, the connection is closed.\n\tDialKeepAliveTimeout time.Duration\n\n\t// SecureConfig is secure config for authentication\n\tSecureConfig\n}\n\ntype SecureConfig struct {\n\t// Cert is a cert for authentication.\n\tCert string\n\n\t// Key is a key for authentication.\n\tKey string\n\n\t// CaCert is a CA cert for authentication.\n\tCaCert string\n\n\t// Username is a user name for authentication.\n\tUsername string\n\n\t// Password is a password for authentication.\n\tPassword string\n}\n\nfunc NewClientConfigSecretGetter(clientBuilder util.ClientBuilder) *ClientConfigSecret {\n\treturn &ClientConfigSecret{\n\t\tkubeCli:      clientBuilder.ClientOrDie(),\n\t\tsecretGetter: Secret,\n\t}\n}\n\nfunc NewClientConfigSecretCacheGetter(secretLister listerscorev1.SecretLister) *ClientConfigSecret {\n\treturn &ClientConfigSecret{\n\t\tsecretLister: secretLister,\n\t\tsecretGetter: SecretCache,\n\t}\n}\n\nfunc (t *ClientConfigSecret) New(path string, sc string) (*ClientConfig, error) {\n\tif sc == \"\" {\n\t\treturn &ClientConfig{}, nil\n\t}\n\titems := strings.Split(sc, \"/\")\n\tpaths := strings.Split(path, \"/\")\n\tnamespace := \"default\"\n\tif len(paths) == 2 {\n\t\tnamespace = paths[0]\n\t}\n\tsecretName := sc\n\tif len(items) > 2 {\n\t\treturn nil, errors.New(\"invalid secretname\")\n\t} else if len(items) == 2 {\n\t\tnamespace = items[0]\n\t\tsecretName = items[1]\n\t}\n\tvar secret *v1.Secret\n\tvar err error\n\tsecret, err = t.secretGetter(t, namespace, secretName)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get secret, namespace is %s, secret name is %s\", namespace, secretName)\n\t\treturn nil, err\n\t}\n\n\tcert := secret.Data[CliCertFile]\n\tkey := secret.Data[CliKeyFile]\n\tca := secret.Data[CliCAFile]\n\tusername := secret.Data[CliUsername]\n\tpassword := secret.Data[CliPassword]\n\tcaFile, certFile, keyFile, err := GetTLSConfigPath(path, cert, key, ca)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get tls config path, name %s,err is %v\", secretName, err)\n\t\treturn nil, err\n\t}\n\treturn &ClientConfig{\n\t\tSecureConfig: SecureConfig{\n\t\t\tCaCert:   caFile,\n\t\t\tCert:     certFile,\n\t\t\tKey:      keyFile,\n\t\t\tUsername: string(username),\n\t\t\tPassword: string(password),\n\t\t},\n\t}, nil\n}\n\nfunc SecretCache(t *ClientConfigSecret, namespace, secretName string) (*v1.Secret, error) {\n\treturn t.secretLister.Secrets(namespace).Get(secretName)\n}\n\nfunc Secret(t *ClientConfigSecret, namespace, secretName string) (*v1.Secret, error) {\n\treturn t.kubeCli.CoreV1().Secrets(namespace).Get(context.TODO(), secretName, metav1.GetOptions{})\n}\n"
  },
  {
    "path": "pkg/etcd/encoding.go",
    "content": "/*\nCopyright 2017 The Kubernetes Authors.\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    http://www.apache.org/licenses/LICENSE-2.0\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 etcd\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\n\t\"go.etcd.io/etcd/api/v3/mvccpb\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\tjsonserializer \"k8s.io/apimachinery/pkg/runtime/serializer/json\"\n\tklog \"k8s.io/klog/v2\"\n\tkubectlScheme \"k8s.io/kubectl/pkg/scheme\"\n\t\"sigs.k8s.io/yaml\"\n)\n\nconst (\n\tStorageBinaryMediaType = \"application/vnd.kubernetes.storagebinary\"\n\tProtobufMediaType      = \"application/vnd.kubernetes.protobuf\"\n\tYamlMediaType          = \"application/yaml\"\n\tJSONMediaType          = \"application/json\"\n\n\tProtobufShortname = \"proto\"\n\tYamlShortname     = \"yaml\"\n\tJSONShortname     = \"json\"\n)\n\n// ProtoEncodingPrefix ... see k8s.io/apimachinery/pkg/runtime/serializer/protobuf.go\nvar ProtoEncodingPrefix = []byte{0x6b, 0x38, 0x73, 0x00}\n\nvar MediaTypeList = []string{JSONMediaType, YamlMediaType}\n\nvar MediaTypeMap = map[string]string{\n\t\"raw\":                  StorageBinaryMediaType,\n\tProtobufShortname:      ProtobufMediaType,\n\tYamlShortname:          YamlMediaType,\n\tJSONShortname:          JSONMediaType,\n\tStorageBinaryMediaType: \"raw\",\n\tProtobufMediaType:      ProtobufShortname,\n\tYamlMediaType:          YamlShortname,\n\tJSONMediaType:          JSONShortname,\n}\n\nvar Codecs = kubectlScheme.Codecs\n\n// ConvertToData converts content input to data with inMediaType\nfunc ConvertToData(inMediaType string, in []byte) (map[string]string, error) {\n\tdata := make(map[string]string)\n\tfor _, outMediaType := range MediaTypeList {\n\t\tif inMediaType == StorageBinaryMediaType && outMediaType == ProtobufMediaType {\n\t\t\tdata[MediaTypeMap[outMediaType]] = DecodeRawToString(in)\n\t\t\tcontinue\n\t\t}\n\n\t\tif inMediaType == ProtobufMediaType && outMediaType == StorageBinaryMediaType {\n\t\t\treturn nil, fmt.Errorf(\"unsupported conversion: protobuf to kubernetes binary storage representation\")\n\t\t}\n\n\t\ttypeMeta, err := decodeTypeMeta(inMediaType, in)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tvar encoded []byte\n\t\tif inMediaType == outMediaType {\n\t\t\t// Assumes that the stored version is \"correct\". Primarily a short cut to allow CRDs to work.\n\t\t\tencoded = in\n\t\t\tif outMediaType == JSONMediaType {\n\t\t\t\tencoded = append(encoded, '\\n')\n\t\t\t}\n\t\t} else {\n\t\t\tinCodec, err := newCodec(typeMeta, inMediaType)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\toutCodec, err := newCodec(typeMeta, outMediaType)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tobj, err := runtime.Decode(inCodec, in)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"error decoding from %s: %s\", inMediaType, err)\n\t\t\t}\n\n\t\t\tencoded, err = runtime.Encode(outCodec, obj)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"error encoding to %s: %s\", outMediaType, err)\n\t\t\t}\n\t\t}\n\t\tdata[MediaTypeMap[outMediaType]] = string(encoded)\n\t}\n\treturn data, nil\n}\n\n// DetectAndExtract searches the start of either json of protobuf data, and, if found, returns the mime type and data.\nfunc DetectAndExtract(in []byte) (string, []byte, error) {\n\tif pb, ok := tryFindProto(in); ok {\n\t\treturn StorageBinaryMediaType, pb, nil\n\t}\n\tif rawJs, ok := tryFindJSON(in); ok {\n\t\tjs, err := rawJs.MarshalJSON()\n\t\tif err != nil {\n\t\t\treturn \"\", nil, err\n\t\t}\n\t\treturn JSONMediaType, js, nil\n\t}\n\treturn \"\", nil, fmt.Errorf(\"error reading input, does not appear to contain valid JSON or binary data\")\n}\n\n// tryFindProto searches for the 'k8s\\0' prefix, and, if found, returns the data starting with the prefix.\nfunc tryFindProto(in []byte) ([]byte, bool) {\n\ti := bytes.Index(in, ProtoEncodingPrefix)\n\tif i >= 0 && i < len(in) {\n\t\treturn in[i:], true\n\t}\n\treturn nil, false\n}\n\nconst jsonStartChars = \"{[\"\n\n// tryFindJSON searches for the start of a valid json substring, and, if found, returns the json.\nfunc tryFindJSON(in []byte) (*json.RawMessage, bool) {\n\tvar js json.RawMessage\n\n\ti := bytes.IndexAny(in, jsonStartChars)\n\tfor i >= 0 && i < len(in) {\n\t\tin = in[i:]\n\t\tif len(in) < 2 {\n\t\t\tbreak\n\t\t}\n\t\terr := json.Unmarshal(in, &js)\n\t\tif err == nil {\n\t\t\treturn &js, true\n\t\t}\n\t\tin = in[1:]\n\t\ti = bytes.IndexAny(in, jsonStartChars)\n\t}\n\treturn nil, false\n}\n\n// DecodeRawToString decodes the raw payload bytes contained within the 'Unknown' protobuf envelope of\n// the given storage data.\nfunc DecodeRawToString(in []byte) string {\n\tunknown, err := DecodeUnknown(in)\n\tif err != nil {\n\t\treturn \"\"\n\t}\n\n\treturn string(unknown.Raw)\n}\n\n// DecodeUnknown decodes the Unknown protobuf type from the given storage data.\nfunc DecodeUnknown(in []byte) (*runtime.Unknown, error) {\n\tif len(in) < 4 {\n\t\treturn nil, fmt.Errorf(\"input too short, expected 4 byte proto encoding prefix but got %v\", in)\n\t}\n\tif !bytes.Equal(in[:4], ProtoEncodingPrefix) {\n\t\treturn nil, fmt.Errorf(\"first 4 bytes %v, do not match proto encoding prefix of %v\", in[:4], ProtoEncodingPrefix)\n\t}\n\tdata := in[4:]\n\n\tunknown := &runtime.Unknown{}\n\tif err := unknown.Unmarshal(data); err != nil {\n\t\treturn nil, err\n\t}\n\treturn unknown, nil\n}\n\n// newCodec creates a new kubernetes storage codec for encoding and decoding persisted data.\nfunc newCodec(typeMeta *runtime.TypeMeta, mediaType string) (runtime.Codec, error) {\n\t// For api machinery purposes, we treat StorageBinaryMediaType as ProtobufMediaType\n\tif mediaType == StorageBinaryMediaType {\n\t\tmediaType = ProtobufMediaType\n\t}\n\tmediaTypes := Codecs.SupportedMediaTypes()\n\n\tinfo, ok := runtime.SerializerInfoForMediaType(mediaTypes, mediaType)\n\tif !ok {\n\t\tif len(mediaTypes) == 0 {\n\t\t\treturn nil, fmt.Errorf(\"no serializers registered for %v\", mediaTypes)\n\t\t}\n\t\tinfo = mediaTypes[0]\n\t}\n\tgv, err := schema.ParseGroupVersion(typeMeta.APIVersion)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to parse meta APIVersion '%s': %s\", typeMeta.APIVersion, err)\n\t}\n\tencoder := Codecs.EncoderForVersion(info.Serializer, gv)\n\tdecoder := Codecs.DecoderToVersion(info.Serializer, gv)\n\tcodec := Codecs.CodecForVersions(encoder, decoder, gv, gv)\n\treturn codec, nil\n}\n\n// decodeTypeMeta gets the TypeMeta from the given data, either as JSON or Protobuf.\nfunc decodeTypeMeta(inMediaType string, in []byte) (*runtime.TypeMeta, error) {\n\tswitch inMediaType {\n\tcase JSONMediaType:\n\t\treturn typeMetaFromJSON(in)\n\tcase StorageBinaryMediaType:\n\t\treturn typeMetaFromBinaryStorage(in)\n\tcase YamlMediaType:\n\t\treturn typeMetaFromYaml(in)\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unsupported inMediaType %s\", inMediaType)\n\t}\n}\n\n// typeMetaFromJSON generates type for json\nfunc typeMetaFromJSON(in []byte) (*runtime.TypeMeta, error) {\n\tvar meta runtime.TypeMeta\n\terr := json.Unmarshal(in, &meta)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &meta, nil\n}\n\n// typeMetaFromBinaryStorage generates type for binary storage\nfunc typeMetaFromBinaryStorage(in []byte) (*runtime.TypeMeta, error) {\n\tunknown, err := DecodeUnknown(in)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &unknown.TypeMeta, nil\n}\n\n// typeMetaFromYaml generates type for yaml\nfunc typeMetaFromYaml(in []byte) (*runtime.TypeMeta, error) {\n\tvar meta runtime.TypeMeta\n\terr := yaml.Unmarshal(in, &meta)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &meta, nil\n}\n\n// ConvertToJSON converts kv to json string\nfunc ConvertToJSON(kv *mvccpb.KeyValue) string {\n\tdecoder := kubectlScheme.Codecs.UniversalDeserializer()\n\tencoder := jsonserializer.NewSerializer(\n\t\tjsonserializer.DefaultMetaFactory,\n\t\tkubectlScheme.Scheme,\n\t\tkubectlScheme.Scheme,\n\t\tfalse,\n\t)\n\tobjJSON := &bytes.Buffer{}\n\n\tobj, _, err := decoder.Decode(kv.Value, nil, nil)\n\tif err != nil {\n\t\tklog.Errorf(\"WARN: error decoding value %s: %v\", string(kv.Value), err)\n\t\treturn string(kv.Value)\n\t}\n\tobjJSON.Reset()\n\tif err := encoder.Encode(obj, objJSON); err != nil {\n\t\tklog.Errorf(\"WARN: error encoding object %#v as JSON: %v\", obj, err)\n\t\treturn string(kv.Value)\n\t}\n\treturn objJSON.String()\n}\n"
  },
  {
    "path": "pkg/etcd/health.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage etcd\n\nimport (\n\t\"crypto/tls\"\n\t\"crypto/x509\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"time\"\n\n\tklog \"k8s.io/klog/v2\"\n)\n\ntype Health interface {\n\n\t// Init creates etcd healthcheck client\n\tInit(ca, cert, key, endpoint string) error\n\n\t// IsHealthy checks etcd health info\n\tIsHealthy() error\n\n\t// Version returns etcd version\n\tVersion() (string, error)\n\n\t// Stats returns etcd status\n\tStats() (*Stats, error)\n\n\t// Close closes etcd healthcheck client\n\tClose() error\n}\n\ntype HealthCheckMethod string\n\nconst (\n\tHealthCheckHTTP    HealthCheckMethod = \"http\"\n\tHealthCheckEtcdctl HealthCheckMethod = \"etcdctl\"\n)\n\n// HealthCheckHTTPClient struct of etcd healthcheck client\ntype HealthCheckHTTPClient struct {\n\tmethod   HealthCheckMethod\n\tcli      *http.Client\n\tendpoint string\n}\n\n// NewEtcdHealthCheckBackend generates etcd healthcheck client\nfunc NewEtcdHealthCheckBackend(method HealthCheckMethod) (Health, error) {\n\tif method == HealthCheckHTTP {\n\t\treturn &HealthCheckHTTPClient{method: HealthCheckHTTP}, nil\n\t}\n\treturn nil, errors.New(\"invalid health check method\")\n}\n\n// Init creates etcd healthcheck client\nfunc (c *HealthCheckHTTPClient) Init(ca, cert, key, endpoint string) error {\n\tc.endpoint = endpoint\n\ttr := &http.Transport{}\n\ttr.MaxIdleConns = 1\n\ttr.DisableKeepAlives = true\n\tif ca != \"\" && cert != \"\" && key != \"\" {\n\t\tcaCert, err := ioutil.ReadFile(ca)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tkeyPair, err := tls.LoadX509KeyPair(cert, key)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tcaPool := x509.NewCertPool()\n\t\tcaPool.AppendCertsFromPEM(caCert)\n\n\t\ttlsConfig := &tls.Config{\n\t\t\tCertificates: []tls.Certificate{keyPair},\n\t\t\tRootCAs:      caPool,\n\t\t}\n\t\ttlsConfig.BuildNameToCertificate()\n\t\ttlsConfig.InsecureSkipVerify = true\n\t\ttr.TLSClientConfig = tlsConfig\n\t}\n\tc.cli = &http.Client{Transport: tr, Timeout: time.Second * 3}\n\treturn nil\n}\n\n// etcdHealth encodes data returned from etcd /healthz handler.\ntype etcdHealth struct {\n\t// Note this has to be public so the json library can modify it.\n\tHealth string `json:\"health\"`\n}\n\n// etcdHealthCheck decodes data returned from etcd /healthz handler.\nfunc (c *HealthCheckHTTPClient) etcdHealthCheck(data []byte) error {\n\tobj := etcdHealth{}\n\tif err := json.Unmarshal(data, &obj); err != nil {\n\t\treturn err\n\t}\n\tif obj.Health != \"true\" {\n\t\tklog.Warningf(\"etcd is not healthy,endpoint is %s\", c.endpoint)\n\t\treturn fmt.Errorf(\"Unhealthy status: %s\", obj.Health)\n\t}\n\treturn nil\n}\n\n// IsHealthy returns etcd healthy info by access etcd endpoint\nfunc (c *HealthCheckHTTPClient) IsHealthy() error {\n\ttarget := fmt.Sprintf(\"%s/health\", c.endpoint)\n\tresp, err := c.cli.Get(target)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to check etcd healthy,err is %v\", err)\n\t\treturn err\n\t}\n\tdefer resp.Body.Close()\n\tbody, _ := ioutil.ReadAll(resp.Body)\n\treturn c.etcdHealthCheck(body)\n}\n\nfunc (c *HealthCheckHTTPClient) GetByAPI(path string) ([]byte, error) {\n\ttarget := fmt.Sprintf(\"%s/%s\", c.endpoint, path)\n\tresp, err := c.cli.Get(target)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to check etcd healthy,err is %v\", err)\n\t\treturn make([]byte, 0), err\n\t}\n\tdefer resp.Body.Close()\n\treturn ioutil.ReadAll(resp.Body)\n}\n\ntype Version struct {\n\tEtcdServer string `json:\"etcdserver\"`\n}\n\nfunc (c *HealthCheckHTTPClient) Version() (string, error) {\n\tbody, err := c.GetByAPI(\"version\")\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"send request failed:%s\", err.Error())\n\t}\n\tvar version Version\n\terr = json.Unmarshal(body, &version)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"version result json failed:%s, body:%s\", err.Error(), string(body))\n\t}\n\treturn version.EtcdServer, nil\n}\n\ntype Stats struct {\n\tName       string `json:\"name\"`\n\tID         string `json:\"id\"`\n\tLeaderInfo struct {\n\t\tLeader string `json:\"leader\"`\n\t} `json:\"leaderInfo\"`\n}\n\nfunc (c *HealthCheckHTTPClient) Stats() (*Stats, error) {\n\tbody, err := c.GetByAPI(\"v2/stats/self\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"send request failed:%s\", err.Error())\n\t}\n\tvar stats Stats\n\terr = json.Unmarshal(body, &stats)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"version result json failed:%s, body:%s\", err.Error(), string(body))\n\t}\n\treturn &stats, nil\n}\n\n// Close closes etcd healthcheck client\nfunc (c *HealthCheckHTTPClient) Close() error {\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/etcd/helper.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage etcd\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"net\"\n\t\"net/http\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n\t\"go.etcd.io/etcd/client/pkg/v3/transport\"\n\tclientv2 \"go.etcd.io/etcd/client/v2\"\n\tclientv3 \"go.etcd.io/etcd/client/v3\"\n\tklog \"k8s.io/klog/v2\"\n)\n\nconst (\n\tDefaultDialTimeout      = 3 * time.Second\n\tDefaultCommandTimeOut   = 10 * time.Second\n\tDefaultKeepAliveTime    = 10 * time.Second\n\tDefaultKeepAliveTimeOut = 30 * time.Second\n\n\tCliCertFile = \"client.pem\"\n\tCliKeyFile  = \"client-key.pem\"\n\tCliCAFile   = \"ca.pem\"\n\tCliUsername = \"username\"\n\tCliPassword = \"password\"\n)\n\n// NewClientv3 generates etcd client v3\nfunc NewClientv3(config *ClientConfig) (*clientv3.Client, error) {\n\tsetDefaultConfig(config)\n\tcfg, err := newClientv3Config(config)\n\tif err != nil {\n\t\tklog.Errorf(\"get new clientv3 cfg failed:%s\", err)\n\t\treturn nil, err\n\t}\n\n\tclient, err := clientv3.New(*cfg)\n\tif err != nil {\n\t\tklog.Errorf(\"create new clientv3 failed:%s\", err)\n\t\treturn nil, err\n\t}\n\n\treturn client, nil\n}\n\nfunc setDefaultConfig(config *ClientConfig) {\n\tif config.DialTimeout == 0 {\n\t\tconfig.DialTimeout = DefaultDialTimeout\n\t}\n\tif config.DialKeepAliveTime == 0 {\n\t\tconfig.DialKeepAliveTime = DefaultKeepAliveTime\n\t}\n\tif config.DialKeepAliveTimeout == 0 {\n\t\tconfig.DialKeepAliveTimeout = DefaultKeepAliveTimeOut\n\t}\n}\n\n// newClientv3Config generates config of etcd client v3\nfunc newClientv3Config(config *ClientConfig) (*clientv3.Config, error) {\n\tcfg := &clientv3.Config{\n\t\tEndpoints:            config.Endpoints,\n\t\tDialTimeout:          config.DialTimeout,\n\t\tDialKeepAliveTime:    config.DialKeepAliveTime,\n\t\tDialKeepAliveTimeout: config.DialKeepAliveTimeout,\n\t\tUsername:             config.Username,\n\t\tPassword:             config.Password,\n\t}\n\t// set tls if any one tls option set\n\tvar cfgtls *transport.TLSInfo\n\ttlsinfo := transport.TLSInfo{}\n\tif config.Cert != \"\" {\n\t\ttlsinfo.CertFile = config.Cert\n\t\tcfgtls = &tlsinfo\n\t}\n\n\tif config.Key != \"\" {\n\t\ttlsinfo.KeyFile = config.Key\n\t\tcfgtls = &tlsinfo\n\t}\n\n\tif config.CaCert != \"\" {\n\t\ttlsinfo.TrustedCAFile = config.CaCert\n\t\tcfgtls = &tlsinfo\n\t}\n\n\tif cfgtls != nil {\n\t\tclientTLS, err := cfgtls.ClientConfig()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tcfg.TLS = clientTLS\n\t\tcfg.TLS.InsecureSkipVerify = true\n\n\t}\n\n\treturn cfg, nil\n}\n\n// MemberList gets etcd members\nfunc MemberList(cli *clientv3.Client) (*clientv3.MemberListResponse, error) {\n\tctx, cancel := context.WithTimeout(context.Background(), DefaultDialTimeout)\n\tdefer cancel()\n\n\trsp, err := cli.MemberList(ctx)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get member list,err is %v\", err)\n\t\treturn nil, err\n\t}\n\tklog.V(6).Infof(\"get member list succ,resp info %v\", rsp)\n\treturn rsp, err\n}\n\n// Status returns new status\nfunc Status(endpoint string, cli *clientv3.Client) (*clientv3.StatusResponse, error) {\n\tctx, cancel := context.WithTimeout(context.Background(), DefaultDialTimeout)\n\tdefer cancel()\n\n\treturn cli.Status(ctx, endpoint)\n}\n\n// writeFile writes []bytes to file\nfunc writeFile(dir, file string, data []byte) (string, error) {\n\tp := filepath.Join(dir, file)\n\treturn p, ioutil.WriteFile(p, data, 0600)\n}\n\nfunc GetTLSConfigPath(clusterName string, certData, keyData, caData []byte) (string, string, string, error) {\n\t// empty tlsFiles, return \"\"\n\tif len(certData) == 0 || len(keyData) == 0 || len(caData) == 0 {\n\t\treturn \"\", \"\", \"\", nil\n\t}\n\n\tdir, err := ioutil.TempDir(\"\", strings.ReplaceAll(clusterName, \"/\", \"_\"))\n\tif err != nil {\n\t\treturn \"\", \"\", \"\", err\n\t}\n\n\tcertFile, err := writeFile(dir, CliCertFile, certData)\n\tif err != nil {\n\t\treturn \"\", \"\", \"\", err\n\t}\n\tkeyFile, err := writeFile(dir, CliKeyFile, keyData)\n\tif err != nil {\n\t\treturn \"\", \"\", \"\", err\n\t}\n\tcaFile, err := writeFile(dir, CliCAFile, caData)\n\tif err != nil {\n\t\treturn \"\", \"\", \"\", err\n\t}\n\treturn caFile, certFile, keyFile, nil\n}\n\nfunc AddMemberWithCmd(isLearner bool, endpoints, peerURL, ca, cert, key string) error {\n\targs := make([]string, 0)\n\tif ca != \"\" && cert != \"\" && key != \"\" {\n\t\targs = append(args, fmt.Sprintf(\"--cacert=%s\", ca))\n\t\targs = append(args, fmt.Sprintf(\"--cert=%s\", cert))\n\t\targs = append(args, fmt.Sprintf(\"--key=%s\", key))\n\t}\n\n\tendpointsStr := fmt.Sprintf(\"--endpoints=%s\", endpoints)\n\tpeerUlrStr := fmt.Sprintf(\"--peer-urls=%s\", peerURL)\n\tisLearnerStr := fmt.Sprintf(\"--learner=%v\", isLearner)\n\n\tname := strings.Split(strings.Split(peerURL, \":\")[1], \"/\")[2]\n\n\targs = append(args, endpointsStr)\n\targs = append(args, \"member\")\n\targs = append(args, \"add\")\n\targs = append(args, name)\n\targs = append(args, peerUlrStr)\n\targs = append(args, isLearnerStr)\n\n\tcmd := exec.Command(\"etcdctl\", args...)\n\toutput, err := cmd.Output()\n\tif err != nil {\n\t\tfmt.Printf(\"Execute Shell:%s failed with error:%s\", cmd, err.Error())\n\t\treturn err\n\t}\n\tfmt.Printf(\"Execute Shell:%s finished with output:\\n%s\", cmd, string(output))\n\treturn nil\n}\n\n// MemberHealthy checks healthy of member\nfunc MemberHealthy(endpoint string, cli *ClientConfig) (bool, error) {\n\tbackend, err := NewEtcdHealthCheckBackend(HealthCheckHTTP)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get healthcheck backend,method %s,err is %v\", HealthCheckHTTP, err)\n\t\treturn false, err\n\t}\n\terr = backend.Init(cli.CaCert, cli.Cert, cli.Key, endpoint)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to init healthcheck client,endpoint is %s,err is %v\", endpoint, err)\n\t\treturn false, err\n\t}\n\tdefer backend.Close()\n\terr = backend.IsHealthy()\n\tif err != nil {\n\t\tklog.Errorf(\"unhealthy,endpoint is %s,err is %v\", endpoint, err)\n\t\treturn false, nil\n\t}\n\treturn true, nil\n}\n\nfunc NewShortConnectionClientv2(config *ClientConfig) (*clientv2.Client, error) {\n\tsetDefaultConfig(config)\n\tcfg, err := newClientv2Config(config)\n\tif err != nil {\n\t\tklog.Errorf(\"get new clientv2 cfg failed:%s\", err)\n\t\treturn nil, err\n\t}\n\n\tclient, err := clientv2.New(*cfg)\n\tif err != nil {\n\t\tklog.Errorf(\"create new clientv2 failed:%s\", err)\n\t\treturn nil, err\n\t}\n\n\treturn &client, nil\n}\n\n// newClientv2Config generates config of etcd client v2\nfunc newClientv2Config(config *ClientConfig) (*clientv2.Config, error) {\n\ttr, err := getTransport(config.DialTimeout, DefaultCommandTimeOut, config.SecureConfig, true)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &clientv2.Config{\n\t\tTransport:               tr,\n\t\tEndpoints:               config.Endpoints,\n\t\tHeaderTimeoutPerRequest: config.DialTimeout,\n\t\tUsername:                config.Username,\n\t\tPassword:                config.Password,\n\t}, nil\n}\n\n// getTransport gets *http.Transport\nfunc getTransport(dialTimeout, totalTimeout time.Duration, scfg SecureConfig, short bool) (*http.Transport, error) {\n\tcafile := scfg.CaCert\n\tcertfile := scfg.Cert\n\tkeyfile := scfg.Key\n\n\ttls := transport.TLSInfo{\n\t\tCertFile:           certfile,\n\t\tKeyFile:            keyfile,\n\t\tTrustedCAFile:      cafile,\n\t\tInsecureSkipVerify: true,\n\t}\n\n\tif totalTimeout != 0 && totalTimeout < dialTimeout {\n\t\tdialTimeout = totalTimeout\n\t}\n\tif !short {\n\t\treturn transport.NewTransport(tls, dialTimeout)\n\t}\n\tconfig, err := tls.ClientConfig()\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get etcd server config,err is %v\", err)\n\t\treturn nil, err\n\t}\n\treturn &http.Transport{\n\t\tDial: (&net.Dialer{\n\t\t\tTimeout:   DefaultDialTimeout,\n\t\t\tKeepAlive: DefaultKeepAliveTime,\n\t\t}).Dial,\n\t\tTLSHandshakeTimeout: DefaultDialTimeout,\n\t\tTLSClientConfig:     config,\n\t\tMaxIdleConnsPerHost: 1,\n\t\tDisableKeepAlives:   true,\n\t}, nil\n}\n\n// AlarmList list etcd alarm\nfunc AlarmList(cli *clientv3.Client) (*clientv3.AlarmResponse, error) {\n\tctx, cancel := context.WithTimeout(context.Background(), DefaultDialTimeout)\n\tdefer cancel()\n\n\trsp, err := cli.AlarmList(ctx)\n\tif err != nil {\n\t\tklog.Errorf(\"failed list etcd alarm,err is %v\", err)\n\t\treturn rsp, err\n\t}\n\tklog.V(6).Infof(\"list etcd alarm succ,resp info %v\", rsp)\n\treturn rsp, err\n}\n"
  },
  {
    "path": "pkg/etcd/stats.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage etcd\n\nimport (\n\t\"context\"\n\t\"errors\"\n\n\tclientv2 \"go.etcd.io/etcd/client/v2\"\n\tclientv3 \"go.etcd.io/etcd/client/v3\"\n\t\"k8s.io/klog/v2\"\n\n\tfeatureutil \"tkestack.io/kstone/pkg/featureprovider/util\"\n)\n\nconst (\n\tEtcdV2Backend = \"v2\"\n\tEtcdV3Backend = \"v3\"\n)\n\ntype Stat interface {\n\n\t// Init create etcd client\n\tInit(config *ClientConfig) error\n\n\t// GetTotalKeyNum counts the number of total keys\n\tGetTotalKeyNum(ctx context.Context, keyPrefix string) (uint64, error)\n\n\t// GetIndex gets the etcd metadata index\n\tGetIndex(ctx context.Context, endpoint string) (map[featureutil.ConsistencyType]uint64, error)\n\n\t// Close close etcd client\n\tClose() error\n}\n\ntype StatV3 struct {\n\tbackendName string\n\tcli         *clientv3.Client\n}\n\ntype StatV2 struct {\n\tbackendName string\n\tcli         *clientv2.Client\n}\n\nfunc NewEtcdStatBackend(storageBackend string) (Stat, error) {\n\tif storageBackend == EtcdV2Backend {\n\t\treturn &StatV2{backendName: storageBackend}, nil\n\t} else if storageBackend == EtcdV3Backend {\n\t\treturn &StatV3{backendName: storageBackend}, nil\n\t} else {\n\t\treturn nil, errors.New(\"invalid storageBackend\")\n\t}\n}\n\nfunc (c *StatV3) Init(config *ClientConfig) error {\n\tvar err error\n\tc.cli, err = NewClientv3(config)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc (c *StatV3) GetTotalKeyNum(ctx context.Context, keyPrefix string) (uint64, error) {\n\trsp, err := c.cli.Get(ctx, keyPrefix, clientv3.WithPrefix(), clientv3.WithCountOnly())\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get etcdcluster total key num,err is %v\", err)\n\t\treturn 0, err\n\t}\n\ttotalKeyNum := rsp.Count\n\tklog.V(2).Infof(\"finished to get etcdcluster total key num %d\", totalKeyNum)\n\treturn uint64(totalKeyNum), nil\n}\n\nfunc (c *StatV3) GetIndex(ctx context.Context, endpoint string) (map[featureutil.ConsistencyType]uint64, error) {\n\tmetadata := make(map[featureutil.ConsistencyType]uint64, 4)\n\tstatusRsp, err := c.cli.Status(ctx, endpoint)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get etcdcluster index,err is %v\", err)\n\t\treturn nil, err\n\t}\n\tmetadata[featureutil.ConsistencyRevision] = uint64(statusRsp.Header.Revision)\n\tmetadata[featureutil.ConsistencyRaftRaftAppliedIndex] = statusRsp.RaftAppliedIndex\n\tmetadata[featureutil.ConsistencyRaftIndex] = statusRsp.RaftIndex\n\treturn metadata, nil\n}\n\nfunc (c *StatV3) Close() error {\n\treturn c.cli.Close()\n}\n\nfunc (c *StatV2) Init(config *ClientConfig) error {\n\tvar err error\n\tc.cli, err = NewShortConnectionClientv2(config)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc (c *StatV2) GetTotalKeyNum(ctx context.Context, keyPrefix string) (uint64, error) {\n\tapi := clientv2.NewKeysAPI(*c.cli)\n\t// Note that in order to avoid affecting performance, only some keys are counted.\n\trsp, err := api.Get(ctx, keyPrefix, &clientv2.GetOptions{Recursive: false, Sort: true, Quorum: true})\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get etcdcluster total key num,err is %v\", err)\n\t\treturn 0, err\n\t}\n\ttotalKeyNum := uint64(len(rsp.Node.Nodes))\n\tklog.V(2).Infof(\"finished to get etcdcluster total key num %d,index is %d\", totalKeyNum, rsp.Index)\n\treturn totalKeyNum, nil\n}\n\nfunc (c *StatV2) GetIndex(ctx context.Context, endpoint string) (map[featureutil.ConsistencyType]uint64, error) {\n\tmetadata := make(map[featureutil.ConsistencyType]uint64, 4)\n\tapi := clientv2.NewKeysAPI(*c.cli)\n\trsp, err := api.Get(ctx, \"\", &clientv2.GetOptions{Recursive: false, Sort: true, Quorum: true})\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get etcdcluster index,err is %v\", err)\n\t\treturn nil, err\n\t}\n\tklog.V(2).Infof(\"finish to get etcdcluster index,%d\", rsp.Index)\n\tmetadata[featureutil.ConsistencyIndex] = rsp.Index\n\tmetadata[featureutil.ConsistencyRaftRaftAppliedIndex] = 0\n\tmetadata[featureutil.ConsistencyRaftIndex] = 0\n\treturn metadata, nil\n}\n\nfunc (c *StatV2) Close() error {\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/featureprovider/feature.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage featureprovider\n\nimport (\n\t\"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/controllers/util\"\n\t\"tkestack.io/kstone/pkg/etcd\"\n)\n\n// Feature is an abstract, pluggable interface for cluster features.\ntype Feature interface {\n\t// Equal checks whether the feature needs to be updated\n\tEqual(cluster *v1alpha2.EtcdCluster) bool\n\n\t// Sync synchronizes the latest feature configuration\n\tSync(cluster *v1alpha2.EtcdCluster) error\n\n\t// Do executes inspection tasks.\n\tDo(task *v1alpha2.EtcdInspection) error\n}\ntype FeatureContext struct {\n\tClientBuilder      util.ClientBuilder\n\tClientConfigGetter etcd.ClientConfigGetter\n}\n"
  },
  {
    "path": "pkg/featureprovider/plugins.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage featureprovider\n\nimport (\n\t\"errors\"\n\t\"sync\"\n\n\t\"k8s.io/klog/v2\"\n)\n\nvar (\n\tmutex                sync.Mutex\n\tEtcdFeatureProviders = make(map[string]FeatureFactory)\n)\n\ntype FeatureFactory func(cfg *FeatureContext) (Feature, error)\n\n// RegisterFeatureFactory registers the specified feature provider\nfunc RegisterFeatureFactory(name string, factory FeatureFactory) {\n\tmutex.Lock()\n\tdefer mutex.Unlock()\n\n\tif _, found := EtcdFeatureProviders[name]; found {\n\t\tklog.V(2).Infof(\"feature provider:%s was registered twice\", name)\n\t}\n\n\tklog.V(2).Infof(\"feature provider:%s\", name)\n\tEtcdFeatureProviders[name] = factory\n}\n\n// GetFeatureProvider gets the specified feature provider\nfunc GetFeatureProvider(name string, ctx *FeatureContext) (Feature, error) {\n\tmutex.Lock()\n\tdefer mutex.Unlock()\n\tf, found := EtcdFeatureProviders[name]\n\n\tklog.V(1).Infof(\"get provider name %s,status:%t\", name, found)\n\tif !found {\n\t\treturn nil, errors.New(\"fatal error,feature provider not found\")\n\t}\n\treturn f(ctx)\n}\n\n// ListFeatureProvider lists all feature provider\nfunc ListFeatureProvider() []string {\n\tvar features []string\n\tmutex.Lock()\n\tdefer mutex.Unlock()\n\tfor feature := range EtcdFeatureProviders {\n\t\tfeatures = append(features, feature)\n\t}\n\treturn features\n}\n"
  },
  {
    "path": "pkg/featureprovider/providers/alarm/alarm.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage alarm\n\nimport (\n\t\"sync\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/featureprovider\"\n\t\"tkestack.io/kstone/pkg/inspection\"\n)\n\nconst (\n\tProviderName = string(kstonev1alpha2.KStoneFeatureAlarm)\n)\n\nvar (\n\tonce     sync.Once\n\tinstance *FeatureAlarm\n)\n\ntype FeatureAlarm struct {\n\tname       string\n\tinspection *inspection.Server\n\tctx        *featureprovider.FeatureContext\n}\n\nfunc init() {\n\tfeatureprovider.RegisterFeatureFactory(\n\t\tProviderName,\n\t\tfunc(ctx *featureprovider.FeatureContext) (featureprovider.Feature, error) {\n\t\t\treturn initFeatureAlarmInstance(ctx)\n\t\t},\n\t)\n}\n\nfunc initFeatureAlarmInstance(ctx *featureprovider.FeatureContext) (featureprovider.Feature, error) {\n\tvar err error\n\tonce.Do(func() {\n\t\tinstance = &FeatureAlarm{\n\t\t\tname: ProviderName,\n\t\t\tctx:  ctx,\n\t\t}\n\t\tinstance.inspection, err = inspection.NewInspectionServer(ctx)\n\t})\n\treturn instance, err\n}\n\nfunc (c *FeatureAlarm) Equal(cluster *kstonev1alpha2.EtcdCluster) bool {\n\treturn c.inspection.Equal(cluster, kstonev1alpha2.KStoneFeatureAlarm)\n}\n\nfunc (c *FeatureAlarm) Sync(cluster *kstonev1alpha2.EtcdCluster) error {\n\treturn c.inspection.Sync(cluster, kstonev1alpha2.KStoneFeatureAlarm)\n}\n\nfunc (c *FeatureAlarm) Do(inspection *kstonev1alpha2.EtcdInspection) error {\n\treturn c.inspection.CollectAlarmList(inspection)\n}\n"
  },
  {
    "path": "pkg/featureprovider/providers/backup/backup.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage backup\n\nimport (\n\t\"sync\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/backup\"\n\t\"tkestack.io/kstone/pkg/featureprovider\"\n\tfeatureutil \"tkestack.io/kstone/pkg/featureprovider/util\"\n)\n\nconst (\n\tProviderName = string(kstonev1alpha2.KStoneFeatureBackup)\n)\n\nvar (\n\tonce     sync.Once\n\tinstance *FeatureBackup\n)\n\ntype FeatureBackup struct {\n\tname      string\n\tbackupSvr *backup.Server\n\tctx       *featureprovider.FeatureContext\n}\n\nfunc init() {\n\tfeatureprovider.RegisterFeatureFactory(\n\t\tProviderName,\n\t\tfunc(ctx *featureprovider.FeatureContext) (featureprovider.Feature, error) {\n\t\t\treturn initFeatureBackupInstance(ctx)\n\t\t},\n\t)\n}\n\nfunc initFeatureBackupInstance(ctx *featureprovider.FeatureContext) (featureprovider.Feature, error) {\n\tvar err error\n\tonce.Do(func() {\n\t\tinstance = &FeatureBackup{\n\t\t\tname: ProviderName,\n\t\t\tctx:  ctx,\n\t\t}\n\t\tinstance.backupSvr, err = backup.NewBackupServer(ctx.ClientBuilder)\n\t})\n\treturn instance, err\n}\n\nfunc (bak *FeatureBackup) Equal(cluster *kstonev1alpha2.EtcdCluster) bool {\n\tif !featureutil.IsFeatureGateEnabled(cluster.ObjectMeta.Annotations, kstonev1alpha2.KStoneFeatureBackup) {\n\t\tif cluster.Status.FeatureGatesStatus[kstonev1alpha2.KStoneFeatureBackup] != featureutil.FeatureStatusDisabled {\n\t\t\treturn bak.backupSvr.CheckEqualIfDisabled(cluster)\n\t\t}\n\t\treturn true\n\t}\n\treturn bak.backupSvr.CheckEqualIfEnabled(cluster)\n}\n\nfunc (bak *FeatureBackup) Sync(cluster *kstonev1alpha2.EtcdCluster) error {\n\tif !featureutil.IsFeatureGateEnabled(cluster.ObjectMeta.Annotations, kstonev1alpha2.KStoneFeatureBackup) {\n\t\treturn bak.backupSvr.CleanBackup(cluster)\n\t}\n\treturn bak.backupSvr.SyncBackup(cluster)\n}\n\nfunc (bak *FeatureBackup) Do(inspection *kstonev1alpha2.EtcdInspection) error {\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/featureprovider/providers/backupcheck/backupcheck.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage backupcheck\n\nimport (\n\t\"sync\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/featureprovider\"\n\t\"tkestack.io/kstone/pkg/inspection\"\n)\n\nvar (\n\tonce     sync.Once\n\tinstance *FeatureBackupCheck\n)\n\ntype FeatureBackupCheck struct {\n\tname       string\n\tinspection *inspection.Server\n\tctx        *featureprovider.FeatureContext\n}\n\nconst (\n\tProviderName = string(kstonev1alpha2.KStoneFeatureBackupCheck)\n)\n\nfunc init() {\n\tfeatureprovider.RegisterFeatureFactory(\n\t\tProviderName,\n\t\tfunc(ctx *featureprovider.FeatureContext) (featureprovider.Feature, error) {\n\t\t\treturn initFeatureBackupCheckInstance(ctx)\n\t\t},\n\t)\n}\n\nfunc initFeatureBackupCheckInstance(ctx *featureprovider.FeatureContext) (featureprovider.Feature, error) {\n\tvar err error\n\tonce.Do(func() {\n\t\tinstance = &FeatureBackupCheck{\n\t\t\tname: ProviderName,\n\t\t\tctx:  ctx,\n\t\t}\n\t\tinstance.inspection, err = inspection.NewInspectionServer(ctx)\n\t})\n\treturn instance, err\n}\n\nfunc (c *FeatureBackupCheck) Equal(cluster *kstonev1alpha2.EtcdCluster) bool {\n\treturn c.inspection.Equal(cluster, kstonev1alpha2.KStoneFeatureBackupCheck)\n}\n\nfunc (c *FeatureBackupCheck) Sync(cluster *kstonev1alpha2.EtcdCluster) error {\n\treturn c.inspection.Sync(cluster, kstonev1alpha2.KStoneFeatureBackupCheck)\n}\n\nfunc (c *FeatureBackupCheck) Do(inspection *kstonev1alpha2.EtcdInspection) error {\n\treturn c.inspection.StatBackupFiles(inspection)\n}\n"
  },
  {
    "path": "pkg/featureprovider/providers/consistency/consistency.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage consistency\n\nimport (\n\t\"sync\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/featureprovider\"\n\t\"tkestack.io/kstone/pkg/inspection\"\n)\n\nconst (\n\tProviderName = string(kstonev1alpha2.KStoneFeatureConsistency)\n)\n\nvar (\n\tonce     sync.Once\n\tinstance *FeatureConsistency\n)\n\ntype FeatureConsistency struct {\n\tname       string\n\tinspection *inspection.Server\n\tctx        *featureprovider.FeatureContext\n}\n\nfunc init() {\n\tfeatureprovider.RegisterFeatureFactory(\n\t\tProviderName,\n\t\tfunc(ctx *featureprovider.FeatureContext) (featureprovider.Feature, error) {\n\t\t\treturn initFeatureConsistencyInstance(ctx)\n\t\t},\n\t)\n}\n\nfunc initFeatureConsistencyInstance(ctx *featureprovider.FeatureContext) (featureprovider.Feature, error) {\n\tvar err error\n\tonce.Do(func() {\n\t\tinstance = &FeatureConsistency{\n\t\t\tname: ProviderName,\n\t\t\tctx:  ctx,\n\t\t}\n\t\tinstance.inspection, err = inspection.NewInspectionServer(ctx)\n\t})\n\treturn instance, err\n}\n\nfunc (c *FeatureConsistency) Equal(cluster *kstonev1alpha2.EtcdCluster) bool {\n\treturn c.inspection.Equal(cluster, kstonev1alpha2.KStoneFeatureConsistency)\n}\n\nfunc (c *FeatureConsistency) Sync(cluster *kstonev1alpha2.EtcdCluster) error {\n\treturn c.inspection.Sync(cluster, kstonev1alpha2.KStoneFeatureConsistency)\n}\n\nfunc (c *FeatureConsistency) Do(inspection *kstonev1alpha2.EtcdInspection) error {\n\treturn c.inspection.CollectClusterConsistentData(inspection)\n}\n"
  },
  {
    "path": "pkg/featureprovider/providers/healthy/healthy.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage healthy\n\nimport (\n\t\"sync\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/featureprovider\"\n\t\"tkestack.io/kstone/pkg/inspection\"\n)\n\nvar (\n\tonce     sync.Once\n\tinstance *FeatureHealthy\n)\n\ntype FeatureHealthy struct {\n\tname       string\n\tinspection *inspection.Server\n\tctx        *featureprovider.FeatureContext\n}\n\nconst (\n\tProviderName = string(kstonev1alpha2.KStoneFeatureHealthy)\n)\n\nfunc init() {\n\tfeatureprovider.RegisterFeatureFactory(\n\t\tProviderName,\n\t\tfunc(ctx *featureprovider.FeatureContext) (featureprovider.Feature, error) {\n\t\t\treturn initFeatureHealthyInstance(ctx)\n\t\t},\n\t)\n}\n\nfunc initFeatureHealthyInstance(ctx *featureprovider.FeatureContext) (featureprovider.Feature, error) {\n\tvar err error\n\tonce.Do(func() {\n\t\tinstance = &FeatureHealthy{\n\t\t\tname: ProviderName,\n\t\t\tctx:  ctx,\n\t\t}\n\t\tinstance.inspection, err = inspection.NewInspectionServer(ctx)\n\t})\n\treturn instance, err\n}\n\nfunc (c *FeatureHealthy) Equal(cluster *kstonev1alpha2.EtcdCluster) bool {\n\treturn c.inspection.Equal(cluster, kstonev1alpha2.KStoneFeatureHealthy)\n}\n\nfunc (c *FeatureHealthy) Sync(cluster *kstonev1alpha2.EtcdCluster) error {\n\treturn c.inspection.Sync(cluster, kstonev1alpha2.KStoneFeatureHealthy)\n}\n\nfunc (c *FeatureHealthy) Do(inspection *kstonev1alpha2.EtcdInspection) error {\n\treturn c.inspection.CollectMemberHealthy(inspection)\n}\n"
  },
  {
    "path": "pkg/featureprovider/providers/monitor/monitor.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage monitor\n\nimport (\n\t\"sync\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/featureprovider\"\n\tfeatureutil \"tkestack.io/kstone/pkg/featureprovider/util\"\n\t\"tkestack.io/kstone/pkg/monitor\"\n)\n\nvar (\n\tonce     sync.Once\n\tinstance *FeaturePrometheus\n)\n\ntype FeaturePrometheus struct {\n\tname string\n\tprom *monitor.PrometheusMonitor\n\tctx  *featureprovider.FeatureContext\n}\n\nconst (\n\tProviderName = string(kstonev1alpha2.KStoneFeatureMonitor)\n)\n\nfunc init() {\n\tfeatureprovider.RegisterFeatureFactory(\n\t\tProviderName,\n\t\tfunc(cfg *featureprovider.FeatureContext) (featureprovider.Feature, error) {\n\t\t\treturn initFeaturePrometheusInstance(cfg)\n\t\t},\n\t)\n}\n\nfunc initFeaturePrometheusInstance(ctx *featureprovider.FeatureContext) (featureprovider.Feature, error) {\n\tvar err error\n\tonce.Do(func() {\n\t\tinstance = &FeaturePrometheus{\n\t\t\tname: ProviderName,\n\t\t\tctx:  ctx,\n\t\t}\n\t\tinstance.prom, err = monitor.NewPrometheusMonitor(ctx.ClientBuilder)\n\t})\n\treturn instance, err\n}\n\nfunc (p *FeaturePrometheus) Equal(cluster *kstonev1alpha2.EtcdCluster) bool {\n\tif !featureutil.IsFeatureGateEnabled(cluster.ObjectMeta.Annotations, kstonev1alpha2.KStoneFeatureMonitor) {\n\t\tif cluster.Status.FeatureGatesStatus[kstonev1alpha2.KStoneFeatureMonitor] != featureutil.FeatureStatusDisabled {\n\t\t\treturn p.prom.CheckEqualIfDisabled(cluster)\n\t\t}\n\t\treturn true\n\t}\n\treturn p.prom.CheckEqualIfEnabled(cluster)\n}\n\nfunc (p *FeaturePrometheus) Sync(cluster *kstonev1alpha2.EtcdCluster) error {\n\tif !featureutil.IsFeatureGateEnabled(cluster.ObjectMeta.Annotations, kstonev1alpha2.KStoneFeatureMonitor) {\n\t\treturn p.prom.CleanPrometheusMonitor(cluster)\n\t}\n\treturn p.prom.SyncPrometheusMonitor(cluster)\n}\n\nfunc (p *FeaturePrometheus) Do(inspection *kstonev1alpha2.EtcdInspection) error {\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/featureprovider/providers/providers.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage providers\n\nimport (\n\t// register backup feature\n\t_ \"tkestack.io/kstone/pkg/featureprovider/providers/backup\"\n\t// register monitor feature\n\t_ \"tkestack.io/kstone/pkg/featureprovider/providers/monitor\"\n\t// register consistency inspection feature\n\t_ \"tkestack.io/kstone/pkg/featureprovider/providers/consistency\"\n\t// register healthy inspection feature\n\t_ \"tkestack.io/kstone/pkg/featureprovider/providers/healthy\"\n\t// register request inspection feature\n\t_ \"tkestack.io/kstone/pkg/featureprovider/providers/request\"\n\t// register alarm inspection feature\n\t_ \"tkestack.io/kstone/pkg/featureprovider/providers/alarm\"\n\t// register backupcheck inspection feature\n\t_ \"tkestack.io/kstone/pkg/featureprovider/providers/backupcheck\"\n)\n"
  },
  {
    "path": "pkg/featureprovider/providers/request/request.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage request\n\nimport (\n\t\"sync\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/featureprovider\"\n\t\"tkestack.io/kstone/pkg/inspection\"\n)\n\nconst (\n\tProviderName = string(kstonev1alpha2.KStoneFeatureRequest)\n)\n\nvar (\n\tonce     sync.Once\n\tinstance *FeatureRequest\n)\n\ntype FeatureRequest struct {\n\tname       string\n\tinspection *inspection.Server\n\tctx        *featureprovider.FeatureContext\n}\n\nfunc init() {\n\tfeatureprovider.RegisterFeatureFactory(\n\t\tProviderName,\n\t\tfunc(ctx *featureprovider.FeatureContext) (featureprovider.Feature, error) {\n\t\t\treturn initFeatureRequestInstance(ctx)\n\t\t},\n\t)\n}\n\nfunc initFeatureRequestInstance(ctx *featureprovider.FeatureContext) (featureprovider.Feature, error) {\n\tvar err error\n\tonce.Do(func() {\n\t\tinstance = &FeatureRequest{\n\t\t\tname: ProviderName,\n\t\t\tctx:  ctx,\n\t\t}\n\t\tinstance.inspection, err = inspection.NewInspectionServer(ctx)\n\t})\n\treturn instance, err\n}\n\nfunc (c *FeatureRequest) Equal(cluster *kstonev1alpha2.EtcdCluster) bool {\n\treturn c.inspection.Equal(cluster, kstonev1alpha2.KStoneFeatureRequest)\n}\n\nfunc (c *FeatureRequest) Sync(cluster *kstonev1alpha2.EtcdCluster) error {\n\treturn c.inspection.Sync(cluster, kstonev1alpha2.KStoneFeatureRequest)\n}\n\nfunc (c *FeatureRequest) Do(inspection *kstonev1alpha2.EtcdInspection) error {\n\treturn c.inspection.CollectEtcdClusterRequest(inspection)\n}\n"
  },
  {
    "path": "pkg/featureprovider/util/util.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage util\n\nimport (\n\t\"strconv\"\n\t\"strings\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/inspection/metrics\"\n)\n\nconst (\n\tFeatureStatusEnabled  = \"enabled\"\n\tFeatureStatusDisabled = \"disabled\"\n)\n\ntype ConsistencyType string\n\nconst (\n\tConsistencyKeyTotal             ConsistencyType = \"keyTotal\"\n\tConsistencyRevision             ConsistencyType = \"revision\"\n\tConsistencyIndex                ConsistencyType = \"index\"\n\tConsistencyRaftRaftAppliedIndex ConsistencyType = \"raftAppliedIndex\"\n\tConsistencyRaftIndex            ConsistencyType = \"raftIndex\"\n)\n\nconst (\n\tOneDaySeconds = 24 * 60 * 60\n)\n\nfunc IsFeatureGateEnabled(annotations map[string]string, name kstonev1alpha2.KStoneFeature) bool {\n\tif gates, found := annotations[kstonev1alpha2.KStoneFeatureAnno]; found && gates != \"\" {\n\t\tfeaturelist := strings.Split(gates, \",\")\n\t\tfor _, item := range featurelist {\n\t\t\tfeatures := strings.Split(item, \"=\")\n\t\t\tif len(features) != 2 {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tenabled, _ := strconv.ParseBool(features[1])\n\t\t\tif kstonev1alpha2.KStoneFeature(features[0]) == name && enabled {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t}\n\treturn false\n}\n\nfunc IncrFailedInspectionCounter(clusterName string, featureName kstonev1alpha2.KStoneFeature) {\n\tlabels := map[string]string{\n\t\t\"clusterName\":    clusterName,\n\t\t\"inspectionType\": string(featureName),\n\t}\n\tmetrics.EtcdInspectionFailedNum.With(labels).Inc()\n}\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/clientset.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\npackage versioned\n\nimport (\n\t\"fmt\"\n\n\tdiscovery \"k8s.io/client-go/discovery\"\n\trest \"k8s.io/client-go/rest\"\n\tflowcontrol \"k8s.io/client-go/util/flowcontrol\"\n\tkstonev1alpha1 \"tkestack.io/kstone/pkg/generated/clientset/versioned/typed/kstone/v1alpha1\"\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/generated/clientset/versioned/typed/kstone/v1alpha2\"\n)\n\ntype Interface interface {\n\tDiscovery() discovery.DiscoveryInterface\n\tKstoneV1alpha1() kstonev1alpha1.KstoneV1alpha1Interface\n\tKstoneV1alpha2() kstonev1alpha2.KstoneV1alpha2Interface\n}\n\n// Clientset contains the clients for groups. Each group has exactly one\n// version included in a Clientset.\ntype Clientset struct {\n\t*discovery.DiscoveryClient\n\tkstoneV1alpha1 *kstonev1alpha1.KstoneV1alpha1Client\n\tkstoneV1alpha2 *kstonev1alpha2.KstoneV1alpha2Client\n}\n\n// KstoneV1alpha1 retrieves the KstoneV1alpha1Client\nfunc (c *Clientset) KstoneV1alpha1() kstonev1alpha1.KstoneV1alpha1Interface {\n\treturn c.kstoneV1alpha1\n}\n\n// KstoneV1alpha2 retrieves the KstoneV1alpha2Client\nfunc (c *Clientset) KstoneV1alpha2() kstonev1alpha2.KstoneV1alpha2Interface {\n\treturn c.kstoneV1alpha2\n}\n\n// Discovery retrieves the DiscoveryClient\nfunc (c *Clientset) Discovery() discovery.DiscoveryInterface {\n\tif c == nil {\n\t\treturn nil\n\t}\n\treturn c.DiscoveryClient\n}\n\n// NewForConfig creates a new Clientset for the given config.\n// If config's RateLimiter is not set and QPS and Burst are acceptable,\n// NewForConfig will generate a rate-limiter in configShallowCopy.\nfunc NewForConfig(c *rest.Config) (*Clientset, error) {\n\tconfigShallowCopy := *c\n\tif configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {\n\t\tif configShallowCopy.Burst <= 0 {\n\t\t\treturn nil, fmt.Errorf(\"burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0\")\n\t\t}\n\t\tconfigShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)\n\t}\n\tvar cs Clientset\n\tvar err error\n\tcs.kstoneV1alpha1, err = kstonev1alpha1.NewForConfig(&configShallowCopy)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcs.kstoneV1alpha2, err = kstonev1alpha2.NewForConfig(&configShallowCopy)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tcs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &cs, nil\n}\n\n// NewForConfigOrDie creates a new Clientset for the given config and\n// panics if there is an error in the config.\nfunc NewForConfigOrDie(c *rest.Config) *Clientset {\n\tvar cs Clientset\n\tcs.kstoneV1alpha1 = kstonev1alpha1.NewForConfigOrDie(c)\n\tcs.kstoneV1alpha2 = kstonev1alpha2.NewForConfigOrDie(c)\n\n\tcs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)\n\treturn &cs\n}\n\n// New creates a new Clientset for the given RESTClient.\nfunc New(c rest.Interface) *Clientset {\n\tvar cs Clientset\n\tcs.kstoneV1alpha1 = kstonev1alpha1.New(c)\n\tcs.kstoneV1alpha2 = kstonev1alpha2.New(c)\n\n\tcs.DiscoveryClient = discovery.NewDiscoveryClient(c)\n\treturn &cs\n}\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/doc.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\n// This package has the automatically generated clientset.\npackage versioned\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/fake/clientset_generated.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\npackage fake\n\nimport (\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/watch\"\n\t\"k8s.io/client-go/discovery\"\n\tfakediscovery \"k8s.io/client-go/discovery/fake\"\n\t\"k8s.io/client-go/testing\"\n\tclientset \"tkestack.io/kstone/pkg/generated/clientset/versioned\"\n\tkstonev1alpha1 \"tkestack.io/kstone/pkg/generated/clientset/versioned/typed/kstone/v1alpha1\"\n\tfakekstonev1alpha1 \"tkestack.io/kstone/pkg/generated/clientset/versioned/typed/kstone/v1alpha1/fake\"\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/generated/clientset/versioned/typed/kstone/v1alpha2\"\n\tfakekstonev1alpha2 \"tkestack.io/kstone/pkg/generated/clientset/versioned/typed/kstone/v1alpha2/fake\"\n)\n\n// NewSimpleClientset returns a clientset that will respond with the provided objects.\n// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,\n// without applying any validations and/or defaults. It shouldn't be considered a replacement\n// for a real clientset and is mostly useful in simple unit tests.\nfunc NewSimpleClientset(objects ...runtime.Object) *Clientset {\n\to := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())\n\tfor _, obj := range objects {\n\t\tif err := o.Add(obj); err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t}\n\n\tcs := &Clientset{tracker: o}\n\tcs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}\n\tcs.AddReactor(\"*\", \"*\", testing.ObjectReaction(o))\n\tcs.AddWatchReactor(\"*\", func(action testing.Action) (handled bool, ret watch.Interface, err error) {\n\t\tgvr := action.GetResource()\n\t\tns := action.GetNamespace()\n\t\twatch, err := o.Watch(gvr, ns)\n\t\tif err != nil {\n\t\t\treturn false, nil, err\n\t\t}\n\t\treturn true, watch, nil\n\t})\n\n\treturn cs\n}\n\n// Clientset implements clientset.Interface. Meant to be embedded into a\n// struct to get a default implementation. This makes faking out just the method\n// you want to test easier.\ntype Clientset struct {\n\ttesting.Fake\n\tdiscovery *fakediscovery.FakeDiscovery\n\ttracker   testing.ObjectTracker\n}\n\nfunc (c *Clientset) Discovery() discovery.DiscoveryInterface {\n\treturn c.discovery\n}\n\nfunc (c *Clientset) Tracker() testing.ObjectTracker {\n\treturn c.tracker\n}\n\nvar _ clientset.Interface = &Clientset{}\n\n// KstoneV1alpha1 retrieves the KstoneV1alpha1Client\nfunc (c *Clientset) KstoneV1alpha1() kstonev1alpha1.KstoneV1alpha1Interface {\n\treturn &fakekstonev1alpha1.FakeKstoneV1alpha1{Fake: &c.Fake}\n}\n\n// KstoneV1alpha2 retrieves the KstoneV1alpha2Client\nfunc (c *Clientset) KstoneV1alpha2() kstonev1alpha2.KstoneV1alpha2Interface {\n\treturn &fakekstonev1alpha2.FakeKstoneV1alpha2{Fake: &c.Fake}\n}\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/fake/doc.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\n// This package has the automatically generated fake clientset.\npackage fake\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/fake/register.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\npackage fake\n\nimport (\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n\tschema \"k8s.io/apimachinery/pkg/runtime/schema\"\n\tserializer \"k8s.io/apimachinery/pkg/runtime/serializer\"\n\tutilruntime \"k8s.io/apimachinery/pkg/util/runtime\"\n\tkstonev1alpha1 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha1\"\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n)\n\nvar scheme = runtime.NewScheme()\nvar codecs = serializer.NewCodecFactory(scheme)\n\nvar localSchemeBuilder = runtime.SchemeBuilder{\n\tkstonev1alpha1.AddToScheme,\n\tkstonev1alpha2.AddToScheme,\n}\n\n// AddToScheme adds all types of this clientset into the given scheme. This allows composition\n// of clientsets, like in:\n//\n//   import (\n//     \"k8s.io/client-go/kubernetes\"\n//     clientsetscheme \"k8s.io/client-go/kubernetes/scheme\"\n//     aggregatorclientsetscheme \"k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme\"\n//   )\n//\n//   kclientset, _ := kubernetes.NewForConfig(c)\n//   _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)\n//\n// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types\n// correctly.\nvar AddToScheme = localSchemeBuilder.AddToScheme\n\nfunc init() {\n\tv1.AddToGroupVersion(scheme, schema.GroupVersion{Version: \"v1\"})\n\tutilruntime.Must(AddToScheme(scheme))\n}\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/scheme/doc.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\n// This package contains the scheme of the automatically generated clientset.\npackage scheme\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/scheme/register.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\npackage scheme\n\nimport (\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n\tschema \"k8s.io/apimachinery/pkg/runtime/schema\"\n\tserializer \"k8s.io/apimachinery/pkg/runtime/serializer\"\n\tutilruntime \"k8s.io/apimachinery/pkg/util/runtime\"\n\tkstonev1alpha1 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha1\"\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n)\n\nvar Scheme = runtime.NewScheme()\nvar Codecs = serializer.NewCodecFactory(Scheme)\nvar ParameterCodec = runtime.NewParameterCodec(Scheme)\nvar localSchemeBuilder = runtime.SchemeBuilder{\n\tkstonev1alpha1.AddToScheme,\n\tkstonev1alpha2.AddToScheme,\n}\n\n// AddToScheme adds all types of this clientset into the given scheme. This allows composition\n// of clientsets, like in:\n//\n//   import (\n//     \"k8s.io/client-go/kubernetes\"\n//     clientsetscheme \"k8s.io/client-go/kubernetes/scheme\"\n//     aggregatorclientsetscheme \"k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme\"\n//   )\n//\n//   kclientset, _ := kubernetes.NewForConfig(c)\n//   _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)\n//\n// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types\n// correctly.\nvar AddToScheme = localSchemeBuilder.AddToScheme\n\nfunc init() {\n\tv1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: \"v1\"})\n\tutilruntime.Must(AddToScheme(Scheme))\n}\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/typed/kstone/v1alpha1/doc.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\n// This package has the automatically generated typed clients.\npackage v1alpha1\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/typed/kstone/v1alpha1/etcdcluster.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\npackage v1alpha1\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\ttypes \"k8s.io/apimachinery/pkg/types\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\trest \"k8s.io/client-go/rest\"\n\tv1alpha1 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha1\"\n\tscheme \"tkestack.io/kstone/pkg/generated/clientset/versioned/scheme\"\n)\n\n// EtcdClustersGetter has a method to return a EtcdClusterInterface.\n// A group's client should implement this interface.\ntype EtcdClustersGetter interface {\n\tEtcdClusters(namespace string) EtcdClusterInterface\n}\n\n// EtcdClusterInterface has methods to work with EtcdCluster resources.\ntype EtcdClusterInterface interface {\n\tCreate(ctx context.Context, etcdCluster *v1alpha1.EtcdCluster, opts v1.CreateOptions) (*v1alpha1.EtcdCluster, error)\n\tUpdate(ctx context.Context, etcdCluster *v1alpha1.EtcdCluster, opts v1.UpdateOptions) (*v1alpha1.EtcdCluster, error)\n\tUpdateStatus(ctx context.Context, etcdCluster *v1alpha1.EtcdCluster, opts v1.UpdateOptions) (*v1alpha1.EtcdCluster, error)\n\tDelete(ctx context.Context, name string, opts v1.DeleteOptions) error\n\tDeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error\n\tGet(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.EtcdCluster, error)\n\tList(ctx context.Context, opts v1.ListOptions) (*v1alpha1.EtcdClusterList, error)\n\tWatch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)\n\tPatch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.EtcdCluster, err error)\n\tEtcdClusterExpansion\n}\n\n// etcdClusters implements EtcdClusterInterface\ntype etcdClusters struct {\n\tclient rest.Interface\n\tns     string\n}\n\n// newEtcdClusters returns a EtcdClusters\nfunc newEtcdClusters(c *KstoneV1alpha1Client, namespace string) *etcdClusters {\n\treturn &etcdClusters{\n\t\tclient: c.RESTClient(),\n\t\tns:     namespace,\n\t}\n}\n\n// Get takes name of the etcdCluster, and returns the corresponding etcdCluster object, and an error if there is any.\nfunc (c *etcdClusters) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.EtcdCluster, err error) {\n\tresult = &v1alpha1.EtcdCluster{}\n\terr = c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tName(name).\n\t\tVersionedParams(&options, scheme.ParameterCodec).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n\n// List takes label and field selectors, and returns the list of EtcdClusters that match those selectors.\nfunc (c *etcdClusters) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.EtcdClusterList, err error) {\n\tvar timeout time.Duration\n\tif opts.TimeoutSeconds != nil {\n\t\ttimeout = time.Duration(*opts.TimeoutSeconds) * time.Second\n\t}\n\tresult = &v1alpha1.EtcdClusterList{}\n\terr = c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tTimeout(timeout).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n\n// Watch returns a watch.Interface that watches the requested etcdClusters.\nfunc (c *etcdClusters) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {\n\tvar timeout time.Duration\n\tif opts.TimeoutSeconds != nil {\n\t\ttimeout = time.Duration(*opts.TimeoutSeconds) * time.Second\n\t}\n\topts.Watch = true\n\treturn c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tTimeout(timeout).\n\t\tWatch(ctx)\n}\n\n// Create takes the representation of a etcdCluster and creates it.  Returns the server's representation of the etcdCluster, and an error, if there is any.\nfunc (c *etcdClusters) Create(ctx context.Context, etcdCluster *v1alpha1.EtcdCluster, opts v1.CreateOptions) (result *v1alpha1.EtcdCluster, err error) {\n\tresult = &v1alpha1.EtcdCluster{}\n\terr = c.client.Post().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tBody(etcdCluster).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n\n// Update takes the representation of a etcdCluster and updates it. Returns the server's representation of the etcdCluster, and an error, if there is any.\nfunc (c *etcdClusters) Update(ctx context.Context, etcdCluster *v1alpha1.EtcdCluster, opts v1.UpdateOptions) (result *v1alpha1.EtcdCluster, err error) {\n\tresult = &v1alpha1.EtcdCluster{}\n\terr = c.client.Put().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tName(etcdCluster.Name).\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tBody(etcdCluster).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n\n// UpdateStatus was generated because the type contains a Status member.\n// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().\nfunc (c *etcdClusters) UpdateStatus(ctx context.Context, etcdCluster *v1alpha1.EtcdCluster, opts v1.UpdateOptions) (result *v1alpha1.EtcdCluster, err error) {\n\tresult = &v1alpha1.EtcdCluster{}\n\terr = c.client.Put().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tName(etcdCluster.Name).\n\t\tSubResource(\"status\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tBody(etcdCluster).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n\n// Delete takes name of the etcdCluster and deletes it. Returns an error if one occurs.\nfunc (c *etcdClusters) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {\n\treturn c.client.Delete().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tName(name).\n\t\tBody(&opts).\n\t\tDo(ctx).\n\t\tError()\n}\n\n// DeleteCollection deletes a collection of objects.\nfunc (c *etcdClusters) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {\n\tvar timeout time.Duration\n\tif listOpts.TimeoutSeconds != nil {\n\t\ttimeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second\n\t}\n\treturn c.client.Delete().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tVersionedParams(&listOpts, scheme.ParameterCodec).\n\t\tTimeout(timeout).\n\t\tBody(&opts).\n\t\tDo(ctx).\n\t\tError()\n}\n\n// Patch applies the patch and returns the patched etcdCluster.\nfunc (c *etcdClusters) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.EtcdCluster, err error) {\n\tresult = &v1alpha1.EtcdCluster{}\n\terr = c.client.Patch(pt).\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tName(name).\n\t\tSubResource(subresources...).\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tBody(data).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/typed/kstone/v1alpha1/etcdinspection.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\npackage v1alpha1\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\ttypes \"k8s.io/apimachinery/pkg/types\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\trest \"k8s.io/client-go/rest\"\n\tv1alpha1 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha1\"\n\tscheme \"tkestack.io/kstone/pkg/generated/clientset/versioned/scheme\"\n)\n\n// EtcdInspectionsGetter has a method to return a EtcdInspectionInterface.\n// A group's client should implement this interface.\ntype EtcdInspectionsGetter interface {\n\tEtcdInspections(namespace string) EtcdInspectionInterface\n}\n\n// EtcdInspectionInterface has methods to work with EtcdInspection resources.\ntype EtcdInspectionInterface interface {\n\tCreate(ctx context.Context, etcdInspection *v1alpha1.EtcdInspection, opts v1.CreateOptions) (*v1alpha1.EtcdInspection, error)\n\tUpdate(ctx context.Context, etcdInspection *v1alpha1.EtcdInspection, opts v1.UpdateOptions) (*v1alpha1.EtcdInspection, error)\n\tUpdateStatus(ctx context.Context, etcdInspection *v1alpha1.EtcdInspection, opts v1.UpdateOptions) (*v1alpha1.EtcdInspection, error)\n\tDelete(ctx context.Context, name string, opts v1.DeleteOptions) error\n\tDeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error\n\tGet(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.EtcdInspection, error)\n\tList(ctx context.Context, opts v1.ListOptions) (*v1alpha1.EtcdInspectionList, error)\n\tWatch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)\n\tPatch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.EtcdInspection, err error)\n\tEtcdInspectionExpansion\n}\n\n// etcdInspections implements EtcdInspectionInterface\ntype etcdInspections struct {\n\tclient rest.Interface\n\tns     string\n}\n\n// newEtcdInspections returns a EtcdInspections\nfunc newEtcdInspections(c *KstoneV1alpha1Client, namespace string) *etcdInspections {\n\treturn &etcdInspections{\n\t\tclient: c.RESTClient(),\n\t\tns:     namespace,\n\t}\n}\n\n// Get takes name of the etcdInspection, and returns the corresponding etcdInspection object, and an error if there is any.\nfunc (c *etcdInspections) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.EtcdInspection, err error) {\n\tresult = &v1alpha1.EtcdInspection{}\n\terr = c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdinspections\").\n\t\tName(name).\n\t\tVersionedParams(&options, scheme.ParameterCodec).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n\n// List takes label and field selectors, and returns the list of EtcdInspections that match those selectors.\nfunc (c *etcdInspections) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.EtcdInspectionList, err error) {\n\tvar timeout time.Duration\n\tif opts.TimeoutSeconds != nil {\n\t\ttimeout = time.Duration(*opts.TimeoutSeconds) * time.Second\n\t}\n\tresult = &v1alpha1.EtcdInspectionList{}\n\terr = c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdinspections\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tTimeout(timeout).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n\n// Watch returns a watch.Interface that watches the requested etcdInspections.\nfunc (c *etcdInspections) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {\n\tvar timeout time.Duration\n\tif opts.TimeoutSeconds != nil {\n\t\ttimeout = time.Duration(*opts.TimeoutSeconds) * time.Second\n\t}\n\topts.Watch = true\n\treturn c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdinspections\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tTimeout(timeout).\n\t\tWatch(ctx)\n}\n\n// Create takes the representation of a etcdInspection and creates it.  Returns the server's representation of the etcdInspection, and an error, if there is any.\nfunc (c *etcdInspections) Create(ctx context.Context, etcdInspection *v1alpha1.EtcdInspection, opts v1.CreateOptions) (result *v1alpha1.EtcdInspection, err error) {\n\tresult = &v1alpha1.EtcdInspection{}\n\terr = c.client.Post().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdinspections\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tBody(etcdInspection).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n\n// Update takes the representation of a etcdInspection and updates it. Returns the server's representation of the etcdInspection, and an error, if there is any.\nfunc (c *etcdInspections) Update(ctx context.Context, etcdInspection *v1alpha1.EtcdInspection, opts v1.UpdateOptions) (result *v1alpha1.EtcdInspection, err error) {\n\tresult = &v1alpha1.EtcdInspection{}\n\terr = c.client.Put().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdinspections\").\n\t\tName(etcdInspection.Name).\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tBody(etcdInspection).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n\n// UpdateStatus was generated because the type contains a Status member.\n// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().\nfunc (c *etcdInspections) UpdateStatus(ctx context.Context, etcdInspection *v1alpha1.EtcdInspection, opts v1.UpdateOptions) (result *v1alpha1.EtcdInspection, err error) {\n\tresult = &v1alpha1.EtcdInspection{}\n\terr = c.client.Put().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdinspections\").\n\t\tName(etcdInspection.Name).\n\t\tSubResource(\"status\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tBody(etcdInspection).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n\n// Delete takes name of the etcdInspection and deletes it. Returns an error if one occurs.\nfunc (c *etcdInspections) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {\n\treturn c.client.Delete().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdinspections\").\n\t\tName(name).\n\t\tBody(&opts).\n\t\tDo(ctx).\n\t\tError()\n}\n\n// DeleteCollection deletes a collection of objects.\nfunc (c *etcdInspections) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {\n\tvar timeout time.Duration\n\tif listOpts.TimeoutSeconds != nil {\n\t\ttimeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second\n\t}\n\treturn c.client.Delete().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdinspections\").\n\t\tVersionedParams(&listOpts, scheme.ParameterCodec).\n\t\tTimeout(timeout).\n\t\tBody(&opts).\n\t\tDo(ctx).\n\t\tError()\n}\n\n// Patch applies the patch and returns the patched etcdInspection.\nfunc (c *etcdInspections) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.EtcdInspection, err error) {\n\tresult = &v1alpha1.EtcdInspection{}\n\terr = c.client.Patch(pt).\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdinspections\").\n\t\tName(name).\n\t\tSubResource(subresources...).\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tBody(data).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/typed/kstone/v1alpha1/fake/doc.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\n// Package fake has the automatically generated clients.\npackage fake\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/typed/kstone/v1alpha1/fake/fake_etcdcluster.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\npackage fake\n\nimport (\n\t\"context\"\n\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\tlabels \"k8s.io/apimachinery/pkg/labels\"\n\tschema \"k8s.io/apimachinery/pkg/runtime/schema\"\n\ttypes \"k8s.io/apimachinery/pkg/types\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\ttesting \"k8s.io/client-go/testing\"\n\tv1alpha1 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha1\"\n)\n\n// FakeEtcdClusters implements EtcdClusterInterface\ntype FakeEtcdClusters struct {\n\tFake *FakeKstoneV1alpha1\n\tns   string\n}\n\nvar etcdclustersResource = schema.GroupVersionResource{Group: \"kstone.tkestack.io\", Version: \"v1alpha1\", Resource: \"etcdclusters\"}\n\nvar etcdclustersKind = schema.GroupVersionKind{Group: \"kstone.tkestack.io\", Version: \"v1alpha1\", Kind: \"EtcdCluster\"}\n\n// Get takes name of the etcdCluster, and returns the corresponding etcdCluster object, and an error if there is any.\nfunc (c *FakeEtcdClusters) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.EtcdCluster, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewGetAction(etcdclustersResource, c.ns, name), &v1alpha1.EtcdCluster{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1alpha1.EtcdCluster), err\n}\n\n// List takes label and field selectors, and returns the list of EtcdClusters that match those selectors.\nfunc (c *FakeEtcdClusters) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.EtcdClusterList, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewListAction(etcdclustersResource, etcdclustersKind, c.ns, opts), &v1alpha1.EtcdClusterList{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\n\tlabel, _, _ := testing.ExtractFromListOptions(opts)\n\tif label == nil {\n\t\tlabel = labels.Everything()\n\t}\n\tlist := &v1alpha1.EtcdClusterList{ListMeta: obj.(*v1alpha1.EtcdClusterList).ListMeta}\n\tfor _, item := range obj.(*v1alpha1.EtcdClusterList).Items {\n\t\tif label.Matches(labels.Set(item.Labels)) {\n\t\t\tlist.Items = append(list.Items, item)\n\t\t}\n\t}\n\treturn list, err\n}\n\n// Watch returns a watch.Interface that watches the requested etcdClusters.\nfunc (c *FakeEtcdClusters) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {\n\treturn c.Fake.\n\t\tInvokesWatch(testing.NewWatchAction(etcdclustersResource, c.ns, opts))\n\n}\n\n// Create takes the representation of a etcdCluster and creates it.  Returns the server's representation of the etcdCluster, and an error, if there is any.\nfunc (c *FakeEtcdClusters) Create(ctx context.Context, etcdCluster *v1alpha1.EtcdCluster, opts v1.CreateOptions) (result *v1alpha1.EtcdCluster, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewCreateAction(etcdclustersResource, c.ns, etcdCluster), &v1alpha1.EtcdCluster{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1alpha1.EtcdCluster), err\n}\n\n// Update takes the representation of a etcdCluster and updates it. Returns the server's representation of the etcdCluster, and an error, if there is any.\nfunc (c *FakeEtcdClusters) Update(ctx context.Context, etcdCluster *v1alpha1.EtcdCluster, opts v1.UpdateOptions) (result *v1alpha1.EtcdCluster, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewUpdateAction(etcdclustersResource, c.ns, etcdCluster), &v1alpha1.EtcdCluster{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1alpha1.EtcdCluster), err\n}\n\n// UpdateStatus was generated because the type contains a Status member.\n// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().\nfunc (c *FakeEtcdClusters) UpdateStatus(ctx context.Context, etcdCluster *v1alpha1.EtcdCluster, opts v1.UpdateOptions) (*v1alpha1.EtcdCluster, error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewUpdateSubresourceAction(etcdclustersResource, \"status\", c.ns, etcdCluster), &v1alpha1.EtcdCluster{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1alpha1.EtcdCluster), err\n}\n\n// Delete takes name of the etcdCluster and deletes it. Returns an error if one occurs.\nfunc (c *FakeEtcdClusters) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {\n\t_, err := c.Fake.\n\t\tInvokes(testing.NewDeleteAction(etcdclustersResource, c.ns, name), &v1alpha1.EtcdCluster{})\n\n\treturn err\n}\n\n// DeleteCollection deletes a collection of objects.\nfunc (c *FakeEtcdClusters) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {\n\taction := testing.NewDeleteCollectionAction(etcdclustersResource, c.ns, listOpts)\n\n\t_, err := c.Fake.Invokes(action, &v1alpha1.EtcdClusterList{})\n\treturn err\n}\n\n// Patch applies the patch and returns the patched etcdCluster.\nfunc (c *FakeEtcdClusters) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.EtcdCluster, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewPatchSubresourceAction(etcdclustersResource, c.ns, name, pt, data, subresources...), &v1alpha1.EtcdCluster{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1alpha1.EtcdCluster), err\n}\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/typed/kstone/v1alpha1/fake/fake_etcdinspection.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\npackage fake\n\nimport (\n\t\"context\"\n\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\tlabels \"k8s.io/apimachinery/pkg/labels\"\n\tschema \"k8s.io/apimachinery/pkg/runtime/schema\"\n\ttypes \"k8s.io/apimachinery/pkg/types\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\ttesting \"k8s.io/client-go/testing\"\n\tv1alpha1 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha1\"\n)\n\n// FakeEtcdInspections implements EtcdInspectionInterface\ntype FakeEtcdInspections struct {\n\tFake *FakeKstoneV1alpha1\n\tns   string\n}\n\nvar etcdinspectionsResource = schema.GroupVersionResource{Group: \"kstone.tkestack.io\", Version: \"v1alpha1\", Resource: \"etcdinspections\"}\n\nvar etcdinspectionsKind = schema.GroupVersionKind{Group: \"kstone.tkestack.io\", Version: \"v1alpha1\", Kind: \"EtcdInspection\"}\n\n// Get takes name of the etcdInspection, and returns the corresponding etcdInspection object, and an error if there is any.\nfunc (c *FakeEtcdInspections) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.EtcdInspection, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewGetAction(etcdinspectionsResource, c.ns, name), &v1alpha1.EtcdInspection{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1alpha1.EtcdInspection), err\n}\n\n// List takes label and field selectors, and returns the list of EtcdInspections that match those selectors.\nfunc (c *FakeEtcdInspections) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.EtcdInspectionList, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewListAction(etcdinspectionsResource, etcdinspectionsKind, c.ns, opts), &v1alpha1.EtcdInspectionList{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\n\tlabel, _, _ := testing.ExtractFromListOptions(opts)\n\tif label == nil {\n\t\tlabel = labels.Everything()\n\t}\n\tlist := &v1alpha1.EtcdInspectionList{ListMeta: obj.(*v1alpha1.EtcdInspectionList).ListMeta}\n\tfor _, item := range obj.(*v1alpha1.EtcdInspectionList).Items {\n\t\tif label.Matches(labels.Set(item.Labels)) {\n\t\t\tlist.Items = append(list.Items, item)\n\t\t}\n\t}\n\treturn list, err\n}\n\n// Watch returns a watch.Interface that watches the requested etcdInspections.\nfunc (c *FakeEtcdInspections) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {\n\treturn c.Fake.\n\t\tInvokesWatch(testing.NewWatchAction(etcdinspectionsResource, c.ns, opts))\n\n}\n\n// Create takes the representation of a etcdInspection and creates it.  Returns the server's representation of the etcdInspection, and an error, if there is any.\nfunc (c *FakeEtcdInspections) Create(ctx context.Context, etcdInspection *v1alpha1.EtcdInspection, opts v1.CreateOptions) (result *v1alpha1.EtcdInspection, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewCreateAction(etcdinspectionsResource, c.ns, etcdInspection), &v1alpha1.EtcdInspection{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1alpha1.EtcdInspection), err\n}\n\n// Update takes the representation of a etcdInspection and updates it. Returns the server's representation of the etcdInspection, and an error, if there is any.\nfunc (c *FakeEtcdInspections) Update(ctx context.Context, etcdInspection *v1alpha1.EtcdInspection, opts v1.UpdateOptions) (result *v1alpha1.EtcdInspection, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewUpdateAction(etcdinspectionsResource, c.ns, etcdInspection), &v1alpha1.EtcdInspection{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1alpha1.EtcdInspection), err\n}\n\n// UpdateStatus was generated because the type contains a Status member.\n// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().\nfunc (c *FakeEtcdInspections) UpdateStatus(ctx context.Context, etcdInspection *v1alpha1.EtcdInspection, opts v1.UpdateOptions) (*v1alpha1.EtcdInspection, error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewUpdateSubresourceAction(etcdinspectionsResource, \"status\", c.ns, etcdInspection), &v1alpha1.EtcdInspection{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1alpha1.EtcdInspection), err\n}\n\n// Delete takes name of the etcdInspection and deletes it. Returns an error if one occurs.\nfunc (c *FakeEtcdInspections) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {\n\t_, err := c.Fake.\n\t\tInvokes(testing.NewDeleteAction(etcdinspectionsResource, c.ns, name), &v1alpha1.EtcdInspection{})\n\n\treturn err\n}\n\n// DeleteCollection deletes a collection of objects.\nfunc (c *FakeEtcdInspections) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {\n\taction := testing.NewDeleteCollectionAction(etcdinspectionsResource, c.ns, listOpts)\n\n\t_, err := c.Fake.Invokes(action, &v1alpha1.EtcdInspectionList{})\n\treturn err\n}\n\n// Patch applies the patch and returns the patched etcdInspection.\nfunc (c *FakeEtcdInspections) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.EtcdInspection, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewPatchSubresourceAction(etcdinspectionsResource, c.ns, name, pt, data, subresources...), &v1alpha1.EtcdInspection{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1alpha1.EtcdInspection), err\n}\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/typed/kstone/v1alpha1/fake/fake_kstone_client.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\npackage fake\n\nimport (\n\trest \"k8s.io/client-go/rest\"\n\ttesting \"k8s.io/client-go/testing\"\n\tv1alpha1 \"tkestack.io/kstone/pkg/generated/clientset/versioned/typed/kstone/v1alpha1\"\n)\n\ntype FakeKstoneV1alpha1 struct {\n\t*testing.Fake\n}\n\nfunc (c *FakeKstoneV1alpha1) EtcdClusters(namespace string) v1alpha1.EtcdClusterInterface {\n\treturn &FakeEtcdClusters{c, namespace}\n}\n\nfunc (c *FakeKstoneV1alpha1) EtcdInspections(namespace string) v1alpha1.EtcdInspectionInterface {\n\treturn &FakeEtcdInspections{c, namespace}\n}\n\n// RESTClient returns a RESTClient that is used to communicate\n// with API server by this client implementation.\nfunc (c *FakeKstoneV1alpha1) RESTClient() rest.Interface {\n\tvar ret *rest.RESTClient\n\treturn ret\n}\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/typed/kstone/v1alpha1/generated_expansion.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\npackage v1alpha1\n\ntype EtcdClusterExpansion interface{}\n\ntype EtcdInspectionExpansion interface{}\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/typed/kstone/v1alpha1/kstone_client.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\npackage v1alpha1\n\nimport (\n\trest \"k8s.io/client-go/rest\"\n\tv1alpha1 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha1\"\n\t\"tkestack.io/kstone/pkg/generated/clientset/versioned/scheme\"\n)\n\ntype KstoneV1alpha1Interface interface {\n\tRESTClient() rest.Interface\n\tEtcdClustersGetter\n\tEtcdInspectionsGetter\n}\n\n// KstoneV1alpha1Client is used to interact with features provided by the kstone.tkestack.io group.\ntype KstoneV1alpha1Client struct {\n\trestClient rest.Interface\n}\n\nfunc (c *KstoneV1alpha1Client) EtcdClusters(namespace string) EtcdClusterInterface {\n\treturn newEtcdClusters(c, namespace)\n}\n\nfunc (c *KstoneV1alpha1Client) EtcdInspections(namespace string) EtcdInspectionInterface {\n\treturn newEtcdInspections(c, namespace)\n}\n\n// NewForConfig creates a new KstoneV1alpha1Client for the given config.\nfunc NewForConfig(c *rest.Config) (*KstoneV1alpha1Client, error) {\n\tconfig := *c\n\tif err := setConfigDefaults(&config); err != nil {\n\t\treturn nil, err\n\t}\n\tclient, err := rest.RESTClientFor(&config)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &KstoneV1alpha1Client{client}, nil\n}\n\n// NewForConfigOrDie creates a new KstoneV1alpha1Client for the given config and\n// panics if there is an error in the config.\nfunc NewForConfigOrDie(c *rest.Config) *KstoneV1alpha1Client {\n\tclient, err := NewForConfig(c)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn client\n}\n\n// New creates a new KstoneV1alpha1Client for the given RESTClient.\nfunc New(c rest.Interface) *KstoneV1alpha1Client {\n\treturn &KstoneV1alpha1Client{c}\n}\n\nfunc setConfigDefaults(config *rest.Config) error {\n\tgv := v1alpha1.SchemeGroupVersion\n\tconfig.GroupVersion = &gv\n\tconfig.APIPath = \"/apis\"\n\tconfig.NegotiatedSerializer = scheme.Codecs.WithoutConversion()\n\n\tif config.UserAgent == \"\" {\n\t\tconfig.UserAgent = rest.DefaultKubernetesUserAgent()\n\t}\n\n\treturn nil\n}\n\n// RESTClient returns a RESTClient that is used to communicate\n// with API server by this client implementation.\nfunc (c *KstoneV1alpha1Client) RESTClient() rest.Interface {\n\tif c == nil {\n\t\treturn nil\n\t}\n\treturn c.restClient\n}\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/typed/kstone/v1alpha2/doc.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\n// This package has the automatically generated typed clients.\npackage v1alpha2\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/typed/kstone/v1alpha2/etcdcluster.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\npackage v1alpha2\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\ttypes \"k8s.io/apimachinery/pkg/types\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\trest \"k8s.io/client-go/rest\"\n\tv1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\tscheme \"tkestack.io/kstone/pkg/generated/clientset/versioned/scheme\"\n)\n\n// EtcdClustersGetter has a method to return a EtcdClusterInterface.\n// A group's client should implement this interface.\ntype EtcdClustersGetter interface {\n\tEtcdClusters(namespace string) EtcdClusterInterface\n}\n\n// EtcdClusterInterface has methods to work with EtcdCluster resources.\ntype EtcdClusterInterface interface {\n\tCreate(ctx context.Context, etcdCluster *v1alpha2.EtcdCluster, opts v1.CreateOptions) (*v1alpha2.EtcdCluster, error)\n\tUpdate(ctx context.Context, etcdCluster *v1alpha2.EtcdCluster, opts v1.UpdateOptions) (*v1alpha2.EtcdCluster, error)\n\tUpdateStatus(ctx context.Context, etcdCluster *v1alpha2.EtcdCluster, opts v1.UpdateOptions) (*v1alpha2.EtcdCluster, error)\n\tDelete(ctx context.Context, name string, opts v1.DeleteOptions) error\n\tDeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error\n\tGet(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha2.EtcdCluster, error)\n\tList(ctx context.Context, opts v1.ListOptions) (*v1alpha2.EtcdClusterList, error)\n\tWatch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)\n\tPatch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.EtcdCluster, err error)\n\tEtcdClusterExpansion\n}\n\n// etcdClusters implements EtcdClusterInterface\ntype etcdClusters struct {\n\tclient rest.Interface\n\tns     string\n}\n\n// newEtcdClusters returns a EtcdClusters\nfunc newEtcdClusters(c *KstoneV1alpha2Client, namespace string) *etcdClusters {\n\treturn &etcdClusters{\n\t\tclient: c.RESTClient(),\n\t\tns:     namespace,\n\t}\n}\n\n// Get takes name of the etcdCluster, and returns the corresponding etcdCluster object, and an error if there is any.\nfunc (c *etcdClusters) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.EtcdCluster, err error) {\n\tresult = &v1alpha2.EtcdCluster{}\n\terr = c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tName(name).\n\t\tVersionedParams(&options, scheme.ParameterCodec).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n\n// List takes label and field selectors, and returns the list of EtcdClusters that match those selectors.\nfunc (c *etcdClusters) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.EtcdClusterList, err error) {\n\tvar timeout time.Duration\n\tif opts.TimeoutSeconds != nil {\n\t\ttimeout = time.Duration(*opts.TimeoutSeconds) * time.Second\n\t}\n\tresult = &v1alpha2.EtcdClusterList{}\n\terr = c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tTimeout(timeout).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n\n// Watch returns a watch.Interface that watches the requested etcdClusters.\nfunc (c *etcdClusters) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {\n\tvar timeout time.Duration\n\tif opts.TimeoutSeconds != nil {\n\t\ttimeout = time.Duration(*opts.TimeoutSeconds) * time.Second\n\t}\n\topts.Watch = true\n\treturn c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tTimeout(timeout).\n\t\tWatch(ctx)\n}\n\n// Create takes the representation of a etcdCluster and creates it.  Returns the server's representation of the etcdCluster, and an error, if there is any.\nfunc (c *etcdClusters) Create(ctx context.Context, etcdCluster *v1alpha2.EtcdCluster, opts v1.CreateOptions) (result *v1alpha2.EtcdCluster, err error) {\n\tresult = &v1alpha2.EtcdCluster{}\n\terr = c.client.Post().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tBody(etcdCluster).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n\n// Update takes the representation of a etcdCluster and updates it. Returns the server's representation of the etcdCluster, and an error, if there is any.\nfunc (c *etcdClusters) Update(ctx context.Context, etcdCluster *v1alpha2.EtcdCluster, opts v1.UpdateOptions) (result *v1alpha2.EtcdCluster, err error) {\n\tresult = &v1alpha2.EtcdCluster{}\n\terr = c.client.Put().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tName(etcdCluster.Name).\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tBody(etcdCluster).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n\n// UpdateStatus was generated because the type contains a Status member.\n// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().\nfunc (c *etcdClusters) UpdateStatus(ctx context.Context, etcdCluster *v1alpha2.EtcdCluster, opts v1.UpdateOptions) (result *v1alpha2.EtcdCluster, err error) {\n\tresult = &v1alpha2.EtcdCluster{}\n\terr = c.client.Put().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tName(etcdCluster.Name).\n\t\tSubResource(\"status\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tBody(etcdCluster).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n\n// Delete takes name of the etcdCluster and deletes it. Returns an error if one occurs.\nfunc (c *etcdClusters) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {\n\treturn c.client.Delete().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tName(name).\n\t\tBody(&opts).\n\t\tDo(ctx).\n\t\tError()\n}\n\n// DeleteCollection deletes a collection of objects.\nfunc (c *etcdClusters) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {\n\tvar timeout time.Duration\n\tif listOpts.TimeoutSeconds != nil {\n\t\ttimeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second\n\t}\n\treturn c.client.Delete().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tVersionedParams(&listOpts, scheme.ParameterCodec).\n\t\tTimeout(timeout).\n\t\tBody(&opts).\n\t\tDo(ctx).\n\t\tError()\n}\n\n// Patch applies the patch and returns the patched etcdCluster.\nfunc (c *etcdClusters) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.EtcdCluster, err error) {\n\tresult = &v1alpha2.EtcdCluster{}\n\terr = c.client.Patch(pt).\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tName(name).\n\t\tSubResource(subresources...).\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tBody(data).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/typed/kstone/v1alpha2/etcdinspection.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\npackage v1alpha2\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\ttypes \"k8s.io/apimachinery/pkg/types\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\trest \"k8s.io/client-go/rest\"\n\tv1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\tscheme \"tkestack.io/kstone/pkg/generated/clientset/versioned/scheme\"\n)\n\n// EtcdInspectionsGetter has a method to return a EtcdInspectionInterface.\n// A group's client should implement this interface.\ntype EtcdInspectionsGetter interface {\n\tEtcdInspections(namespace string) EtcdInspectionInterface\n}\n\n// EtcdInspectionInterface has methods to work with EtcdInspection resources.\ntype EtcdInspectionInterface interface {\n\tCreate(ctx context.Context, etcdInspection *v1alpha2.EtcdInspection, opts v1.CreateOptions) (*v1alpha2.EtcdInspection, error)\n\tUpdate(ctx context.Context, etcdInspection *v1alpha2.EtcdInspection, opts v1.UpdateOptions) (*v1alpha2.EtcdInspection, error)\n\tUpdateStatus(ctx context.Context, etcdInspection *v1alpha2.EtcdInspection, opts v1.UpdateOptions) (*v1alpha2.EtcdInspection, error)\n\tDelete(ctx context.Context, name string, opts v1.DeleteOptions) error\n\tDeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error\n\tGet(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha2.EtcdInspection, error)\n\tList(ctx context.Context, opts v1.ListOptions) (*v1alpha2.EtcdInspectionList, error)\n\tWatch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)\n\tPatch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.EtcdInspection, err error)\n\tEtcdInspectionExpansion\n}\n\n// etcdInspections implements EtcdInspectionInterface\ntype etcdInspections struct {\n\tclient rest.Interface\n\tns     string\n}\n\n// newEtcdInspections returns a EtcdInspections\nfunc newEtcdInspections(c *KstoneV1alpha2Client, namespace string) *etcdInspections {\n\treturn &etcdInspections{\n\t\tclient: c.RESTClient(),\n\t\tns:     namespace,\n\t}\n}\n\n// Get takes name of the etcdInspection, and returns the corresponding etcdInspection object, and an error if there is any.\nfunc (c *etcdInspections) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.EtcdInspection, err error) {\n\tresult = &v1alpha2.EtcdInspection{}\n\terr = c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdinspections\").\n\t\tName(name).\n\t\tVersionedParams(&options, scheme.ParameterCodec).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n\n// List takes label and field selectors, and returns the list of EtcdInspections that match those selectors.\nfunc (c *etcdInspections) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.EtcdInspectionList, err error) {\n\tvar timeout time.Duration\n\tif opts.TimeoutSeconds != nil {\n\t\ttimeout = time.Duration(*opts.TimeoutSeconds) * time.Second\n\t}\n\tresult = &v1alpha2.EtcdInspectionList{}\n\terr = c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdinspections\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tTimeout(timeout).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n\n// Watch returns a watch.Interface that watches the requested etcdInspections.\nfunc (c *etcdInspections) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {\n\tvar timeout time.Duration\n\tif opts.TimeoutSeconds != nil {\n\t\ttimeout = time.Duration(*opts.TimeoutSeconds) * time.Second\n\t}\n\topts.Watch = true\n\treturn c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdinspections\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tTimeout(timeout).\n\t\tWatch(ctx)\n}\n\n// Create takes the representation of a etcdInspection and creates it.  Returns the server's representation of the etcdInspection, and an error, if there is any.\nfunc (c *etcdInspections) Create(ctx context.Context, etcdInspection *v1alpha2.EtcdInspection, opts v1.CreateOptions) (result *v1alpha2.EtcdInspection, err error) {\n\tresult = &v1alpha2.EtcdInspection{}\n\terr = c.client.Post().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdinspections\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tBody(etcdInspection).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n\n// Update takes the representation of a etcdInspection and updates it. Returns the server's representation of the etcdInspection, and an error, if there is any.\nfunc (c *etcdInspections) Update(ctx context.Context, etcdInspection *v1alpha2.EtcdInspection, opts v1.UpdateOptions) (result *v1alpha2.EtcdInspection, err error) {\n\tresult = &v1alpha2.EtcdInspection{}\n\terr = c.client.Put().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdinspections\").\n\t\tName(etcdInspection.Name).\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tBody(etcdInspection).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n\n// UpdateStatus was generated because the type contains a Status member.\n// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().\nfunc (c *etcdInspections) UpdateStatus(ctx context.Context, etcdInspection *v1alpha2.EtcdInspection, opts v1.UpdateOptions) (result *v1alpha2.EtcdInspection, err error) {\n\tresult = &v1alpha2.EtcdInspection{}\n\terr = c.client.Put().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdinspections\").\n\t\tName(etcdInspection.Name).\n\t\tSubResource(\"status\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tBody(etcdInspection).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n\n// Delete takes name of the etcdInspection and deletes it. Returns an error if one occurs.\nfunc (c *etcdInspections) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {\n\treturn c.client.Delete().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdinspections\").\n\t\tName(name).\n\t\tBody(&opts).\n\t\tDo(ctx).\n\t\tError()\n}\n\n// DeleteCollection deletes a collection of objects.\nfunc (c *etcdInspections) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {\n\tvar timeout time.Duration\n\tif listOpts.TimeoutSeconds != nil {\n\t\ttimeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second\n\t}\n\treturn c.client.Delete().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdinspections\").\n\t\tVersionedParams(&listOpts, scheme.ParameterCodec).\n\t\tTimeout(timeout).\n\t\tBody(&opts).\n\t\tDo(ctx).\n\t\tError()\n}\n\n// Patch applies the patch and returns the patched etcdInspection.\nfunc (c *etcdInspections) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.EtcdInspection, err error) {\n\tresult = &v1alpha2.EtcdInspection{}\n\terr = c.client.Patch(pt).\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdinspections\").\n\t\tName(name).\n\t\tSubResource(subresources...).\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tBody(data).\n\t\tDo(ctx).\n\t\tInto(result)\n\treturn\n}\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/typed/kstone/v1alpha2/fake/doc.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\n// Package fake has the automatically generated clients.\npackage fake\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/typed/kstone/v1alpha2/fake/fake_etcdcluster.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\npackage fake\n\nimport (\n\t\"context\"\n\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\tlabels \"k8s.io/apimachinery/pkg/labels\"\n\tschema \"k8s.io/apimachinery/pkg/runtime/schema\"\n\ttypes \"k8s.io/apimachinery/pkg/types\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\ttesting \"k8s.io/client-go/testing\"\n\tv1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n)\n\n// FakeEtcdClusters implements EtcdClusterInterface\ntype FakeEtcdClusters struct {\n\tFake *FakeKstoneV1alpha2\n\tns   string\n}\n\nvar etcdclustersResource = schema.GroupVersionResource{Group: \"kstone.tkestack.io\", Version: \"v1alpha2\", Resource: \"etcdclusters\"}\n\nvar etcdclustersKind = schema.GroupVersionKind{Group: \"kstone.tkestack.io\", Version: \"v1alpha2\", Kind: \"EtcdCluster\"}\n\n// Get takes name of the etcdCluster, and returns the corresponding etcdCluster object, and an error if there is any.\nfunc (c *FakeEtcdClusters) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.EtcdCluster, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewGetAction(etcdclustersResource, c.ns, name), &v1alpha2.EtcdCluster{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1alpha2.EtcdCluster), err\n}\n\n// List takes label and field selectors, and returns the list of EtcdClusters that match those selectors.\nfunc (c *FakeEtcdClusters) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.EtcdClusterList, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewListAction(etcdclustersResource, etcdclustersKind, c.ns, opts), &v1alpha2.EtcdClusterList{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\n\tlabel, _, _ := testing.ExtractFromListOptions(opts)\n\tif label == nil {\n\t\tlabel = labels.Everything()\n\t}\n\tlist := &v1alpha2.EtcdClusterList{ListMeta: obj.(*v1alpha2.EtcdClusterList).ListMeta}\n\tfor _, item := range obj.(*v1alpha2.EtcdClusterList).Items {\n\t\tif label.Matches(labels.Set(item.Labels)) {\n\t\t\tlist.Items = append(list.Items, item)\n\t\t}\n\t}\n\treturn list, err\n}\n\n// Watch returns a watch.Interface that watches the requested etcdClusters.\nfunc (c *FakeEtcdClusters) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {\n\treturn c.Fake.\n\t\tInvokesWatch(testing.NewWatchAction(etcdclustersResource, c.ns, opts))\n\n}\n\n// Create takes the representation of a etcdCluster and creates it.  Returns the server's representation of the etcdCluster, and an error, if there is any.\nfunc (c *FakeEtcdClusters) Create(ctx context.Context, etcdCluster *v1alpha2.EtcdCluster, opts v1.CreateOptions) (result *v1alpha2.EtcdCluster, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewCreateAction(etcdclustersResource, c.ns, etcdCluster), &v1alpha2.EtcdCluster{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1alpha2.EtcdCluster), err\n}\n\n// Update takes the representation of a etcdCluster and updates it. Returns the server's representation of the etcdCluster, and an error, if there is any.\nfunc (c *FakeEtcdClusters) Update(ctx context.Context, etcdCluster *v1alpha2.EtcdCluster, opts v1.UpdateOptions) (result *v1alpha2.EtcdCluster, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewUpdateAction(etcdclustersResource, c.ns, etcdCluster), &v1alpha2.EtcdCluster{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1alpha2.EtcdCluster), err\n}\n\n// UpdateStatus was generated because the type contains a Status member.\n// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().\nfunc (c *FakeEtcdClusters) UpdateStatus(ctx context.Context, etcdCluster *v1alpha2.EtcdCluster, opts v1.UpdateOptions) (*v1alpha2.EtcdCluster, error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewUpdateSubresourceAction(etcdclustersResource, \"status\", c.ns, etcdCluster), &v1alpha2.EtcdCluster{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1alpha2.EtcdCluster), err\n}\n\n// Delete takes name of the etcdCluster and deletes it. Returns an error if one occurs.\nfunc (c *FakeEtcdClusters) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {\n\t_, err := c.Fake.\n\t\tInvokes(testing.NewDeleteAction(etcdclustersResource, c.ns, name), &v1alpha2.EtcdCluster{})\n\n\treturn err\n}\n\n// DeleteCollection deletes a collection of objects.\nfunc (c *FakeEtcdClusters) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {\n\taction := testing.NewDeleteCollectionAction(etcdclustersResource, c.ns, listOpts)\n\n\t_, err := c.Fake.Invokes(action, &v1alpha2.EtcdClusterList{})\n\treturn err\n}\n\n// Patch applies the patch and returns the patched etcdCluster.\nfunc (c *FakeEtcdClusters) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.EtcdCluster, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewPatchSubresourceAction(etcdclustersResource, c.ns, name, pt, data, subresources...), &v1alpha2.EtcdCluster{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1alpha2.EtcdCluster), err\n}\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/typed/kstone/v1alpha2/fake/fake_etcdinspection.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\npackage fake\n\nimport (\n\t\"context\"\n\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\tlabels \"k8s.io/apimachinery/pkg/labels\"\n\tschema \"k8s.io/apimachinery/pkg/runtime/schema\"\n\ttypes \"k8s.io/apimachinery/pkg/types\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\ttesting \"k8s.io/client-go/testing\"\n\tv1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n)\n\n// FakeEtcdInspections implements EtcdInspectionInterface\ntype FakeEtcdInspections struct {\n\tFake *FakeKstoneV1alpha2\n\tns   string\n}\n\nvar etcdinspectionsResource = schema.GroupVersionResource{Group: \"kstone.tkestack.io\", Version: \"v1alpha2\", Resource: \"etcdinspections\"}\n\nvar etcdinspectionsKind = schema.GroupVersionKind{Group: \"kstone.tkestack.io\", Version: \"v1alpha2\", Kind: \"EtcdInspection\"}\n\n// Get takes name of the etcdInspection, and returns the corresponding etcdInspection object, and an error if there is any.\nfunc (c *FakeEtcdInspections) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha2.EtcdInspection, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewGetAction(etcdinspectionsResource, c.ns, name), &v1alpha2.EtcdInspection{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1alpha2.EtcdInspection), err\n}\n\n// List takes label and field selectors, and returns the list of EtcdInspections that match those selectors.\nfunc (c *FakeEtcdInspections) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha2.EtcdInspectionList, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewListAction(etcdinspectionsResource, etcdinspectionsKind, c.ns, opts), &v1alpha2.EtcdInspectionList{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\n\tlabel, _, _ := testing.ExtractFromListOptions(opts)\n\tif label == nil {\n\t\tlabel = labels.Everything()\n\t}\n\tlist := &v1alpha2.EtcdInspectionList{ListMeta: obj.(*v1alpha2.EtcdInspectionList).ListMeta}\n\tfor _, item := range obj.(*v1alpha2.EtcdInspectionList).Items {\n\t\tif label.Matches(labels.Set(item.Labels)) {\n\t\t\tlist.Items = append(list.Items, item)\n\t\t}\n\t}\n\treturn list, err\n}\n\n// Watch returns a watch.Interface that watches the requested etcdInspections.\nfunc (c *FakeEtcdInspections) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {\n\treturn c.Fake.\n\t\tInvokesWatch(testing.NewWatchAction(etcdinspectionsResource, c.ns, opts))\n\n}\n\n// Create takes the representation of a etcdInspection and creates it.  Returns the server's representation of the etcdInspection, and an error, if there is any.\nfunc (c *FakeEtcdInspections) Create(ctx context.Context, etcdInspection *v1alpha2.EtcdInspection, opts v1.CreateOptions) (result *v1alpha2.EtcdInspection, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewCreateAction(etcdinspectionsResource, c.ns, etcdInspection), &v1alpha2.EtcdInspection{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1alpha2.EtcdInspection), err\n}\n\n// Update takes the representation of a etcdInspection and updates it. Returns the server's representation of the etcdInspection, and an error, if there is any.\nfunc (c *FakeEtcdInspections) Update(ctx context.Context, etcdInspection *v1alpha2.EtcdInspection, opts v1.UpdateOptions) (result *v1alpha2.EtcdInspection, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewUpdateAction(etcdinspectionsResource, c.ns, etcdInspection), &v1alpha2.EtcdInspection{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1alpha2.EtcdInspection), err\n}\n\n// UpdateStatus was generated because the type contains a Status member.\n// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().\nfunc (c *FakeEtcdInspections) UpdateStatus(ctx context.Context, etcdInspection *v1alpha2.EtcdInspection, opts v1.UpdateOptions) (*v1alpha2.EtcdInspection, error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewUpdateSubresourceAction(etcdinspectionsResource, \"status\", c.ns, etcdInspection), &v1alpha2.EtcdInspection{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1alpha2.EtcdInspection), err\n}\n\n// Delete takes name of the etcdInspection and deletes it. Returns an error if one occurs.\nfunc (c *FakeEtcdInspections) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {\n\t_, err := c.Fake.\n\t\tInvokes(testing.NewDeleteAction(etcdinspectionsResource, c.ns, name), &v1alpha2.EtcdInspection{})\n\n\treturn err\n}\n\n// DeleteCollection deletes a collection of objects.\nfunc (c *FakeEtcdInspections) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {\n\taction := testing.NewDeleteCollectionAction(etcdinspectionsResource, c.ns, listOpts)\n\n\t_, err := c.Fake.Invokes(action, &v1alpha2.EtcdInspectionList{})\n\treturn err\n}\n\n// Patch applies the patch and returns the patched etcdInspection.\nfunc (c *FakeEtcdInspections) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha2.EtcdInspection, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewPatchSubresourceAction(etcdinspectionsResource, c.ns, name, pt, data, subresources...), &v1alpha2.EtcdInspection{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1alpha2.EtcdInspection), err\n}\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/typed/kstone/v1alpha2/fake/fake_kstone_client.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\npackage fake\n\nimport (\n\trest \"k8s.io/client-go/rest\"\n\ttesting \"k8s.io/client-go/testing\"\n\tv1alpha2 \"tkestack.io/kstone/pkg/generated/clientset/versioned/typed/kstone/v1alpha2\"\n)\n\ntype FakeKstoneV1alpha2 struct {\n\t*testing.Fake\n}\n\nfunc (c *FakeKstoneV1alpha2) EtcdClusters(namespace string) v1alpha2.EtcdClusterInterface {\n\treturn &FakeEtcdClusters{c, namespace}\n}\n\nfunc (c *FakeKstoneV1alpha2) EtcdInspections(namespace string) v1alpha2.EtcdInspectionInterface {\n\treturn &FakeEtcdInspections{c, namespace}\n}\n\n// RESTClient returns a RESTClient that is used to communicate\n// with API server by this client implementation.\nfunc (c *FakeKstoneV1alpha2) RESTClient() rest.Interface {\n\tvar ret *rest.RESTClient\n\treturn ret\n}\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/typed/kstone/v1alpha2/generated_expansion.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\npackage v1alpha2\n\ntype EtcdClusterExpansion interface{}\n\ntype EtcdInspectionExpansion interface{}\n"
  },
  {
    "path": "pkg/generated/clientset/versioned/typed/kstone/v1alpha2/kstone_client.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by client-gen. DO NOT EDIT.\n\npackage v1alpha2\n\nimport (\n\trest \"k8s.io/client-go/rest\"\n\tv1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/generated/clientset/versioned/scheme\"\n)\n\ntype KstoneV1alpha2Interface interface {\n\tRESTClient() rest.Interface\n\tEtcdClustersGetter\n\tEtcdInspectionsGetter\n}\n\n// KstoneV1alpha2Client is used to interact with features provided by the kstone.tkestack.io group.\ntype KstoneV1alpha2Client struct {\n\trestClient rest.Interface\n}\n\nfunc (c *KstoneV1alpha2Client) EtcdClusters(namespace string) EtcdClusterInterface {\n\treturn newEtcdClusters(c, namespace)\n}\n\nfunc (c *KstoneV1alpha2Client) EtcdInspections(namespace string) EtcdInspectionInterface {\n\treturn newEtcdInspections(c, namespace)\n}\n\n// NewForConfig creates a new KstoneV1alpha2Client for the given config.\nfunc NewForConfig(c *rest.Config) (*KstoneV1alpha2Client, error) {\n\tconfig := *c\n\tif err := setConfigDefaults(&config); err != nil {\n\t\treturn nil, err\n\t}\n\tclient, err := rest.RESTClientFor(&config)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &KstoneV1alpha2Client{client}, nil\n}\n\n// NewForConfigOrDie creates a new KstoneV1alpha2Client for the given config and\n// panics if there is an error in the config.\nfunc NewForConfigOrDie(c *rest.Config) *KstoneV1alpha2Client {\n\tclient, err := NewForConfig(c)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn client\n}\n\n// New creates a new KstoneV1alpha2Client for the given RESTClient.\nfunc New(c rest.Interface) *KstoneV1alpha2Client {\n\treturn &KstoneV1alpha2Client{c}\n}\n\nfunc setConfigDefaults(config *rest.Config) error {\n\tgv := v1alpha2.SchemeGroupVersion\n\tconfig.GroupVersion = &gv\n\tconfig.APIPath = \"/apis\"\n\tconfig.NegotiatedSerializer = scheme.Codecs.WithoutConversion()\n\n\tif config.UserAgent == \"\" {\n\t\tconfig.UserAgent = rest.DefaultKubernetesUserAgent()\n\t}\n\n\treturn nil\n}\n\n// RESTClient returns a RESTClient that is used to communicate\n// with API server by this client implementation.\nfunc (c *KstoneV1alpha2Client) RESTClient() rest.Interface {\n\tif c == nil {\n\t\treturn nil\n\t}\n\treturn c.restClient\n}\n"
  },
  {
    "path": "pkg/generated/informers/externalversions/factory.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by informer-gen. DO NOT EDIT.\n\npackage externalversions\n\nimport (\n\treflect \"reflect\"\n\tsync \"sync\"\n\ttime \"time\"\n\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n\tschema \"k8s.io/apimachinery/pkg/runtime/schema\"\n\tcache \"k8s.io/client-go/tools/cache\"\n\tversioned \"tkestack.io/kstone/pkg/generated/clientset/versioned\"\n\tinternalinterfaces \"tkestack.io/kstone/pkg/generated/informers/externalversions/internalinterfaces\"\n\tkstone \"tkestack.io/kstone/pkg/generated/informers/externalversions/kstone\"\n)\n\n// SharedInformerOption defines the functional option type for SharedInformerFactory.\ntype SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory\n\ntype sharedInformerFactory struct {\n\tclient           versioned.Interface\n\tnamespace        string\n\ttweakListOptions internalinterfaces.TweakListOptionsFunc\n\tlock             sync.Mutex\n\tdefaultResync    time.Duration\n\tcustomResync     map[reflect.Type]time.Duration\n\n\tinformers map[reflect.Type]cache.SharedIndexInformer\n\t// startedInformers is used for tracking which informers have been started.\n\t// This allows Start() to be called multiple times safely.\n\tstartedInformers map[reflect.Type]bool\n}\n\n// WithCustomResyncConfig sets a custom resync period for the specified informer types.\nfunc WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption {\n\treturn func(factory *sharedInformerFactory) *sharedInformerFactory {\n\t\tfor k, v := range resyncConfig {\n\t\t\tfactory.customResync[reflect.TypeOf(k)] = v\n\t\t}\n\t\treturn factory\n\t}\n}\n\n// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory.\nfunc WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption {\n\treturn func(factory *sharedInformerFactory) *sharedInformerFactory {\n\t\tfactory.tweakListOptions = tweakListOptions\n\t\treturn factory\n\t}\n}\n\n// WithNamespace limits the SharedInformerFactory to the specified namespace.\nfunc WithNamespace(namespace string) SharedInformerOption {\n\treturn func(factory *sharedInformerFactory) *sharedInformerFactory {\n\t\tfactory.namespace = namespace\n\t\treturn factory\n\t}\n}\n\n// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces.\nfunc NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory {\n\treturn NewSharedInformerFactoryWithOptions(client, defaultResync)\n}\n\n// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory.\n// Listers obtained via this SharedInformerFactory will be subject to the same filters\n// as specified here.\n// Deprecated: Please use NewSharedInformerFactoryWithOptions instead\nfunc NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory {\n\treturn NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions))\n}\n\n// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options.\nfunc NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory {\n\tfactory := &sharedInformerFactory{\n\t\tclient:           client,\n\t\tnamespace:        v1.NamespaceAll,\n\t\tdefaultResync:    defaultResync,\n\t\tinformers:        make(map[reflect.Type]cache.SharedIndexInformer),\n\t\tstartedInformers: make(map[reflect.Type]bool),\n\t\tcustomResync:     make(map[reflect.Type]time.Duration),\n\t}\n\n\t// Apply all options\n\tfor _, opt := range options {\n\t\tfactory = opt(factory)\n\t}\n\n\treturn factory\n}\n\n// Start initializes all requested informers.\nfunc (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {\n\tf.lock.Lock()\n\tdefer f.lock.Unlock()\n\n\tfor informerType, informer := range f.informers {\n\t\tif !f.startedInformers[informerType] {\n\t\t\tgo informer.Run(stopCh)\n\t\t\tf.startedInformers[informerType] = true\n\t\t}\n\t}\n}\n\n// WaitForCacheSync waits for all started informers' cache were synced.\nfunc (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool {\n\tinformers := func() map[reflect.Type]cache.SharedIndexInformer {\n\t\tf.lock.Lock()\n\t\tdefer f.lock.Unlock()\n\n\t\tinformers := map[reflect.Type]cache.SharedIndexInformer{}\n\t\tfor informerType, informer := range f.informers {\n\t\t\tif f.startedInformers[informerType] {\n\t\t\t\tinformers[informerType] = informer\n\t\t\t}\n\t\t}\n\t\treturn informers\n\t}()\n\n\tres := map[reflect.Type]bool{}\n\tfor informType, informer := range informers {\n\t\tres[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)\n\t}\n\treturn res\n}\n\n// InternalInformerFor returns the SharedIndexInformer for obj using an internal\n// client.\nfunc (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer {\n\tf.lock.Lock()\n\tdefer f.lock.Unlock()\n\n\tinformerType := reflect.TypeOf(obj)\n\tinformer, exists := f.informers[informerType]\n\tif exists {\n\t\treturn informer\n\t}\n\n\tresyncPeriod, exists := f.customResync[informerType]\n\tif !exists {\n\t\tresyncPeriod = f.defaultResync\n\t}\n\n\tinformer = newFunc(f.client, resyncPeriod)\n\tf.informers[informerType] = informer\n\n\treturn informer\n}\n\n// SharedInformerFactory provides shared informers for resources in all known\n// API group versions.\ntype SharedInformerFactory interface {\n\tinternalinterfaces.SharedInformerFactory\n\tForResource(resource schema.GroupVersionResource) (GenericInformer, error)\n\tWaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool\n\n\tKstone() kstone.Interface\n}\n\nfunc (f *sharedInformerFactory) Kstone() kstone.Interface {\n\treturn kstone.New(f, f.namespace, f.tweakListOptions)\n}\n"
  },
  {
    "path": "pkg/generated/informers/externalversions/generic.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by informer-gen. DO NOT EDIT.\n\npackage externalversions\n\nimport (\n\t\"fmt\"\n\n\tschema \"k8s.io/apimachinery/pkg/runtime/schema\"\n\tcache \"k8s.io/client-go/tools/cache\"\n\tv1alpha1 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha1\"\n\tv1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n)\n\n// GenericInformer is type of SharedIndexInformer which will locate and delegate to other\n// sharedInformers based on type\ntype GenericInformer interface {\n\tInformer() cache.SharedIndexInformer\n\tLister() cache.GenericLister\n}\n\ntype genericInformer struct {\n\tinformer cache.SharedIndexInformer\n\tresource schema.GroupResource\n}\n\n// Informer returns the SharedIndexInformer.\nfunc (f *genericInformer) Informer() cache.SharedIndexInformer {\n\treturn f.informer\n}\n\n// Lister returns the GenericLister.\nfunc (f *genericInformer) Lister() cache.GenericLister {\n\treturn cache.NewGenericLister(f.Informer().GetIndexer(), f.resource)\n}\n\n// ForResource gives generic access to a shared informer of the matching type\n// TODO extend this to unknown resources with a client pool\nfunc (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {\n\tswitch resource {\n\t// Group=kstone.tkestack.io, Version=v1alpha1\n\tcase v1alpha1.SchemeGroupVersion.WithResource(\"etcdclusters\"):\n\t\treturn &genericInformer{resource: resource.GroupResource(), informer: f.Kstone().V1alpha1().EtcdClusters().Informer()}, nil\n\tcase v1alpha1.SchemeGroupVersion.WithResource(\"etcdinspections\"):\n\t\treturn &genericInformer{resource: resource.GroupResource(), informer: f.Kstone().V1alpha1().EtcdInspections().Informer()}, nil\n\n\t\t// Group=kstone.tkestack.io, Version=v1alpha2\n\tcase v1alpha2.SchemeGroupVersion.WithResource(\"etcdclusters\"):\n\t\treturn &genericInformer{resource: resource.GroupResource(), informer: f.Kstone().V1alpha2().EtcdClusters().Informer()}, nil\n\tcase v1alpha2.SchemeGroupVersion.WithResource(\"etcdinspections\"):\n\t\treturn &genericInformer{resource: resource.GroupResource(), informer: f.Kstone().V1alpha2().EtcdInspections().Informer()}, nil\n\n\t}\n\n\treturn nil, fmt.Errorf(\"no informer found for %v\", resource)\n}\n"
  },
  {
    "path": "pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by informer-gen. DO NOT EDIT.\n\npackage internalinterfaces\n\nimport (\n\ttime \"time\"\n\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n\tcache \"k8s.io/client-go/tools/cache\"\n\tversioned \"tkestack.io/kstone/pkg/generated/clientset/versioned\"\n)\n\n// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer.\ntype NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer\n\n// SharedInformerFactory a small interface to allow for adding an informer without an import cycle\ntype SharedInformerFactory interface {\n\tStart(stopCh <-chan struct{})\n\tInformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer\n}\n\n// TweakListOptionsFunc is a function that transforms a v1.ListOptions.\ntype TweakListOptionsFunc func(*v1.ListOptions)\n"
  },
  {
    "path": "pkg/generated/informers/externalversions/kstone/interface.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by informer-gen. DO NOT EDIT.\n\npackage kstone\n\nimport (\n\tinternalinterfaces \"tkestack.io/kstone/pkg/generated/informers/externalversions/internalinterfaces\"\n\tv1alpha1 \"tkestack.io/kstone/pkg/generated/informers/externalversions/kstone/v1alpha1\"\n\tv1alpha2 \"tkestack.io/kstone/pkg/generated/informers/externalversions/kstone/v1alpha2\"\n)\n\n// Interface provides access to each of this group's versions.\ntype Interface interface {\n\t// V1alpha1 provides access to shared informers for resources in V1alpha1.\n\tV1alpha1() v1alpha1.Interface\n\t// V1alpha2 provides access to shared informers for resources in V1alpha2.\n\tV1alpha2() v1alpha2.Interface\n}\n\ntype group struct {\n\tfactory          internalinterfaces.SharedInformerFactory\n\tnamespace        string\n\ttweakListOptions internalinterfaces.TweakListOptionsFunc\n}\n\n// New returns a new Interface.\nfunc New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {\n\treturn &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}\n}\n\n// V1alpha1 returns a new v1alpha1.Interface.\nfunc (g *group) V1alpha1() v1alpha1.Interface {\n\treturn v1alpha1.New(g.factory, g.namespace, g.tweakListOptions)\n}\n\n// V1alpha2 returns a new v1alpha2.Interface.\nfunc (g *group) V1alpha2() v1alpha2.Interface {\n\treturn v1alpha2.New(g.factory, g.namespace, g.tweakListOptions)\n}\n"
  },
  {
    "path": "pkg/generated/informers/externalversions/kstone/v1alpha1/etcdcluster.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by informer-gen. DO NOT EDIT.\n\npackage v1alpha1\n\nimport (\n\t\"context\"\n\ttime \"time\"\n\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\tcache \"k8s.io/client-go/tools/cache\"\n\tkstonev1alpha1 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha1\"\n\tversioned \"tkestack.io/kstone/pkg/generated/clientset/versioned\"\n\tinternalinterfaces \"tkestack.io/kstone/pkg/generated/informers/externalversions/internalinterfaces\"\n\tv1alpha1 \"tkestack.io/kstone/pkg/generated/listers/kstone/v1alpha1\"\n)\n\n// EtcdClusterInformer provides access to a shared informer and lister for\n// EtcdClusters.\ntype EtcdClusterInformer interface {\n\tInformer() cache.SharedIndexInformer\n\tLister() v1alpha1.EtcdClusterLister\n}\n\ntype etcdClusterInformer struct {\n\tfactory          internalinterfaces.SharedInformerFactory\n\ttweakListOptions internalinterfaces.TweakListOptionsFunc\n\tnamespace        string\n}\n\n// NewEtcdClusterInformer constructs a new informer for EtcdCluster type.\n// Always prefer using an informer factory to get a shared informer instead of getting an independent\n// one. This reduces memory footprint and number of connections to the server.\nfunc NewEtcdClusterInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {\n\treturn NewFilteredEtcdClusterInformer(client, namespace, resyncPeriod, indexers, nil)\n}\n\n// NewFilteredEtcdClusterInformer constructs a new informer for EtcdCluster type.\n// Always prefer using an informer factory to get a shared informer instead of getting an independent\n// one. This reduces memory footprint and number of connections to the server.\nfunc NewFilteredEtcdClusterInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {\n\treturn cache.NewSharedIndexInformer(\n\t\t&cache.ListWatch{\n\t\t\tListFunc: func(options v1.ListOptions) (runtime.Object, error) {\n\t\t\t\tif tweakListOptions != nil {\n\t\t\t\t\ttweakListOptions(&options)\n\t\t\t\t}\n\t\t\t\treturn client.KstoneV1alpha1().EtcdClusters(namespace).List(context.TODO(), options)\n\t\t\t},\n\t\t\tWatchFunc: func(options v1.ListOptions) (watch.Interface, error) {\n\t\t\t\tif tweakListOptions != nil {\n\t\t\t\t\ttweakListOptions(&options)\n\t\t\t\t}\n\t\t\t\treturn client.KstoneV1alpha1().EtcdClusters(namespace).Watch(context.TODO(), options)\n\t\t\t},\n\t\t},\n\t\t&kstonev1alpha1.EtcdCluster{},\n\t\tresyncPeriod,\n\t\tindexers,\n\t)\n}\n\nfunc (f *etcdClusterInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {\n\treturn NewFilteredEtcdClusterInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)\n}\n\nfunc (f *etcdClusterInformer) Informer() cache.SharedIndexInformer {\n\treturn f.factory.InformerFor(&kstonev1alpha1.EtcdCluster{}, f.defaultInformer)\n}\n\nfunc (f *etcdClusterInformer) Lister() v1alpha1.EtcdClusterLister {\n\treturn v1alpha1.NewEtcdClusterLister(f.Informer().GetIndexer())\n}\n"
  },
  {
    "path": "pkg/generated/informers/externalversions/kstone/v1alpha1/etcdinspection.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by informer-gen. DO NOT EDIT.\n\npackage v1alpha1\n\nimport (\n\t\"context\"\n\ttime \"time\"\n\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\tcache \"k8s.io/client-go/tools/cache\"\n\tkstonev1alpha1 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha1\"\n\tversioned \"tkestack.io/kstone/pkg/generated/clientset/versioned\"\n\tinternalinterfaces \"tkestack.io/kstone/pkg/generated/informers/externalversions/internalinterfaces\"\n\tv1alpha1 \"tkestack.io/kstone/pkg/generated/listers/kstone/v1alpha1\"\n)\n\n// EtcdInspectionInformer provides access to a shared informer and lister for\n// EtcdInspections.\ntype EtcdInspectionInformer interface {\n\tInformer() cache.SharedIndexInformer\n\tLister() v1alpha1.EtcdInspectionLister\n}\n\ntype etcdInspectionInformer struct {\n\tfactory          internalinterfaces.SharedInformerFactory\n\ttweakListOptions internalinterfaces.TweakListOptionsFunc\n\tnamespace        string\n}\n\n// NewEtcdInspectionInformer constructs a new informer for EtcdInspection type.\n// Always prefer using an informer factory to get a shared informer instead of getting an independent\n// one. This reduces memory footprint and number of connections to the server.\nfunc NewEtcdInspectionInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {\n\treturn NewFilteredEtcdInspectionInformer(client, namespace, resyncPeriod, indexers, nil)\n}\n\n// NewFilteredEtcdInspectionInformer constructs a new informer for EtcdInspection type.\n// Always prefer using an informer factory to get a shared informer instead of getting an independent\n// one. This reduces memory footprint and number of connections to the server.\nfunc NewFilteredEtcdInspectionInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {\n\treturn cache.NewSharedIndexInformer(\n\t\t&cache.ListWatch{\n\t\t\tListFunc: func(options v1.ListOptions) (runtime.Object, error) {\n\t\t\t\tif tweakListOptions != nil {\n\t\t\t\t\ttweakListOptions(&options)\n\t\t\t\t}\n\t\t\t\treturn client.KstoneV1alpha1().EtcdInspections(namespace).List(context.TODO(), options)\n\t\t\t},\n\t\t\tWatchFunc: func(options v1.ListOptions) (watch.Interface, error) {\n\t\t\t\tif tweakListOptions != nil {\n\t\t\t\t\ttweakListOptions(&options)\n\t\t\t\t}\n\t\t\t\treturn client.KstoneV1alpha1().EtcdInspections(namespace).Watch(context.TODO(), options)\n\t\t\t},\n\t\t},\n\t\t&kstonev1alpha1.EtcdInspection{},\n\t\tresyncPeriod,\n\t\tindexers,\n\t)\n}\n\nfunc (f *etcdInspectionInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {\n\treturn NewFilteredEtcdInspectionInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)\n}\n\nfunc (f *etcdInspectionInformer) Informer() cache.SharedIndexInformer {\n\treturn f.factory.InformerFor(&kstonev1alpha1.EtcdInspection{}, f.defaultInformer)\n}\n\nfunc (f *etcdInspectionInformer) Lister() v1alpha1.EtcdInspectionLister {\n\treturn v1alpha1.NewEtcdInspectionLister(f.Informer().GetIndexer())\n}\n"
  },
  {
    "path": "pkg/generated/informers/externalversions/kstone/v1alpha1/interface.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by informer-gen. DO NOT EDIT.\n\npackage v1alpha1\n\nimport (\n\tinternalinterfaces \"tkestack.io/kstone/pkg/generated/informers/externalversions/internalinterfaces\"\n)\n\n// Interface provides access to all the informers in this group version.\ntype Interface interface {\n\t// EtcdClusters returns a EtcdClusterInformer.\n\tEtcdClusters() EtcdClusterInformer\n\t// EtcdInspections returns a EtcdInspectionInformer.\n\tEtcdInspections() EtcdInspectionInformer\n}\n\ntype version struct {\n\tfactory          internalinterfaces.SharedInformerFactory\n\tnamespace        string\n\ttweakListOptions internalinterfaces.TweakListOptionsFunc\n}\n\n// New returns a new Interface.\nfunc New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {\n\treturn &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}\n}\n\n// EtcdClusters returns a EtcdClusterInformer.\nfunc (v *version) EtcdClusters() EtcdClusterInformer {\n\treturn &etcdClusterInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}\n}\n\n// EtcdInspections returns a EtcdInspectionInformer.\nfunc (v *version) EtcdInspections() EtcdInspectionInformer {\n\treturn &etcdInspectionInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}\n}\n"
  },
  {
    "path": "pkg/generated/informers/externalversions/kstone/v1alpha2/etcdcluster.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by informer-gen. DO NOT EDIT.\n\npackage v1alpha2\n\nimport (\n\t\"context\"\n\ttime \"time\"\n\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\tcache \"k8s.io/client-go/tools/cache\"\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\tversioned \"tkestack.io/kstone/pkg/generated/clientset/versioned\"\n\tinternalinterfaces \"tkestack.io/kstone/pkg/generated/informers/externalversions/internalinterfaces\"\n\tv1alpha2 \"tkestack.io/kstone/pkg/generated/listers/kstone/v1alpha2\"\n)\n\n// EtcdClusterInformer provides access to a shared informer and lister for\n// EtcdClusters.\ntype EtcdClusterInformer interface {\n\tInformer() cache.SharedIndexInformer\n\tLister() v1alpha2.EtcdClusterLister\n}\n\ntype etcdClusterInformer struct {\n\tfactory          internalinterfaces.SharedInformerFactory\n\ttweakListOptions internalinterfaces.TweakListOptionsFunc\n\tnamespace        string\n}\n\n// NewEtcdClusterInformer constructs a new informer for EtcdCluster type.\n// Always prefer using an informer factory to get a shared informer instead of getting an independent\n// one. This reduces memory footprint and number of connections to the server.\nfunc NewEtcdClusterInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {\n\treturn NewFilteredEtcdClusterInformer(client, namespace, resyncPeriod, indexers, nil)\n}\n\n// NewFilteredEtcdClusterInformer constructs a new informer for EtcdCluster type.\n// Always prefer using an informer factory to get a shared informer instead of getting an independent\n// one. This reduces memory footprint and number of connections to the server.\nfunc NewFilteredEtcdClusterInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {\n\treturn cache.NewSharedIndexInformer(\n\t\t&cache.ListWatch{\n\t\t\tListFunc: func(options v1.ListOptions) (runtime.Object, error) {\n\t\t\t\tif tweakListOptions != nil {\n\t\t\t\t\ttweakListOptions(&options)\n\t\t\t\t}\n\t\t\t\treturn client.KstoneV1alpha2().EtcdClusters(namespace).List(context.TODO(), options)\n\t\t\t},\n\t\t\tWatchFunc: func(options v1.ListOptions) (watch.Interface, error) {\n\t\t\t\tif tweakListOptions != nil {\n\t\t\t\t\ttweakListOptions(&options)\n\t\t\t\t}\n\t\t\t\treturn client.KstoneV1alpha2().EtcdClusters(namespace).Watch(context.TODO(), options)\n\t\t\t},\n\t\t},\n\t\t&kstonev1alpha2.EtcdCluster{},\n\t\tresyncPeriod,\n\t\tindexers,\n\t)\n}\n\nfunc (f *etcdClusterInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {\n\treturn NewFilteredEtcdClusterInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)\n}\n\nfunc (f *etcdClusterInformer) Informer() cache.SharedIndexInformer {\n\treturn f.factory.InformerFor(&kstonev1alpha2.EtcdCluster{}, f.defaultInformer)\n}\n\nfunc (f *etcdClusterInformer) Lister() v1alpha2.EtcdClusterLister {\n\treturn v1alpha2.NewEtcdClusterLister(f.Informer().GetIndexer())\n}\n"
  },
  {
    "path": "pkg/generated/informers/externalversions/kstone/v1alpha2/etcdinspection.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by informer-gen. DO NOT EDIT.\n\npackage v1alpha2\n\nimport (\n\t\"context\"\n\ttime \"time\"\n\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\tcache \"k8s.io/client-go/tools/cache\"\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\tversioned \"tkestack.io/kstone/pkg/generated/clientset/versioned\"\n\tinternalinterfaces \"tkestack.io/kstone/pkg/generated/informers/externalversions/internalinterfaces\"\n\tv1alpha2 \"tkestack.io/kstone/pkg/generated/listers/kstone/v1alpha2\"\n)\n\n// EtcdInspectionInformer provides access to a shared informer and lister for\n// EtcdInspections.\ntype EtcdInspectionInformer interface {\n\tInformer() cache.SharedIndexInformer\n\tLister() v1alpha2.EtcdInspectionLister\n}\n\ntype etcdInspectionInformer struct {\n\tfactory          internalinterfaces.SharedInformerFactory\n\ttweakListOptions internalinterfaces.TweakListOptionsFunc\n\tnamespace        string\n}\n\n// NewEtcdInspectionInformer constructs a new informer for EtcdInspection type.\n// Always prefer using an informer factory to get a shared informer instead of getting an independent\n// one. This reduces memory footprint and number of connections to the server.\nfunc NewEtcdInspectionInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {\n\treturn NewFilteredEtcdInspectionInformer(client, namespace, resyncPeriod, indexers, nil)\n}\n\n// NewFilteredEtcdInspectionInformer constructs a new informer for EtcdInspection type.\n// Always prefer using an informer factory to get a shared informer instead of getting an independent\n// one. This reduces memory footprint and number of connections to the server.\nfunc NewFilteredEtcdInspectionInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {\n\treturn cache.NewSharedIndexInformer(\n\t\t&cache.ListWatch{\n\t\t\tListFunc: func(options v1.ListOptions) (runtime.Object, error) {\n\t\t\t\tif tweakListOptions != nil {\n\t\t\t\t\ttweakListOptions(&options)\n\t\t\t\t}\n\t\t\t\treturn client.KstoneV1alpha2().EtcdInspections(namespace).List(context.TODO(), options)\n\t\t\t},\n\t\t\tWatchFunc: func(options v1.ListOptions) (watch.Interface, error) {\n\t\t\t\tif tweakListOptions != nil {\n\t\t\t\t\ttweakListOptions(&options)\n\t\t\t\t}\n\t\t\t\treturn client.KstoneV1alpha2().EtcdInspections(namespace).Watch(context.TODO(), options)\n\t\t\t},\n\t\t},\n\t\t&kstonev1alpha2.EtcdInspection{},\n\t\tresyncPeriod,\n\t\tindexers,\n\t)\n}\n\nfunc (f *etcdInspectionInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {\n\treturn NewFilteredEtcdInspectionInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)\n}\n\nfunc (f *etcdInspectionInformer) Informer() cache.SharedIndexInformer {\n\treturn f.factory.InformerFor(&kstonev1alpha2.EtcdInspection{}, f.defaultInformer)\n}\n\nfunc (f *etcdInspectionInformer) Lister() v1alpha2.EtcdInspectionLister {\n\treturn v1alpha2.NewEtcdInspectionLister(f.Informer().GetIndexer())\n}\n"
  },
  {
    "path": "pkg/generated/informers/externalversions/kstone/v1alpha2/interface.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by informer-gen. DO NOT EDIT.\n\npackage v1alpha2\n\nimport (\n\tinternalinterfaces \"tkestack.io/kstone/pkg/generated/informers/externalversions/internalinterfaces\"\n)\n\n// Interface provides access to all the informers in this group version.\ntype Interface interface {\n\t// EtcdClusters returns a EtcdClusterInformer.\n\tEtcdClusters() EtcdClusterInformer\n\t// EtcdInspections returns a EtcdInspectionInformer.\n\tEtcdInspections() EtcdInspectionInformer\n}\n\ntype version struct {\n\tfactory          internalinterfaces.SharedInformerFactory\n\tnamespace        string\n\ttweakListOptions internalinterfaces.TweakListOptionsFunc\n}\n\n// New returns a new Interface.\nfunc New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {\n\treturn &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}\n}\n\n// EtcdClusters returns a EtcdClusterInformer.\nfunc (v *version) EtcdClusters() EtcdClusterInformer {\n\treturn &etcdClusterInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}\n}\n\n// EtcdInspections returns a EtcdInspectionInformer.\nfunc (v *version) EtcdInspections() EtcdInspectionInformer {\n\treturn &etcdInspectionInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}\n}\n"
  },
  {
    "path": "pkg/generated/listers/kstone/v1alpha1/etcdcluster.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by lister-gen. DO NOT EDIT.\n\npackage v1alpha1\n\nimport (\n\t\"k8s.io/apimachinery/pkg/api/errors\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n\t\"k8s.io/client-go/tools/cache\"\n\tv1alpha1 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha1\"\n)\n\n// EtcdClusterLister helps list EtcdClusters.\n// All objects returned here must be treated as read-only.\ntype EtcdClusterLister interface {\n\t// List lists all EtcdClusters in the indexer.\n\t// Objects returned here must be treated as read-only.\n\tList(selector labels.Selector) (ret []*v1alpha1.EtcdCluster, err error)\n\t// EtcdClusters returns an object that can list and get EtcdClusters.\n\tEtcdClusters(namespace string) EtcdClusterNamespaceLister\n\tEtcdClusterListerExpansion\n}\n\n// etcdClusterLister implements the EtcdClusterLister interface.\ntype etcdClusterLister struct {\n\tindexer cache.Indexer\n}\n\n// NewEtcdClusterLister returns a new EtcdClusterLister.\nfunc NewEtcdClusterLister(indexer cache.Indexer) EtcdClusterLister {\n\treturn &etcdClusterLister{indexer: indexer}\n}\n\n// List lists all EtcdClusters in the indexer.\nfunc (s *etcdClusterLister) List(selector labels.Selector) (ret []*v1alpha1.EtcdCluster, err error) {\n\terr = cache.ListAll(s.indexer, selector, func(m interface{}) {\n\t\tret = append(ret, m.(*v1alpha1.EtcdCluster))\n\t})\n\treturn ret, err\n}\n\n// EtcdClusters returns an object that can list and get EtcdClusters.\nfunc (s *etcdClusterLister) EtcdClusters(namespace string) EtcdClusterNamespaceLister {\n\treturn etcdClusterNamespaceLister{indexer: s.indexer, namespace: namespace}\n}\n\n// EtcdClusterNamespaceLister helps list and get EtcdClusters.\n// All objects returned here must be treated as read-only.\ntype EtcdClusterNamespaceLister interface {\n\t// List lists all EtcdClusters in the indexer for a given namespace.\n\t// Objects returned here must be treated as read-only.\n\tList(selector labels.Selector) (ret []*v1alpha1.EtcdCluster, err error)\n\t// Get retrieves the EtcdCluster from the indexer for a given namespace and name.\n\t// Objects returned here must be treated as read-only.\n\tGet(name string) (*v1alpha1.EtcdCluster, error)\n\tEtcdClusterNamespaceListerExpansion\n}\n\n// etcdClusterNamespaceLister implements the EtcdClusterNamespaceLister\n// interface.\ntype etcdClusterNamespaceLister struct {\n\tindexer   cache.Indexer\n\tnamespace string\n}\n\n// List lists all EtcdClusters in the indexer for a given namespace.\nfunc (s etcdClusterNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.EtcdCluster, err error) {\n\terr = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {\n\t\tret = append(ret, m.(*v1alpha1.EtcdCluster))\n\t})\n\treturn ret, err\n}\n\n// Get retrieves the EtcdCluster from the indexer for a given namespace and name.\nfunc (s etcdClusterNamespaceLister) Get(name string) (*v1alpha1.EtcdCluster, error) {\n\tobj, exists, err := s.indexer.GetByKey(s.namespace + \"/\" + name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif !exists {\n\t\treturn nil, errors.NewNotFound(v1alpha1.Resource(\"etcdcluster\"), name)\n\t}\n\treturn obj.(*v1alpha1.EtcdCluster), nil\n}\n"
  },
  {
    "path": "pkg/generated/listers/kstone/v1alpha1/etcdinspection.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by lister-gen. DO NOT EDIT.\n\npackage v1alpha1\n\nimport (\n\t\"k8s.io/apimachinery/pkg/api/errors\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n\t\"k8s.io/client-go/tools/cache\"\n\tv1alpha1 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha1\"\n)\n\n// EtcdInspectionLister helps list EtcdInspections.\n// All objects returned here must be treated as read-only.\ntype EtcdInspectionLister interface {\n\t// List lists all EtcdInspections in the indexer.\n\t// Objects returned here must be treated as read-only.\n\tList(selector labels.Selector) (ret []*v1alpha1.EtcdInspection, err error)\n\t// EtcdInspections returns an object that can list and get EtcdInspections.\n\tEtcdInspections(namespace string) EtcdInspectionNamespaceLister\n\tEtcdInspectionListerExpansion\n}\n\n// etcdInspectionLister implements the EtcdInspectionLister interface.\ntype etcdInspectionLister struct {\n\tindexer cache.Indexer\n}\n\n// NewEtcdInspectionLister returns a new EtcdInspectionLister.\nfunc NewEtcdInspectionLister(indexer cache.Indexer) EtcdInspectionLister {\n\treturn &etcdInspectionLister{indexer: indexer}\n}\n\n// List lists all EtcdInspections in the indexer.\nfunc (s *etcdInspectionLister) List(selector labels.Selector) (ret []*v1alpha1.EtcdInspection, err error) {\n\terr = cache.ListAll(s.indexer, selector, func(m interface{}) {\n\t\tret = append(ret, m.(*v1alpha1.EtcdInspection))\n\t})\n\treturn ret, err\n}\n\n// EtcdInspections returns an object that can list and get EtcdInspections.\nfunc (s *etcdInspectionLister) EtcdInspections(namespace string) EtcdInspectionNamespaceLister {\n\treturn etcdInspectionNamespaceLister{indexer: s.indexer, namespace: namespace}\n}\n\n// EtcdInspectionNamespaceLister helps list and get EtcdInspections.\n// All objects returned here must be treated as read-only.\ntype EtcdInspectionNamespaceLister interface {\n\t// List lists all EtcdInspections in the indexer for a given namespace.\n\t// Objects returned here must be treated as read-only.\n\tList(selector labels.Selector) (ret []*v1alpha1.EtcdInspection, err error)\n\t// Get retrieves the EtcdInspection from the indexer for a given namespace and name.\n\t// Objects returned here must be treated as read-only.\n\tGet(name string) (*v1alpha1.EtcdInspection, error)\n\tEtcdInspectionNamespaceListerExpansion\n}\n\n// etcdInspectionNamespaceLister implements the EtcdInspectionNamespaceLister\n// interface.\ntype etcdInspectionNamespaceLister struct {\n\tindexer   cache.Indexer\n\tnamespace string\n}\n\n// List lists all EtcdInspections in the indexer for a given namespace.\nfunc (s etcdInspectionNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.EtcdInspection, err error) {\n\terr = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {\n\t\tret = append(ret, m.(*v1alpha1.EtcdInspection))\n\t})\n\treturn ret, err\n}\n\n// Get retrieves the EtcdInspection from the indexer for a given namespace and name.\nfunc (s etcdInspectionNamespaceLister) Get(name string) (*v1alpha1.EtcdInspection, error) {\n\tobj, exists, err := s.indexer.GetByKey(s.namespace + \"/\" + name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif !exists {\n\t\treturn nil, errors.NewNotFound(v1alpha1.Resource(\"etcdinspection\"), name)\n\t}\n\treturn obj.(*v1alpha1.EtcdInspection), nil\n}\n"
  },
  {
    "path": "pkg/generated/listers/kstone/v1alpha1/expansion_generated.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by lister-gen. DO NOT EDIT.\n\npackage v1alpha1\n\n// EtcdClusterListerExpansion allows custom methods to be added to\n// EtcdClusterLister.\ntype EtcdClusterListerExpansion interface{}\n\n// EtcdClusterNamespaceListerExpansion allows custom methods to be added to\n// EtcdClusterNamespaceLister.\ntype EtcdClusterNamespaceListerExpansion interface{}\n\n// EtcdInspectionListerExpansion allows custom methods to be added to\n// EtcdInspectionLister.\ntype EtcdInspectionListerExpansion interface{}\n\n// EtcdInspectionNamespaceListerExpansion allows custom methods to be added to\n// EtcdInspectionNamespaceLister.\ntype EtcdInspectionNamespaceListerExpansion interface{}\n"
  },
  {
    "path": "pkg/generated/listers/kstone/v1alpha2/etcdcluster.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by lister-gen. DO NOT EDIT.\n\npackage v1alpha2\n\nimport (\n\t\"k8s.io/apimachinery/pkg/api/errors\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n\t\"k8s.io/client-go/tools/cache\"\n\tv1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n)\n\n// EtcdClusterLister helps list EtcdClusters.\n// All objects returned here must be treated as read-only.\ntype EtcdClusterLister interface {\n\t// List lists all EtcdClusters in the indexer.\n\t// Objects returned here must be treated as read-only.\n\tList(selector labels.Selector) (ret []*v1alpha2.EtcdCluster, err error)\n\t// EtcdClusters returns an object that can list and get EtcdClusters.\n\tEtcdClusters(namespace string) EtcdClusterNamespaceLister\n\tEtcdClusterListerExpansion\n}\n\n// etcdClusterLister implements the EtcdClusterLister interface.\ntype etcdClusterLister struct {\n\tindexer cache.Indexer\n}\n\n// NewEtcdClusterLister returns a new EtcdClusterLister.\nfunc NewEtcdClusterLister(indexer cache.Indexer) EtcdClusterLister {\n\treturn &etcdClusterLister{indexer: indexer}\n}\n\n// List lists all EtcdClusters in the indexer.\nfunc (s *etcdClusterLister) List(selector labels.Selector) (ret []*v1alpha2.EtcdCluster, err error) {\n\terr = cache.ListAll(s.indexer, selector, func(m interface{}) {\n\t\tret = append(ret, m.(*v1alpha2.EtcdCluster))\n\t})\n\treturn ret, err\n}\n\n// EtcdClusters returns an object that can list and get EtcdClusters.\nfunc (s *etcdClusterLister) EtcdClusters(namespace string) EtcdClusterNamespaceLister {\n\treturn etcdClusterNamespaceLister{indexer: s.indexer, namespace: namespace}\n}\n\n// EtcdClusterNamespaceLister helps list and get EtcdClusters.\n// All objects returned here must be treated as read-only.\ntype EtcdClusterNamespaceLister interface {\n\t// List lists all EtcdClusters in the indexer for a given namespace.\n\t// Objects returned here must be treated as read-only.\n\tList(selector labels.Selector) (ret []*v1alpha2.EtcdCluster, err error)\n\t// Get retrieves the EtcdCluster from the indexer for a given namespace and name.\n\t// Objects returned here must be treated as read-only.\n\tGet(name string) (*v1alpha2.EtcdCluster, error)\n\tEtcdClusterNamespaceListerExpansion\n}\n\n// etcdClusterNamespaceLister implements the EtcdClusterNamespaceLister\n// interface.\ntype etcdClusterNamespaceLister struct {\n\tindexer   cache.Indexer\n\tnamespace string\n}\n\n// List lists all EtcdClusters in the indexer for a given namespace.\nfunc (s etcdClusterNamespaceLister) List(selector labels.Selector) (ret []*v1alpha2.EtcdCluster, err error) {\n\terr = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {\n\t\tret = append(ret, m.(*v1alpha2.EtcdCluster))\n\t})\n\treturn ret, err\n}\n\n// Get retrieves the EtcdCluster from the indexer for a given namespace and name.\nfunc (s etcdClusterNamespaceLister) Get(name string) (*v1alpha2.EtcdCluster, error) {\n\tobj, exists, err := s.indexer.GetByKey(s.namespace + \"/\" + name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif !exists {\n\t\treturn nil, errors.NewNotFound(v1alpha2.Resource(\"etcdcluster\"), name)\n\t}\n\treturn obj.(*v1alpha2.EtcdCluster), nil\n}\n"
  },
  {
    "path": "pkg/generated/listers/kstone/v1alpha2/etcdinspection.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by lister-gen. DO NOT EDIT.\n\npackage v1alpha2\n\nimport (\n\t\"k8s.io/apimachinery/pkg/api/errors\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n\t\"k8s.io/client-go/tools/cache\"\n\tv1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n)\n\n// EtcdInspectionLister helps list EtcdInspections.\n// All objects returned here must be treated as read-only.\ntype EtcdInspectionLister interface {\n\t// List lists all EtcdInspections in the indexer.\n\t// Objects returned here must be treated as read-only.\n\tList(selector labels.Selector) (ret []*v1alpha2.EtcdInspection, err error)\n\t// EtcdInspections returns an object that can list and get EtcdInspections.\n\tEtcdInspections(namespace string) EtcdInspectionNamespaceLister\n\tEtcdInspectionListerExpansion\n}\n\n// etcdInspectionLister implements the EtcdInspectionLister interface.\ntype etcdInspectionLister struct {\n\tindexer cache.Indexer\n}\n\n// NewEtcdInspectionLister returns a new EtcdInspectionLister.\nfunc NewEtcdInspectionLister(indexer cache.Indexer) EtcdInspectionLister {\n\treturn &etcdInspectionLister{indexer: indexer}\n}\n\n// List lists all EtcdInspections in the indexer.\nfunc (s *etcdInspectionLister) List(selector labels.Selector) (ret []*v1alpha2.EtcdInspection, err error) {\n\terr = cache.ListAll(s.indexer, selector, func(m interface{}) {\n\t\tret = append(ret, m.(*v1alpha2.EtcdInspection))\n\t})\n\treturn ret, err\n}\n\n// EtcdInspections returns an object that can list and get EtcdInspections.\nfunc (s *etcdInspectionLister) EtcdInspections(namespace string) EtcdInspectionNamespaceLister {\n\treturn etcdInspectionNamespaceLister{indexer: s.indexer, namespace: namespace}\n}\n\n// EtcdInspectionNamespaceLister helps list and get EtcdInspections.\n// All objects returned here must be treated as read-only.\ntype EtcdInspectionNamespaceLister interface {\n\t// List lists all EtcdInspections in the indexer for a given namespace.\n\t// Objects returned here must be treated as read-only.\n\tList(selector labels.Selector) (ret []*v1alpha2.EtcdInspection, err error)\n\t// Get retrieves the EtcdInspection from the indexer for a given namespace and name.\n\t// Objects returned here must be treated as read-only.\n\tGet(name string) (*v1alpha2.EtcdInspection, error)\n\tEtcdInspectionNamespaceListerExpansion\n}\n\n// etcdInspectionNamespaceLister implements the EtcdInspectionNamespaceLister\n// interface.\ntype etcdInspectionNamespaceLister struct {\n\tindexer   cache.Indexer\n\tnamespace string\n}\n\n// List lists all EtcdInspections in the indexer for a given namespace.\nfunc (s etcdInspectionNamespaceLister) List(selector labels.Selector) (ret []*v1alpha2.EtcdInspection, err error) {\n\terr = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {\n\t\tret = append(ret, m.(*v1alpha2.EtcdInspection))\n\t})\n\treturn ret, err\n}\n\n// Get retrieves the EtcdInspection from the indexer for a given namespace and name.\nfunc (s etcdInspectionNamespaceLister) Get(name string) (*v1alpha2.EtcdInspection, error) {\n\tobj, exists, err := s.indexer.GetByKey(s.namespace + \"/\" + name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif !exists {\n\t\treturn nil, errors.NewNotFound(v1alpha2.Resource(\"etcdinspection\"), name)\n\t}\n\treturn obj.(*v1alpha2.EtcdInspection), nil\n}\n"
  },
  {
    "path": "pkg/generated/listers/kstone/v1alpha2/expansion_generated.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\n// Code generated by lister-gen. DO NOT EDIT.\n\npackage v1alpha2\n\n// EtcdClusterListerExpansion allows custom methods to be added to\n// EtcdClusterLister.\ntype EtcdClusterListerExpansion interface{}\n\n// EtcdClusterNamespaceListerExpansion allows custom methods to be added to\n// EtcdClusterNamespaceLister.\ntype EtcdClusterNamespaceListerExpansion interface{}\n\n// EtcdInspectionListerExpansion allows custom methods to be added to\n// EtcdInspectionLister.\ntype EtcdInspectionListerExpansion interface{}\n\n// EtcdInspectionNamespaceListerExpansion allows custom methods to be added to\n// EtcdInspectionNamespaceLister.\ntype EtcdInspectionNamespaceListerExpansion interface{}\n"
  },
  {
    "path": "pkg/inspection/alarm.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage inspection\n\nimport (\n\t\"strconv\"\n\n\t\"k8s.io/klog/v2\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/clusterprovider\"\n\tfeatureutil \"tkestack.io/kstone/pkg/featureprovider/util\"\n\t\"tkestack.io/kstone/pkg/inspection/metrics\"\n)\n\nvar alarmTypeList = []string{\"NOSPACE\", \"CORRUPT\"}\n\n// CollectAlarmList collects the alarms of etcd, and\n// transfer them to prometheus metrics\nfunc (c *Server) CollectAlarmList(inspection *kstonev1alpha2.EtcdInspection) error {\n\tnamespace, name := inspection.Namespace, inspection.Spec.ClusterName\n\tcluster, clientConfig, err := c.GetEtcdClusterInfo(namespace, name)\n\tdefer func() {\n\t\tif err != nil {\n\t\t\tfeatureutil.IncrFailedInspectionCounter(name, kstonev1alpha2.KStoneFeatureAlarm)\n\t\t}\n\t}()\n\tif err != nil {\n\t\tklog.Errorf(\"load tlsConfig failed, namespace is %s, name is %s, err is %v\", namespace, name, err)\n\t\treturn err\n\t}\n\n\talarms, err := clusterprovider.GetEtcdAlarms([]string{cluster.Status.ServiceName}, clientConfig)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, m := range cluster.Status.Members {\n\t\tif len(alarms) == 0 {\n\t\t\tcleanAllAlarmMetrics(cluster.Name, m.Endpoint)\n\t\t}\n\t\tfor _, a := range alarms {\n\t\t\tif m.MemberId == strconv.FormatUint(a.MemberID, 10) {\n\t\t\t\tlabels := map[string]string{\n\t\t\t\t\t\"clusterName\": cluster.Name,\n\t\t\t\t\t\"endpoint\":    m.Endpoint,\n\t\t\t\t\t\"alarmType\":   a.AlarmType,\n\t\t\t\t}\n\t\t\t\tmetrics.EtcdEndpointAlarm.With(labels).Set(1)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// cleanAllAlarmMetrics clear all alarm metrics by cluster\nfunc cleanAllAlarmMetrics(clusterName, endpoint string) {\n\tfor _, t := range alarmTypeList {\n\t\tmetrics.EtcdEndpointAlarm.With(map[string]string{\n\t\t\t\"clusterName\": clusterName,\n\t\t\t\"endpoint\":    endpoint,\n\t\t\t\"alarmType\":   t,\n\t\t}).Set(0)\n\t}\n}\n"
  },
  {
    "path": "pkg/inspection/backupcheck.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage inspection\n\nimport (\n\t\"context\"\n\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/klog/v2\"\n\n\t\"tkestack.io/kstone/pkg/backup\"\n\t_ \"tkestack.io/kstone/pkg/backup/providers\" // import backup provider\n\t\"tkestack.io/kstone/pkg/inspection/metrics\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\tfeatureutil \"tkestack.io/kstone/pkg/featureprovider/util\"\n)\n\n// StatBackupFiles counts the number of backup files in the last day and\n// transfer it to prometheus metrics\nfunc (c *Server) StatBackupFiles(inspection *kstonev1alpha2.EtcdInspection) error {\n\tnamespace, name := inspection.Namespace, inspection.Spec.ClusterName\n\tlabels := map[string]string{\n\t\t\"clusterName\": name,\n\t}\n\n\tcluster, err := c.cli.KstoneV1alpha2().EtcdClusters(namespace).Get(context.TODO(), name, metav1.GetOptions{})\n\tdefer func() {\n\t\tif err != nil {\n\t\t\tfeatureutil.IncrFailedInspectionCounter(name, kstonev1alpha2.KStoneFeatureBackupCheck)\n\t\t}\n\t}()\n\tif err != nil {\n\t\tif apierrors.IsNotFound(err) {\n\t\t\treturn nil\n\t\t}\n\t\treturn err\n\t}\n\n\t// get backup config\n\tbackupConfig, err := backup.GetBackupConfig(cluster)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get backup config,cluster %s,err is %v\", cluster.Name, err)\n\t\treturn err\n\t}\n\n\t// get specified backup storage provider\n\tstorage, err := backup.GetBackupStorageProvider(string(backupConfig.StorageType), &backup.StorageConfig{\n\t\tKubeCli: c.kubeCli,\n\t})\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get backup provider,cluster %s,err is %v\", inspection.ClusterName, err)\n\t\treturn err\n\t}\n\tobjects, err := storage.List(cluster)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to list backup files,cluster %s,err is %v\", inspection.ClusterName, err)\n\t\treturn err\n\t}\n\n\tactualFiles, err := storage.Stat(objects)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to stat backup files,cluster %s,err is %v\", inspection.ClusterName, err)\n\t\treturn err\n\t}\n\tDesiredFiles := int(featureutil.OneDaySeconds / backupConfig.StoragePolicy.BackupIntervalInSecond)\n\tif DesiredFiles > backupConfig.StoragePolicy.MaxBackups {\n\t\tDesiredFiles = backupConfig.StoragePolicy.MaxBackups\n\t}\n\tfailedFiles := DesiredFiles - actualFiles\n\tif failedFiles < 0 {\n\t\tfailedFiles = 0\n\t}\n\n\tmetrics.EtcdBackupFiles.With(labels).Set(float64(actualFiles))\n\tmetrics.EtcdFailedBackupFiles.With(labels).Set(float64(failedFiles))\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/inspection/consistency.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage inspection\n\nimport (\n\t\"context\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"golang.org/x/sync/errgroup\"\n\t\"k8s.io/klog/v2\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/etcd\"\n\tfeatureutil \"tkestack.io/kstone/pkg/featureprovider/util\"\n\t\"tkestack.io/kstone/pkg/inspection/metrics\"\n)\n\ntype ConsistencyInfo struct {\n\tPath     string `json:\"path,omitempty\"`\n\tInterval int    `json:\"interval,omitempty\"`\n}\n\n// getEtcdConsistentMetadata gets the etcd consistent metadata.\nfunc (c *Server) getEtcdConsistentMetadata(\n\tcluster *kstonev1alpha2.EtcdCluster,\n\tkeyPrefix string,\n\tcli *etcd.ClientConfig,\n) (map[featureutil.ConsistencyType][]uint64, error) {\n\n\tvar mu sync.Mutex\n\tendpointMetadata := make(map[featureutil.ConsistencyType][]uint64)\n\n\tctx, cancel := context.WithTimeout(context.Background(), etcd.DefaultDialTimeout)\n\tg, ctx := errgroup.WithContext(ctx)\n\tdefer cancel()\n\n\tfor _, member := range cluster.Status.Members {\n\t\tmember := member\n\t\tg.Go(func() error {\n\t\t\tbackendStorage, extensionClientURL := etcd.EtcdV3Backend, member.ExtensionClientUrl\n\t\t\tif strings.HasPrefix(member.Version, \"2\") {\n\t\t\t\tbackendStorage = etcd.EtcdV2Backend\n\t\t\t}\n\t\t\tbackend, err := etcd.NewEtcdStatBackend(backendStorage)\n\t\t\tif err != nil {\n\t\t\t\tklog.Errorf(\"failed to get etcd stat backend,backend %s,err is %v\", extensionClientURL, err)\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tcli.Endpoints = []string{extensionClientURL}\n\n\t\t\terr = backend.Init(cli)\n\t\t\tif err != nil {\n\t\t\t\tklog.Errorf(\n\t\t\t\t\t\"failed to get new etcd clientv3,cluster name is %s,endpoint is %s,err is %v\",\n\t\t\t\t\tcluster.Name,\n\t\t\t\t\textensionClientURL,\n\t\t\t\t\terr,\n\t\t\t\t)\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tdefer backend.Close()\n\t\t\tmetadata, err := backend.GetIndex(ctx, extensionClientURL)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\ttotalKey, err := backend.GetTotalKeyNum(ctx, keyPrefix)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tmetadata[featureutil.ConsistencyKeyTotal] = totalKey\n\n\t\t\tmu.Lock()\n\t\t\tfor t, v := range metadata {\n\t\t\t\tendpointMetadata[t] = append(endpointMetadata[t], v)\n\t\t\t}\n\t\t\tmu.Unlock()\n\t\t\treturn nil\n\t\t})\n\t}\n\tif err := g.Wait(); err != nil {\n\t\treturn endpointMetadata, err\n\t}\n\treturn endpointMetadata, nil\n}\n\n// CollectClusterConsistentData collects the etcd metadata info, calculate the difference, and\n// transfer them to prometheus metrics\nfunc (c *Server) CollectClusterConsistentData(inspection *kstonev1alpha2.EtcdInspection) error {\n\tnamespace, name := inspection.Namespace, inspection.Spec.ClusterName\n\tcluster, clientConfig, err := c.GetEtcdClusterInfo(namespace, name)\n\tdefer func() {\n\t\tif err != nil {\n\t\t\tfeatureutil.IncrFailedInspectionCounter(name, kstonev1alpha2.KStoneFeatureConsistency)\n\t\t}\n\t}()\n\tif err != nil {\n\t\tklog.Errorf(\"failed to load tls config, namespace is %s, name is %s, err is %v\", namespace, name, err)\n\t\treturn err\n\t}\n\tendpointMetadataDiff := make(map[featureutil.ConsistencyType]uint64)\n\tendpointMetadata, err := c.getEtcdConsistentMetadata(cluster, DefaultInspectionPath, clientConfig)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to getEtcdConsistentMetadata, etcd cluster %s, err is %v\", cluster.Name, err)\n\t} else {\n\t\tfor t, values := range endpointMetadata {\n\t\t\tsort.Slice(values, func(i, j int) bool { return values[i] < values[j] })\n\t\t\tendpointMetadataDiff[t] = values[len(values)-1] - values[0]\n\t\t}\n\t}\n\tlabels := map[string]string{\n\t\t\"clusterName\": cluster.Name,\n\t}\n\tfor t, v := range endpointMetadataDiff {\n\t\tswitch t {\n\t\tcase featureutil.ConsistencyKeyTotal:\n\t\t\tmetrics.EtcdNodeDiffTotal.With(labels).Set(float64(v))\n\t\tcase featureutil.ConsistencyRevision:\n\t\t\tmetrics.EtcdNodeRevisionDiff.With(labels).Set(float64(v))\n\t\tcase featureutil.ConsistencyIndex:\n\t\t\tmetrics.EtcdNodeIndexDiff.With(labels).Set(float64(v))\n\t\tcase featureutil.ConsistencyRaftRaftAppliedIndex:\n\t\t\tmetrics.EtcdNodeRaftAppliedIndexDiff.With(labels).Set(float64(v))\n\t\tcase featureutil.ConsistencyRaftIndex:\n\t\t\tmetrics.EtcdNodeRaftIndexDiff.With(labels).Set(float64(v))\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/inspection/healthy.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage inspection\n\nimport (\n\t\"k8s.io/klog/v2\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/etcd\"\n\tfeatureutil \"tkestack.io/kstone/pkg/featureprovider/util\"\n\t\"tkestack.io/kstone/pkg/inspection/metrics\"\n)\n\n// CollectMemberHealthy collects the health of etcd, and\n// transfer them to prometheus metrics\nfunc (c *Server) CollectMemberHealthy(inspection *kstonev1alpha2.EtcdInspection) error {\n\tnamespace, name := inspection.Namespace, inspection.Spec.ClusterName\n\tcluster, clientConfig, err := c.GetEtcdClusterInfo(namespace, name)\n\tdefer func() {\n\t\tif err != nil {\n\t\t\tfeatureutil.IncrFailedInspectionCounter(name, kstonev1alpha2.KStoneFeatureHealthy)\n\t\t}\n\t}()\n\tif err != nil {\n\t\tklog.Errorf(\"load tlsConfig failed, namespace is %s, name is %s, err is %v\", namespace, name, err)\n\t\treturn err\n\t}\n\n\tfor _, m := range cluster.Status.Members {\n\t\thealthy, hErr := etcd.MemberHealthy(m.ExtensionClientUrl, clientConfig)\n\t\tlabels := map[string]string{\n\t\t\t\"clusterName\": cluster.Name,\n\t\t\t\"endpoint\":    m.Endpoint,\n\t\t}\n\t\tif hErr != nil || !healthy {\n\t\t\tmetrics.EtcdEndpointHealthy.With(labels).Set(0)\n\t\t} else {\n\t\t\tmetrics.EtcdEndpointHealthy.With(labels).Set(1)\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/inspection/inspection.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage inspection\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"sync\"\n\t\"time\"\n\n\tclientv3 \"go.etcd.io/etcd/client/v3\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/klog/v2\"\n\t\"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/controllers/util\"\n\t\"tkestack.io/kstone/pkg/etcd\"\n\t\"tkestack.io/kstone/pkg/featureprovider\"\n\tfeatureutil \"tkestack.io/kstone/pkg/featureprovider/util\"\n\tclientset \"tkestack.io/kstone/pkg/generated/clientset/versioned\"\n\tplatformscheme \"tkestack.io/kstone/pkg/generated/clientset/versioned/scheme\"\n)\n\nconst (\n\tDefaultInspectionInterval = 300 * time.Second\n\tDefaultInspectionPath     = \"\"\n)\n\ntype Server struct {\n\tcli                *clientset.Clientset\n\tkubeCli            kubernetes.Interface\n\tclient             map[string]*clientv3.Client\n\twchan              map[string]clientv3.WatchChan\n\twatcher            map[string]clientv3.Watcher\n\teventCh            map[string]chan *clientv3.Event\n\tmux                sync.Mutex\n\tclientConfigGetter etcd.ClientConfigGetter\n}\n\n// NewInspectionServer generates the server of inspection\nfunc NewInspectionServer(ctx *featureprovider.FeatureContext) (*Server, error) {\n\tcli, err := clientset.NewForConfig(ctx.ClientBuilder.ConfigOrDie())\n\tif err != nil {\n\t\tklog.Errorf(\"failed to init etcdinspection client, err is %v\", err)\n\t\treturn nil, err\n\t}\n\treturn &Server{\n\t\tkubeCli:            ctx.ClientBuilder.ClientOrDie(),\n\t\tcli:                cli,\n\t\tclient:             make(map[string]*clientv3.Client),\n\t\twchan:              make(map[string]clientv3.WatchChan),\n\t\twatcher:            make(map[string]clientv3.Watcher),\n\t\teventCh:            make(map[string]chan *clientv3.Event),\n\t\tclientConfigGetter: ctx.ClientConfigGetter,\n\t}, nil\n}\n\n// GetEtcdCluster gets etcdcluster\nfunc (c *Server) GetEtcdCluster(namespace, name string) (*kstonev1alpha2.EtcdCluster, error) {\n\treturn c.cli.KstoneV1alpha2().EtcdClusters(namespace).Get(context.TODO(), name, metav1.GetOptions{})\n}\n\n// GetEtcdInspection gets etcdinspection\nfunc (c *Server) GetEtcdInspection(namespace, name string) (*kstonev1alpha2.EtcdInspection, error) {\n\tinspectionTask, err := c.cli.KstoneV1alpha2().EtcdInspections(namespace).Get(context.TODO(), name, metav1.GetOptions{})\n\tif err != nil {\n\t\tif !apierrors.IsNotFound(err) {\n\t\t\tklog.Errorf(\"failed to get etcdinspection, err: %v, namespace is %s, name is %s\", err, namespace, name)\n\t\t}\n\t\treturn nil, err\n\t}\n\treturn inspectionTask, nil\n}\n\n// DeleteEtcdInspection deletes etcdinspection\nfunc (c *Server) DeleteEtcdInspection(namespace, name string) error {\n\terr := c.cli.KstoneV1alpha2().EtcdInspections(namespace).\n\t\tDelete(context.TODO(), name, metav1.DeleteOptions{})\n\tif err != nil && !apierrors.IsNotFound(err) {\n\t\tklog.Errorf(\n\t\t\t\"failed to delete etcdinspection, namespace is %s, name is %s, err is %v\",\n\t\t\tnamespace,\n\t\t\tname,\n\t\t\terr,\n\t\t)\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// CreateEtcdInspection creates etcdinspection\nfunc (c *Server) CreateEtcdInspection(inspection *kstonev1alpha2.EtcdInspection) (*kstonev1alpha2.EtcdInspection, error) {\n\tnewinspectionTask, err := c.cli.KstoneV1alpha2().EtcdInspections(inspection.Namespace).\n\t\tCreate(context.TODO(), inspection, metav1.CreateOptions{})\n\tif err != nil && !apierrors.IsAlreadyExists(err) {\n\t\tklog.Errorf(\n\t\t\t\"failed to create etcdinspection, namespace is %s, name is %s, err is %v\",\n\t\t\tinspection.Namespace,\n\t\t\tinspection.Name,\n\t\t\terr,\n\t\t)\n\t\treturn newinspectionTask, err\n\t}\n\treturn newinspectionTask, nil\n}\n\nfunc (c *Server) initInspectionTask(\n\tcluster *kstonev1alpha2.EtcdCluster,\n\tinspectionFeatureName kstonev1alpha2.KStoneFeature,\n) (*kstonev1alpha2.EtcdInspection, error) {\n\tname := cluster.Name + \"-\" + string(inspectionFeatureName)\n\tinspectionTask := &kstonev1alpha2.EtcdInspection{}\n\tinspectionTask.ObjectMeta = metav1.ObjectMeta{\n\t\tName:      name,\n\t\tNamespace: cluster.Namespace,\n\t\tLabels:    cluster.Labels,\n\t}\n\tinspectionTask.Spec = kstonev1alpha2.EtcdInspectionSpec{\n\t\tInspectionType: string(inspectionFeatureName),\n\t\tClusterName:    cluster.Name,\n\t}\n\tinspectionTask.Status = kstonev1alpha2.EtcdInspectionStatus{\n\t\tLastUpdatedTime: metav1.Time{\n\t\t\tTime: time.Now(),\n\t\t},\n\t}\n\n\terr := controllerutil.SetOwnerReference(cluster, inspectionTask, platformscheme.Scheme)\n\tif err != nil {\n\t\tklog.Errorf(\"set inspection task's owner failed, err is %v\", err)\n\t\treturn inspectionTask, err\n\t}\n\treturn inspectionTask, nil\n}\n\nfunc (c *Server) GetEtcdClusterInfo(namespace, name string) (*kstonev1alpha2.EtcdCluster, *etcd.ClientConfig, error) {\n\tcluster, err := c.GetEtcdCluster(namespace, name)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get cluster info, namespace is %s, name is %s, err is %v\", namespace, name, err)\n\t\treturn nil, nil, err\n\t}\n\n\tannotations := cluster.ObjectMeta.Annotations\n\tsecretName := \"\"\n\tif annotations != nil {\n\t\tif _, found := annotations[util.ClusterTLSSecretName]; found {\n\t\t\tsecretName = annotations[util.ClusterTLSSecretName]\n\t\t}\n\t}\n\tpath := fmt.Sprintf(\"%s/%s\", cluster.Namespace, cluster.Name)\n\tclientConfig, err := c.clientConfigGetter.New(path, secretName)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get cluster, namespace is %s, name is %s, err is %v\", namespace, name, err)\n\t\treturn nil, nil, err\n\t}\n\treturn cluster, clientConfig, nil\n}\n\nfunc (c *Server) Equal(cluster *kstonev1alpha2.EtcdCluster, inspectionFeatureName kstonev1alpha2.KStoneFeature) bool {\n\tif !featureutil.IsFeatureGateEnabled(cluster.ObjectMeta.Annotations, inspectionFeatureName) {\n\t\tif cluster.Status.FeatureGatesStatus[inspectionFeatureName] != featureutil.FeatureStatusDisabled {\n\t\t\treturn c.checkEqualIfDisabled(cluster, inspectionFeatureName)\n\t\t}\n\t\treturn true\n\t}\n\treturn c.checkEqualIfEnabled(cluster, inspectionFeatureName)\n}\n\nfunc (c *Server) Sync(cluster *kstonev1alpha2.EtcdCluster, inspectionFeatureName kstonev1alpha2.KStoneFeature) error {\n\tif !featureutil.IsFeatureGateEnabled(cluster.ObjectMeta.Annotations, inspectionFeatureName) {\n\t\treturn c.cleanInspectionTask(cluster, inspectionFeatureName)\n\t}\n\treturn c.syncInspectionTask(cluster, inspectionFeatureName)\n}\n\n// CheckEqualIfDisabled Checks whether the inspection task has been deleted if the inspection feature is disabled.\nfunc (c *Server) checkEqualIfDisabled(cluster *kstonev1alpha2.EtcdCluster, inspectionFeatureName kstonev1alpha2.KStoneFeature) bool {\n\tname := cluster.Name + \"-\" + string(inspectionFeatureName)\n\tif _, err := c.GetEtcdInspection(cluster.Namespace, name); apierrors.IsNotFound(err) {\n\t\treturn true\n\t}\n\treturn false\n}\n\n// CheckEqualIfEnabled check whether the desired inspection task are consistent with the actual task,\n// if the inspection feature is enabled.\nfunc (c *Server) checkEqualIfEnabled(cluster *kstonev1alpha2.EtcdCluster, inspectionFeatureName kstonev1alpha2.KStoneFeature) bool {\n\tname := cluster.Name + \"-\" + string(inspectionFeatureName)\n\tif _, err := c.GetEtcdInspection(cluster.Namespace, name); err == nil {\n\t\treturn true\n\t}\n\treturn false\n}\n\n// CleanInspectionTask cleans inspection task\nfunc (c *Server) cleanInspectionTask(cluster *kstonev1alpha2.EtcdCluster, inspectionFeatureName kstonev1alpha2.KStoneFeature) error {\n\tname := cluster.Name + \"-\" + string(inspectionFeatureName)\n\treturn c.DeleteEtcdInspection(cluster.Namespace, name)\n}\n\n// SyncInspectionTask syncs inspection task\nfunc (c *Server) syncInspectionTask(cluster *kstonev1alpha2.EtcdCluster, inspectionFeatureName kstonev1alpha2.KStoneFeature) error {\n\ttask, err := c.initInspectionTask(cluster, inspectionFeatureName)\n\tif err != nil {\n\t\treturn err\n\t}\n\t_, err = c.CreateEtcdInspection(task)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/inspection/metrics/metrics.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage metrics\n\nimport (\n\t\"github.com/prometheus/client_golang/prometheus\"\n)\n\nvar (\n\tEtcdNodeDiffTotal = prometheus.NewGaugeVec(prometheus.GaugeOpts{\n\t\tNamespace: \"kstone\",\n\t\tSubsystem: \"inspection\",\n\t\tName:      \"etcd_node_diff_total\",\n\t\tHelp:      \"total etcd node diff key\",\n\t}, []string{\"clusterName\"})\n\n\tEtcdEndpointHealthy = prometheus.NewGaugeVec(prometheus.GaugeOpts{\n\t\tNamespace: \"kstone\",\n\t\tSubsystem: \"inspection\",\n\t\tName:      \"etcd_endpoint_healthy\",\n\t\tHelp:      \"The healthy of etcd member\",\n\t}, []string{\"clusterName\", \"endpoint\"})\n\n\tEtcdRequestTotal = prometheus.NewCounterVec(prometheus.CounterOpts{\n\t\tNamespace: \"kstone\",\n\t\tSubsystem: \"inspection\",\n\t\tName:      \"etcd_request_total\",\n\t\tHelp:      \"The total number of etcd requests\",\n\t}, []string{\"clusterName\", \"grpcMethod\", \"etcdPrefix\", \"resourceName\"})\n\n\tEtcdKeyTotal = prometheus.NewGaugeVec(prometheus.GaugeOpts{\n\t\tNamespace: \"kstone\",\n\t\tSubsystem: \"inspection\",\n\t\tName:      \"etcd_key_total\",\n\t\tHelp:      \"The total number of etcd key\",\n\t}, []string{\"clusterName\", \"etcdPrefix\", \"resourceName\"})\n\n\tEtcdEndpointAlarm = prometheus.NewGaugeVec(prometheus.GaugeOpts{\n\t\tNamespace: \"kstone\",\n\t\tSubsystem: \"inspection\",\n\t\tName:      \"etcd_endpoint_alarm\",\n\t\tHelp:      \"The alarm of etcd member\",\n\t}, []string{\"clusterName\", \"endpoint\", \"alarmType\"})\n\n\tEtcdNodeRevisionDiff = prometheus.NewGaugeVec(prometheus.GaugeOpts{\n\t\tNamespace: \"kstone\",\n\t\tSubsystem: \"inspection\",\n\t\tName:      \"etcd_node_revision_diff_total\",\n\t\tHelp:      \"The revision difference between all member\",\n\t}, []string{\"clusterName\"})\n\n\tEtcdNodeIndexDiff = prometheus.NewGaugeVec(prometheus.GaugeOpts{\n\t\tNamespace: \"kstone\",\n\t\tSubsystem: \"inspection\",\n\t\tName:      \"etcd_node_index_diff_total\",\n\t\tHelp:      \"The index difference between all member\",\n\t}, []string{\"clusterName\"})\n\n\tEtcdNodeRaftAppliedIndexDiff = prometheus.NewGaugeVec(prometheus.GaugeOpts{\n\t\tNamespace: \"kstone\",\n\t\tSubsystem: \"inspection\",\n\t\tName:      \"etcd_node_raft_applied_index_diff_total\",\n\t\tHelp:      \"The raft applied index difference between all member\",\n\t}, []string{\"clusterName\"})\n\n\tEtcdNodeRaftIndexDiff = prometheus.NewGaugeVec(prometheus.GaugeOpts{\n\t\tNamespace: \"kstone\",\n\t\tSubsystem: \"inspection\",\n\t\tName:      \"etcd_node_raft_index_diff_total\",\n\t\tHelp:      \"The raft index difference between all member\",\n\t}, []string{\"clusterName\"})\n\n\tEtcdBackupFiles = prometheus.NewGaugeVec(prometheus.GaugeOpts{\n\t\tNamespace: \"kstone\",\n\t\tSubsystem: \"inspection\",\n\t\tName:      \"etcd_backup_files\",\n\t\tHelp:      \"The Number of backup files in the last day\",\n\t}, []string{\"clusterName\"})\n\n\tEtcdFailedBackupFiles = prometheus.NewGaugeVec(prometheus.GaugeOpts{\n\t\tNamespace: \"kstone\",\n\t\tSubsystem: \"inspection\",\n\t\tName:      \"etcd_failed_backup_files\",\n\t\tHelp:      \"The Number of failed backup files in the last day\",\n\t}, []string{\"clusterName\"})\n\n\tEtcdInspectionFailedNum = prometheus.NewCounterVec(prometheus.CounterOpts{\n\t\tNamespace: \"kstone\",\n\t\tSubsystem: \"inspection\",\n\t\tName:      \"failed_num\",\n\t\tHelp:      \"The total Number of failed inspection\",\n\t}, []string{\"clusterName\", \"inspectionType\"})\n)\n\nfunc init() {\n\tprometheus.MustRegister(EtcdNodeDiffTotal)\n\tprometheus.MustRegister(EtcdEndpointHealthy)\n\tprometheus.MustRegister(EtcdRequestTotal)\n\tprometheus.MustRegister(EtcdKeyTotal)\n\tprometheus.MustRegister(EtcdEndpointAlarm)\n\tprometheus.MustRegister(EtcdNodeRevisionDiff)\n\tprometheus.MustRegister(EtcdNodeIndexDiff)\n\tprometheus.MustRegister(EtcdNodeRaftAppliedIndexDiff)\n\tprometheus.MustRegister(EtcdNodeRaftIndexDiff)\n\tprometheus.MustRegister(EtcdBackupFiles)\n\tprometheus.MustRegister(EtcdFailedBackupFiles)\n\tprometheus.MustRegister(EtcdInspectionFailedNum)\n}\n"
  },
  {
    "path": "pkg/inspection/request.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage inspection\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"strings\"\n\t\"time\"\n\n\t\"go.etcd.io/etcd/api/v3/mvccpb\"\n\tclientv3 \"go.etcd.io/etcd/client/v3\"\n\t\"k8s.io/klog/v2\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/clusterprovider\"\n\t\"tkestack.io/kstone/pkg/etcd\"\n\tfeatureutil \"tkestack.io/kstone/pkg/featureprovider/util\"\n\t\"tkestack.io/kstone/pkg/inspection/metrics\"\n)\n\nconst (\n\tinspectionRequestAnno = \"request\"\n\teventBuffer           = 40960\n)\n\ntype RequestInfo struct {\n\tPath     string `json:\"path,omitempty\"`\n\tInterval int    `json:\"interval,omitempty\"`\n\tPrefix   bool   `json:\"prefix,omitempty\"`\n}\n\n// CollectEtcdClusterRequest collects request of etcd\nfunc (c *Server) CollectEtcdClusterRequest(inspection *kstonev1alpha2.EtcdInspection) error {\n\tnamespace, name := inspection.Namespace, inspection.Spec.ClusterName\n\tcluster, config, err := c.GetEtcdClusterInfo(namespace, name)\n\tdefer func() {\n\t\tif err != nil {\n\t\t\tfeatureutil.IncrFailedInspectionCounter(name, kstonev1alpha2.KStoneFeatureRequest)\n\t\t}\n\t}()\n\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get cluster info, namespace is %s, name is %s, err is %v\", namespace, name, err)\n\t\treturn err\n\t}\n\n\t_, ok := c.watcher[cluster.Name]\n\tif ok {\n\t\treturn nil\n\t}\n\n\tannotations := cluster.ObjectMeta.Annotations\n\twatchKey := DefaultInspectionPath\n\tif annotations != nil {\n\t\tif infoStr, found := annotations[inspectionRequestAnno]; found {\n\t\t\tinfo := &RequestInfo{}\n\t\t\terr = json.Unmarshal([]byte(infoStr), info)\n\t\t\tif err == nil {\n\t\t\t\twatchKey = info.Path\n\t\t\t}\n\t\t}\n\t}\n\n\tconfig.Endpoints = clusterprovider.GetStorageMemberEndpoints(cluster)\n\n\tclient, err := etcd.NewClientv3(config)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get new etcd clientv3,err is %v\", err)\n\t\treturn err\n\t}\n\n\ttimeoutCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\n\tdefer cancel()\n\n\trsp, rErr := client.Get(\n\t\ttimeoutCtx,\n\t\twatchKey,\n\t\tclientv3.WithPrefix(),\n\t\tclientv3.WithSort(clientv3.SortByKey, clientv3.SortAscend),\n\t\tclientv3.WithKeysOnly(),\n\t)\n\tif rErr != nil {\n\t\tklog.Errorf(\"failed to get all etcd cluster keys,err is %v\", rErr)\n\t\treturn rErr\n\t}\n\n\tc.populateClusterTotalKeyMetrics(cluster, rsp.Kvs)\n\tc.client[cluster.Name] = client\n\teventCh := make(chan *clientv3.Event, eventBuffer)\n\tc.setEventCh(eventCh, cluster.Name)\n\terr = c.Watch(cluster, client, watchKey)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get watch etcdcluster,err is %v\", err)\n\t\treturn err\n\t}\n\tgo c.processWatchEvent(cluster)\n\treturn err\n}\n\n// populateClusterTotalKeyMetrics generates prometheus metrics of the etcd key\nfunc (c *Server) populateClusterTotalKeyMetrics(cluster *kstonev1alpha2.EtcdCluster, nodes []*mvccpb.KeyValue) {\n\tklog.V(2).Infof(\"cluster name %s,total node:%d\", cluster.Name, len(nodes))\n\tlabels := map[string]string{\n\t\t\"clusterName\": cluster.Name,\n\t}\n\tfor i := 0; i < len(nodes); i++ {\n\t\tc.setEtcdPrefixAndResourceName(labels, string(nodes[i].Key))\n\t\tmetrics.EtcdKeyTotal.With(labels).Inc()\n\t}\n}\n\n// setEtcdPrefixAndResourceName sets prefix and resource name of metric\nfunc (c *Server) setEtcdPrefixAndResourceName(labels map[string]string, key string) {\n\tlabels[\"etcdPrefix\"] = \"\"\n\tlabels[\"resourceName\"] = \"\"\n\tkeys := strings.Split(key, \"/\")\n\tif len(keys) < 2 {\n\t\treturn\n\t}\n\tlabels[\"etcdPrefix\"] = keys[1]\n\tif len(keys) > 2 {\n\t\tlabels[\"resourceName\"] = keys[2]\n\t}\n}\n\n// setEventCh sets event chan\nfunc (c *Server) setEventCh(ch chan *clientv3.Event, clusterName string) {\n\tc.mux.Lock()\n\tdefer c.mux.Unlock()\n\tc.eventCh[clusterName] = ch\n}\n\n// getEventCh gets event chan\nfunc (c *Server) getEventCh(clusterName string) chan *clientv3.Event {\n\tc.mux.Lock()\n\tdefer c.mux.Unlock()\n\tch, ok := c.eventCh[clusterName]\n\tif !ok {\n\t\tklog.Fatalf(\"failed to get event ch,cluster name is %s\", clusterName)\n\t}\n\treturn ch\n}\n\n// Watch watches etcd event\nfunc (c *Server) Watch(cluster *kstonev1alpha2.EtcdCluster, client *clientv3.Client, keyPrefix string) error {\n\twatcher := clientv3.NewWatcher(client)\n\tc.watcher[cluster.Name] = watcher\n\tgo func() {\n\t\tfor {\n\t\t\tklog.V(2).Infof(\"cluster name:%s,prefix:%s,start to watch key change\", cluster.Name, keyPrefix)\n\t\t\tch := watcher.Watch(context.Background(), keyPrefix, clientv3.WithPrefix())\n\t\t\terr := c.watch(cluster, ch)\n\t\t\tif err == nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t//if failed to watch,just retry\n\t\t\ttime.Sleep(time.Second)\n\t\t}\n\t}()\n\treturn nil\n}\n\nfunc (c *Server) watch(cluster *kstonev1alpha2.EtcdCluster, wchan clientv3.WatchChan) error {\n\tch := c.getEventCh(cluster.Name)\n\tfor wresp := range wchan {\n\t\tif wresp.Canceled {\n\t\t\tklog.V(3).Infof(\"cluster:%s,watcher is closed\", cluster.Name)\n\t\t\treturn errors.New(\"watch failure\")\n\t\t}\n\t\tfor _, ev := range wresp.Events {\n\t\t\tswitch ev.Type {\n\t\t\tcase mvccpb.PUT:\n\t\t\t\tklog.V(3).Infof(\"type: put,key:%s,lease:%d,mod version:%d\", ev.Kv.Key, ev.Kv.Lease, ev.Kv.ModRevision)\n\t\t\t\tch <- ev\n\t\t\tcase mvccpb.DELETE:\n\t\t\t\tklog.V(3).Infof(\"type: delete,key:%s\", ev.Kv.Key)\n\t\t\t\tch <- ev\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// processWatchEvent prcoesses the event watched\nfunc (c *Server) processWatchEvent(cluster *kstonev1alpha2.EtcdCluster) {\n\tch := c.getEventCh(cluster.Name)\n\tlabels := map[string]string{\n\t\t\"clusterName\": cluster.Name,\n\t}\n\tfor ev := range ch {\n\t\t//fix inconsistent label cardinality,etcdKeyTotal metrics does not have label grpcMethod\n\t\tdelete(labels, \"grpcMethod\")\n\t\tswitch ev.Type {\n\t\tcase mvccpb.PUT:\n\t\t\tc.setEtcdPrefixAndResourceName(labels, string(ev.Kv.Key))\n\t\t\tif ev.IsCreate() {\n\t\t\t\tmetrics.EtcdKeyTotal.With(labels).Inc()\n\t\t\t}\n\t\t\tlabels[\"grpcMethod\"] = \"PUT\"\n\t\t\tklog.V(3).Infof(\"cluster:%s,type: PUT,key:%s,lease:%d\", cluster.Name, ev.Kv.Key, ev.Kv.Lease)\n\t\t\tmetrics.EtcdRequestTotal.With(labels).Inc()\n\t\tcase mvccpb.DELETE:\n\t\t\tc.setEtcdPrefixAndResourceName(labels, string(ev.Kv.Key))\n\t\t\tmetrics.EtcdKeyTotal.With(labels).Dec()\n\t\t\tlabels[\"grpcMethod\"] = \"Delete\"\n\t\t\tmetrics.EtcdRequestTotal.With(labels).Inc()\n\t\t\tklog.V(3).Infof(\"cluster:%s,type: delete,key:%s,lease:%d\", cluster.Name, ev.Kv.Key, ev.Kv.Lease)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "pkg/k8s/client.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage k8s\n\nimport (\n\t\"time\"\n\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\tkubeinformers \"k8s.io/client-go/informers\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/client-go/rest\"\n\t\"k8s.io/client-go/tools/clientcmd\"\n\t\"k8s.io/klog/v2\"\n\n\tclientset \"tkestack.io/kstone/pkg/generated/clientset/versioned\"\n\tinformers \"tkestack.io/kstone/pkg/generated/informers/externalversions\"\n)\n\n// GetClientConfig gets *rest.Config with the kube config\nfunc GetClientConfig(kubeconfig string) (*rest.Config, error) {\n\tvar cfg *rest.Config\n\tvar err error\n\tif kubeconfig != \"\" {\n\t\tcfg, err = clientcmd.BuildConfigFromFlags(\"\", kubeconfig)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t} else {\n\t\tcfg, err = rest.InClusterConfig()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\treturn cfg, nil\n}\n\n// GenerateInformer generates informer and client for controller\nfunc GenerateInformer(config *rest.Config, labelSelector string) (\n\t*kubernetes.Clientset,\n\t*clientset.Clientset,\n\tkubeinformers.SharedInformerFactory,\n\tinformers.SharedInformerFactory,\n\terror,\n) {\n\tkubeClient, err := kubernetes.NewForConfig(config)\n\tif err != nil {\n\t\tklog.Fatalf(\"Error building kubernetes clientset: %s\", err.Error())\n\t\treturn nil, nil, nil, nil, err\n\t}\n\n\tclustetClient, err := clientset.NewForConfig(config)\n\tif err != nil {\n\t\tklog.Fatalf(\"Error building example clientset: %s\", err.Error())\n\t\treturn nil, nil, nil, nil, err\n\t}\n\n\tinformerFactory := informers.NewSharedInformerFactory(clustetClient, time.Second*30)\n\tif labelSelector != \"\" {\n\t\toptionsFunc := func(options *metav1.ListOptions) {\n\t\t\toptions.LabelSelector = labelSelector\n\t\t}\n\t\tinformerFactory = informers.NewSharedInformerFactoryWithOptions(\n\t\t\tclustetClient,\n\t\t\ttime.Second*30,\n\t\t\tinformers.WithTweakListOptions(optionsFunc),\n\t\t)\n\t}\n\tkubeInformerFactory := kubeinformers.NewSharedInformerFactory(kubeClient, time.Second*30)\n\n\treturn kubeClient, clustetClient, kubeInformerFactory, informerFactory, nil\n}\n"
  },
  {
    "path": "pkg/middlewares/auth.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage middlewares\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/gin-gonic/gin\"\n\n\t\"tkestack.io/kstone/pkg/authentication/request\"\n)\n\n// Auth authenticates requests\nfunc Auth() gin.HandlerFunc {\n\treturn func(c *gin.Context) {\n\t\trsp, ok, err := request.MiddlewareRequest(c)\n\t\tif !ok || err != nil {\n\t\t\tc.JSON(http.StatusUnauthorized, *rsp)\n\t\t\tc.Abort()\n\t\t}\n\t\tc.Next()\n\t}\n}\n"
  },
  {
    "path": "pkg/middlewares/cors.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage middlewares\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\nconst (\n\tAccessControlExposeHeadersValue = \"Content-Length, \" +\n\t\t\"Access-Control-Allow-Origin, \" +\n\t\t\"Access-Control-Allow-Headers, \" +\n\t\t\"Cache-Control, \" +\n\t\t\"Content-Language, \" +\n\t\t\"Content-Type\"\n)\n\n// Cors return middleware of cors\nfunc Cors() gin.HandlerFunc {\n\treturn func(c *gin.Context) {\n\t\tmethod := c.Request.Method\n\t\tc.Header(\"Access-Control-Allow-Origin\", \"*\")\n\t\tc.Header(\"Access-Control-Allow-Methods\", \"POST, GET, OPTIONS, PUT, DELETE, UPDATE\")\n\t\tc.Header(\"Access-Control-Allow-Headers\", \"Origin, X-Requested-With, Content-Type, Accept, Authorization\")\n\t\tc.Header(\n\t\t\t\"Access-Control-Expose-Headers\",\n\t\t\tAccessControlExposeHeadersValue,\n\t\t)\n\t\tc.Header(\"Access-Control-Allow-Credentials\", \"true\")\n\t\tif method == \"OPTIONS\" {\n\t\t\tc.AbortWithStatus(http.StatusNoContent)\n\t\t}\n\t\tc.Next()\n\t}\n}\n"
  },
  {
    "path": "pkg/monitor/prometheus.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage monitor\n\nimport (\n\t\"context\"\n\t\"os\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\n\tpromapiv1 \"github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1\"\n\tmonitoringv1 \"github.com/prometheus-operator/prometheus-operator/pkg/client/versioned/typed/monitoring/v1\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\tk8sV1 \"k8s.io/api/core/v1\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/util/intstr\"\n\t\"k8s.io/client-go/kubernetes\"\n\tklog \"k8s.io/klog/v2\"\n\t\"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/controllers/util\"\n\t\"tkestack.io/kstone/pkg/etcd\"\n\tfeatureutil \"tkestack.io/kstone/pkg/featureprovider/util\"\n\tplatformscheme \"tkestack.io/kstone/pkg/generated/clientset/versioned/scheme\"\n)\n\nconst (\n\tDefaultEtcdV3SecretName  = \"etcd-v3-certs\"\n\tEtcdTLSPrefix            = \"/etc/prometheus/secrets/\"\n\tDefaultEtcdPromNamespace = \"kstone\"\n)\n\nvar EtcdPromNamespace = os.Getenv(\"PROM_NAMESPACE\")\n\ntype PrometheusMonitor struct {\n\tkubeCli kubernetes.Interface\n\tpromCli *monitoringv1.MonitoringV1Client\n}\n\n// NewPrometheusMonitor generates prometheus provider\nfunc NewPrometheusMonitor(clientBuilder util.ClientBuilder) (*PrometheusMonitor, error) {\n\t// init prom cli\n\tpromCli, err := monitoringv1.NewForConfig(clientBuilder.ConfigOrDie())\n\tif err != nil {\n\t\tklog.Errorf(\"failed to init prom client, err is %v\", err)\n\t\treturn nil, err\n\t}\n\treturn &PrometheusMonitor{\n\t\tkubeCli: clientBuilder.ClientOrDie(),\n\t\tpromCli: promCli,\n\t}, nil\n}\n\n// GetEtcdService gets service\nfunc (prom *PrometheusMonitor) GetEtcdService(namespace, name string) (*corev1.Service, error) {\n\tsvr, err := prom.kubeCli.CoreV1().Services(namespace).Get(context.TODO(), name, metav1.GetOptions{})\n\tif err != nil {\n\t\tklog.Errorf(\"get etcd service ,namespaces is %s,name is %s,error is %v\", namespace, name, err)\n\t\treturn nil, err\n\t}\n\treturn svr, err\n}\n\n// CreateEtcdService creates service\nfunc (prom *PrometheusMonitor) CreateEtcdService(service *corev1.Service) (*corev1.Service, error) {\n\tsvr, err := prom.kubeCli.CoreV1().Services(service.Namespace).Create(context.TODO(), service, metav1.CreateOptions{})\n\tif err != nil {\n\t\tklog.Errorf(\"create etcd service ,namespaces is %s,name is %s,error is %v\", service.Namespace, service.Name, err)\n\t\treturn nil, err\n\t}\n\treturn svr, err\n}\n\n// UpdateEtcdService updates service\nfunc (prom *PrometheusMonitor) UpdateEtcdService(service *corev1.Service) (*corev1.Service, error) {\n\tsvr, err := prom.kubeCli.CoreV1().Services(service.Namespace).Update(context.TODO(), service, metav1.UpdateOptions{})\n\tif err != nil {\n\t\tklog.Errorf(\"update etcd service ,namespaces is %s,name is %s,error is %v\", service.Namespace, service.Name, err)\n\t\treturn nil, err\n\t}\n\treturn svr, err\n}\n\n// DeleteEtcdService deletes service\nfunc (prom *PrometheusMonitor) DeleteEtcdService(namespace, name string) error {\n\terr := prom.kubeCli.CoreV1().Services(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{})\n\tif err != nil {\n\t\tklog.Errorf(\"delete etcd service, namespace is %s, name is %s,error is %v\", namespace, name, err)\n\t}\n\treturn err\n}\n\n// GetEtcdEndpoint gets endpoints\nfunc (prom *PrometheusMonitor) GetEtcdEndpoint(namespace, name string) (*corev1.Endpoints, error) {\n\tep, err := prom.kubeCli.CoreV1().Endpoints(namespace).Get(context.TODO(), name, metav1.GetOptions{})\n\tif err != nil {\n\t\tklog.Errorf(\"get etcd ep ,namespaces is %s,name is %s,error is %v\", namespace, name, err)\n\t\treturn nil, err\n\t}\n\treturn ep, err\n}\n\n// UpdateEtcdEndpoint updates endpoints\nfunc (prom *PrometheusMonitor) UpdateEtcdEndpoint(ep *corev1.Endpoints) (*corev1.Endpoints, error) {\n\tep, err := prom.kubeCli.CoreV1().Endpoints(ep.Namespace).Update(context.TODO(), ep, metav1.UpdateOptions{})\n\tif err != nil {\n\t\tklog.Errorf(\"failed to update etcd ep ,namespaces is %s,name is %s,error is %v\", ep.Namespace, ep.Name, err)\n\t\treturn nil, err\n\t}\n\treturn ep, err\n}\n\n// CreateEtcdEndpoint creates endpoints\nfunc (prom *PrometheusMonitor) CreateEtcdEndpoint(ep *corev1.Endpoints) (*corev1.Endpoints, error) {\n\tnewEp, err := prom.kubeCli.CoreV1().Endpoints(ep.Namespace).Create(context.TODO(), ep, metav1.CreateOptions{})\n\tif err != nil {\n\t\tklog.Errorf(\"create etcd endpoint ,namespaces is %s,name is %s,error is %v\", ep.Namespace, ep.Name, err)\n\t\treturn nil, err\n\t}\n\treturn newEp, err\n}\n\n// GetServiceMonitorTask gets service monitor by namespace and name\nfunc (prom *PrometheusMonitor) GetServiceMonitorTask(namespace, name string) (*promapiv1.ServiceMonitor, error) {\n\ttask, err := prom.promCli.ServiceMonitors(namespace).Get(context.TODO(), name, metav1.GetOptions{})\n\tif err != nil {\n\t\tklog.Errorf(\"get service monitor,namespaces is %s,name is %s,error is %v\", namespace, name, err)\n\t\treturn nil, err\n\t}\n\treturn task, err\n}\n\n// UpdateServiceMonitorSpec updates spec of service monitor\nfunc (prom *PrometheusMonitor) UpdateServiceMonitorSpec(task *promapiv1.ServiceMonitor) (\n\t*promapiv1.ServiceMonitor,\n\terror) {\n\tnewTask, err := prom.promCli.ServiceMonitors(task.Namespace).Update(context.TODO(), task, metav1.UpdateOptions{})\n\tif err != nil {\n\t\tklog.Errorf(\"update service monitor,namespaces is %s,name is %s,error is %v\", task.Namespace, task.Name, err)\n\t\treturn nil, err\n\t}\n\tklog.V(6).Infof(\"update task %v spec succ\", newTask)\n\treturn newTask, err\n}\n\n// CreateServiceMonitor creates service monitor\nfunc (prom *PrometheusMonitor) CreateServiceMonitor(task *promapiv1.ServiceMonitor) (*promapiv1.ServiceMonitor, error) {\n\tnewTask, err := prom.promCli.ServiceMonitors(task.Namespace).Create(context.TODO(), task, metav1.CreateOptions{})\n\tif err != nil {\n\t\tklog.Errorf(\"create service monitor,namespaces is %s,name is %s,error is %v\", task.Namespace, task.Name, err)\n\t\treturn nil, err\n\t}\n\tklog.V(6).Infof(\"update task %v spec succ\", newTask)\n\treturn newTask, err\n}\n\n// UpdateServiceMonitor updates service monitor\nfunc (prom *PrometheusMonitor) UpdateServiceMonitor(task *promapiv1.ServiceMonitor) (*promapiv1.ServiceMonitor, error) {\n\tnewTask, err := prom.promCli.ServiceMonitors(task.Namespace).Update(context.TODO(), task, metav1.UpdateOptions{})\n\tif err != nil {\n\t\tklog.Errorf(\"update service monitor,namespaces is %s,name is %s,error is %v\", task.Namespace, task.Name, err)\n\t\treturn nil, err\n\t}\n\tklog.V(6).Infof(\"update task %v spec succ\", newTask)\n\treturn newTask, err\n}\n\n// DeleteServiceMonitor deletes service monitor\nfunc (prom *PrometheusMonitor) DeleteServiceMonitor(namespace, name string) error {\n\terr := prom.promCli.ServiceMonitors(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{})\n\tif err != nil {\n\t\tklog.Errorf(\"delete service monitor,namespaces is %s,name is %s,error is %v\", namespace, name, err)\n\t\treturn err\n\t}\n\tklog.V(6).Infof(\"delete service monitor %s succ\", name)\n\treturn err\n}\n\n// ServiceMonitorIsEquivalent compares old service monitor with new service monitor\nfunc (prom *PrometheusMonitor) ServiceMonitorIsEquivalent(old, new *promapiv1.ServiceMonitor) bool {\n\tif !reflect.DeepEqual(old.Labels, new.Labels) {\n\t\treturn false\n\t}\n\tif !reflect.DeepEqual(old.Spec, new.Spec) {\n\t\treturn false\n\t}\n\treturn true\n}\n\n// EndpointIsEquivalent compares old endpoints with new endpoints\nfunc (prom *PrometheusMonitor) EndpointIsEquivalent(old, new *corev1.Endpoints) bool {\n\tif !reflect.DeepEqual(old.Labels, new.Labels) {\n\t\treturn false\n\t}\n\n\tif !reflect.DeepEqual(old.Subsets, new.Subsets) {\n\t\treturn false\n\t}\n\treturn true\n}\n\n// ServiceIsEquivalent compares old service with old service\nfunc (prom *PrometheusMonitor) ServiceIsEquivalent(old, new *corev1.Service) bool {\n\tif !reflect.DeepEqual(old.Labels, new.Labels) {\n\t\treturn false\n\t}\n\tif !reflect.DeepEqual(old.Spec, new.Spec) {\n\t\treturn false\n\t}\n\treturn true\n}\n\n// UnpackEndPointSubsets unpacks endpoint subnets\nfunc (prom *PrometheusMonitor) UnpackEndPointSubsets(endpoint *corev1.Endpoints) ([]string, error) {\n\tvar addrs []string\n\tfor _, subset := range endpoint.Subsets {\n\t\tfor _, ipAddr := range subset.Addresses {\n\t\t\tfor _, port := range subset.Ports {\n\t\t\t\ts := ipAddr.IP + \":\" + strconv.Itoa(int(port.Port))\n\t\t\t\taddrs = append(addrs, s)\n\t\t\t}\n\t\t}\n\t}\n\tsort.Strings(addrs)\n\treturn addrs, nil\n}\n\nfunc (prom *PrometheusMonitor) IsMonitorEnabled(cluster *kstonev1alpha2.EtcdCluster) bool {\n\treturn featureutil.IsFeatureGateEnabled(cluster.ObjectMeta.Annotations, kstonev1alpha2.KStoneFeatureMonitor)\n}\n\n// Equal checks to Update ServiceMonitor & svc & ep, when label & memberIp change, update\nfunc (prom *PrometheusMonitor) Equal(cluster *kstonev1alpha2.EtcdCluster) bool {\n\tvar epAddrs []string\n\tepLabels := make(map[string]string)\n\n\tvar clusterEndpoints []string\n\tfor _, m := range cluster.Status.Members {\n\t\titems := strings.Split(m.ExtensionClientUrl, \":\")\n\t\tendPoint := strings.TrimPrefix(items[1], \"//\")\n\t\tclusterEndpoints = append(clusterEndpoints, endPoint+\":\"+items[2])\n\t}\n\n\tendpoints, err := prom.GetEtcdEndpoint(cluster.GetNamespace(), cluster.Name)\n\tif err != nil {\n\t\tif !apierrors.IsNotFound(err) {\n\t\t\tklog.Errorf(\"get endpoint failed, err is %v\", err)\n\t\t\treturn false\n\t\t}\n\t} else {\n\t\tepAddrs, err = prom.UnpackEndPointSubsets(endpoints)\n\t\tif err != nil {\n\t\t\tklog.Errorf(\"unpack endpoint failed, err is %v\", err)\n\t\t\treturn false\n\t\t}\n\t}\n\n\tif reflect.DeepEqual(epLabels, cluster.ObjectMeta.Labels) &&\n\t\treflect.DeepEqual(epAddrs, clusterEndpoints) {\n\t\treturn false\n\t}\n\treturn true\n}\n\n// initEtcdServiceMonitor inits cluster serviceMonitor\nfunc (prom *PrometheusMonitor) initEtcdServiceMonitor(cluster *kstonev1alpha2.EtcdCluster) (\n\t*promapiv1.ServiceMonitor,\n\terror) {\n\tcertName := cluster.ObjectMeta.Annotations[util.ClusterTLSSecretName]\n\tendpointList := make([]promapiv1.Endpoint, 0)\n\n\tif certName == \"\" {\n\t\tcertName = DefaultEtcdV3SecretName\n\t}\n\trelabel := &promapiv1.RelabelConfig{\n\t\tAction: \"labelmap\",\n\t\tRegex:  \"__meta_kubernetes_service_label_(.+)\",\n\t}\n\treplaceRelabel := &promapiv1.RelabelConfig{\n\t\tAction:      \"replace\",\n\t\tRegex:       \"(.*)-(.*)-(.*)-(.*)\",\n\t\tReplacement: \"$1.$2.$3.$4\",\n\t\tSourceLabels: []string{\n\t\t\t\"endpoint\",\n\t\t},\n\t\tTargetLabel: \"endpoint\",\n\t}\n\n\tscheme := \"http\"\n\tif strings.HasPrefix(cluster.Status.ServiceName, \"https\") {\n\t\tscheme = \"https\"\n\t}\n\n\tsecretName := certName\n\tif strings.Contains(secretName, \"/\") {\n\t\tsecretName = strings.Split(secretName, \"/\")[1]\n\t}\n\tfor _, memberStatus := range cluster.Status.Members {\n\t\tendpoint := promapiv1.Endpoint{\n\t\t\tPort:     strings.ReplaceAll(memberStatus.Endpoint, \".\", \"-\"),\n\t\t\tScheme:   scheme,\n\t\t\tInterval: \"30s\",\n\t\t\tRelabelConfigs: []*promapiv1.RelabelConfig{\n\t\t\t\trelabel,\n\t\t\t\treplaceRelabel,\n\t\t\t},\n\t\t\tProxyURL: nil,\n\t\t}\n\t\tif scheme == \"https\" {\n\t\t\tendpoint.TLSConfig = &promapiv1.TLSConfig{\n\t\t\t\tSafeTLSConfig: promapiv1.SafeTLSConfig{\n\t\t\t\t\tCA: promapiv1.SecretOrConfigMap{\n\t\t\t\t\t\tSecret: &k8sV1.SecretKeySelector{\n\t\t\t\t\t\t\tLocalObjectReference: k8sV1.LocalObjectReference{\n\t\t\t\t\t\t\t\tName: secretName,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tKey: etcd.CliCAFile,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tCert: promapiv1.SecretOrConfigMap{\n\t\t\t\t\t\tSecret: &k8sV1.SecretKeySelector{\n\t\t\t\t\t\t\tLocalObjectReference: k8sV1.LocalObjectReference{\n\t\t\t\t\t\t\t\tName: secretName,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tKey: etcd.CliCertFile,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tKeySecret: &k8sV1.SecretKeySelector{\n\t\t\t\t\t\tLocalObjectReference: k8sV1.LocalObjectReference{\n\t\t\t\t\t\t\tName: secretName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tKey: etcd.CliKeyFile,\n\t\t\t\t\t},\n\t\t\t\t\tInsecureSkipVerify: true,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t\tendpointList = append(endpointList, endpoint)\n\t}\n\n\tlabels := cluster.ObjectMeta.Labels\n\tlabels[\"etcdName\"] = cluster.Name\n\tservicemonitor := &promapiv1.ServiceMonitor{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      cluster.Name,\n\t\t\tNamespace: cluster.GetNamespace(),\n\t\t\tLabels:    labels,\n\t\t},\n\t\tSpec: promapiv1.ServiceMonitorSpec{\n\t\t\tEndpoints:         endpointList,\n\t\t\tNamespaceSelector: promapiv1.NamespaceSelector{MatchNames: []string{cluster.GetNamespace()}},\n\t\t\tSelector: metav1.LabelSelector{MatchLabels: map[string]string{\n\t\t\t\t\"etcdName\": cluster.Name,\n\t\t\t}},\n\t\t},\n\t}\n\n\terr := controllerutil.SetOwnerReference(cluster, servicemonitor, platformscheme.Scheme)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn servicemonitor, nil\n}\n\n// initEtcdSvc inits cluster svc\nfunc (prom *PrometheusMonitor) initEtcdSvc(cluster *kstonev1alpha2.EtcdCluster) (*corev1.Service, error) {\n\tportList := make([]corev1.ServicePort, 0)\n\tcount := 0\n\tfor _, m := range cluster.Status.Members {\n\t\taddr := strings.Split(m.ExtensionClientUrl, \":\")\n\t\tport, _ := strconv.Atoi(addr[2])\n\t\tportName := strings.ReplaceAll(m.Endpoint, \".\", \"-\")\n\n\t\tif len(portList) > 0 {\n\t\t\tif portName == portList[len(portList)-1].Name {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\tservicePort := corev1.ServicePort{\n\t\t\tName:       portName,\n\t\t\tProtocol:   corev1.ProtocolTCP,\n\t\t\tPort:       int32(2379 + count),\n\t\t\tTargetPort: intstr.FromInt(port),\n\t\t}\n\t\tportList = append(portList, servicePort)\n\t\tcount++\n\t}\n\n\tlabelMap := cluster.ObjectMeta.Labels\n\tlabelMap[\"etcdName\"] = cluster.Name\n\n\tsvr := &corev1.Service{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      cluster.Name,\n\t\t\tNamespace: cluster.GetNamespace(),\n\t\t\tLabels:    labelMap,\n\t\t},\n\t\tSpec: corev1.ServiceSpec{\n\t\t\tPorts: portList,\n\t\t\tType:  corev1.ServiceTypeClusterIP,\n\t\t},\n\t}\n\n\tif cluster.Spec.ClusterType == kstonev1alpha2.EtcdClusterKstone {\n\t\tsvr.Spec.Selector = map[string]string{\n\t\t\t\"etcdcluster.etcd.tkestack.io/cluster-name\": cluster.Name,\n\t\t}\n\t}\n\n\terr := controllerutil.SetOwnerReference(cluster, svr, platformscheme.Scheme)\n\tif err != nil {\n\t\tklog.Errorf(\"set reference failed, err is %s, service is %s\", svr.Name)\n\t\treturn nil, err\n\t}\n\n\treturn svr, nil\n}\n\n// initEtcdEndpoint inits cluster ep\nfunc (prom *PrometheusMonitor) initEtcdEndpoint(cluster *kstonev1alpha2.EtcdCluster) (*corev1.Endpoints, error) {\n\tsubsets := make([]corev1.EndpointSubset, 0)\n\tif cluster.Spec.ClusterType == kstonev1alpha2.EtcdClusterImported {\n\t\tfor _, m := range cluster.Status.Members {\n\t\t\taddr := strings.Split(m.ExtensionClientUrl, \":\")\n\t\t\tport, err := strconv.Atoi(addr[2])\n\t\t\tif err != nil {\n\t\t\t\tklog.Errorf(\"failed to convert port string to int: %v\", err)\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\ts := corev1.EndpointSubset{\n\t\t\t\tAddresses: []corev1.EndpointAddress{\n\t\t\t\t\t{\n\t\t\t\t\t\tIP: strings.TrimPrefix(addr[1], \"//\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tPorts: []corev1.EndpointPort{\n\t\t\t\t\t{\n\t\t\t\t\t\tName:     strings.ReplaceAll(m.Endpoint, \".\", \"-\"),\n\t\t\t\t\t\tProtocol: corev1.ProtocolTCP,\n\t\t\t\t\t\tPort:     int32(port),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\tsubsets = append(subsets, s)\n\t\t}\n\t}\n\tep := &corev1.Endpoints{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      cluster.Name,\n\t\t\tNamespace: cluster.GetNamespace(),\n\t\t\tLabels:    cluster.ObjectMeta.Labels,\n\t\t},\n\t\tSubsets: subsets,\n\t}\n\treturn ep, nil\n}\n\n// CheckEqualIfDisabled Checks whether the monitoring resource has been deleted if monitor feature is disabled.\nfunc (prom *PrometheusMonitor) CheckEqualIfDisabled(cluster *kstonev1alpha2.EtcdCluster) bool {\n\t_, err := prom.GetServiceMonitorTask(cluster.Namespace, cluster.Name)\n\tif err != nil && apierrors.IsNotFound(err) {\n\t\t_, err = prom.GetEtcdService(cluster.Namespace, cluster.Name)\n\t\tif err != nil && apierrors.IsNotFound(err) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// CheckEqualIfEnabled check whether the desired monitoring resources are consistent with the actual resources,\n// if monitor feature is enabled.\nfunc (prom *PrometheusMonitor) CheckEqualIfEnabled(cluster *kstonev1alpha2.EtcdCluster) bool {\n\tvar epAddrs []string\n\tepLabels := make(map[string]string)\n\n\tvar clusterEndpoints []string\n\tfor _, m := range cluster.Status.Members {\n\t\titems := strings.Split(m.ExtensionClientUrl, \":\")\n\t\tendPoint := strings.TrimPrefix(items[1], \"//\")\n\t\tclusterEndpoints = append(clusterEndpoints, endPoint+\":\"+items[2])\n\t}\n\n\tendpoints, err := prom.GetEtcdEndpoint(cluster.GetNamespace(), cluster.Name)\n\tif err != nil {\n\t\tklog.Errorf(\"get endpoint failed, cluster name %s,err is %v\", cluster.Name, err)\n\t\treturn false\n\t}\n\tif epAddrs, err = prom.UnpackEndPointSubsets(endpoints); err != nil {\n\t\tklog.Errorf(\"unpack endpoint failed, err is %v\", err)\n\t\treturn false\n\t}\n\n\tif reflect.DeepEqual(epLabels, cluster.ObjectMeta.Labels) &&\n\t\treflect.DeepEqual(epAddrs, clusterEndpoints) {\n\t\treturn true\n\t}\n\treturn false\n}\n\n// CleanPrometheusMonitor cleans prometheus monitor for etcdcluster if it is disabled\nfunc (prom *PrometheusMonitor) CleanPrometheusMonitor(cluster *kstonev1alpha2.EtcdCluster) error {\n\tif err := prom.DeleteServiceMonitor(cluster.Namespace, cluster.Name); err != nil && !apierrors.IsNotFound(err) {\n\t\treturn err\n\t}\n\tif err := prom.DeleteEtcdService(cluster.Namespace, cluster.Name); err != nil && !apierrors.IsNotFound(err) {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// SyncPrometheusMonitor syncs prometheus monitor for etcdcluster if it is enabled\nfunc (prom *PrometheusMonitor) SyncPrometheusMonitor(cluster *kstonev1alpha2.EtcdCluster) error {\n\ttaskName := cluster.Name\n\n\t// 1 init service\n\tnewSvc, nErr := prom.initEtcdSvc(cluster)\n\tif nErr != nil {\n\t\tklog.Errorf(\"init etcdSvc failed, err is %v, cluster is %s\", nErr, taskName)\n\t\treturn nErr\n\t}\n\tcurSvc, err := prom.GetEtcdService(cluster.GetNamespace(), taskName)\n\tif apierrors.IsNotFound(err) {\n\t\t_, err = prom.CreateEtcdService(newSvc)\n\t\tif err != nil {\n\t\t\tklog.Errorf(\"create etcd %s svr failed:%v\", taskName, err)\n\t\t\treturn err\n\t\t}\n\t} else if err != nil {\n\t\tklog.Errorf(\"get etcd %s svr failed:%v\", taskName, err)\n\t\treturn err\n\t} else if !prom.ServiceIsEquivalent(curSvc, newSvc) {\n\t\tnewSvc.Spec.ClusterIP = curSvc.Spec.ClusterIP\n\t\tnewSvc.ResourceVersion = curSvc.ResourceVersion\n\t\t_, err = prom.UpdateEtcdService(newSvc)\n\t\tif err != nil {\n\t\t\tklog.Errorf(\"failed to update etcd %s svr failed:%v\", taskName, err)\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// 2 init ep\n\tif cluster.Spec.ClusterType == kstonev1alpha2.EtcdClusterImported {\n\t\tnewEp, err := prom.initEtcdEndpoint(cluster)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tcurEp, err := prom.GetEtcdEndpoint(cluster.GetNamespace(), taskName)\n\t\tif apierrors.IsNotFound(err) {\n\t\t\t_, err = prom.CreateEtcdEndpoint(newEp)\n\t\t\tif err != nil {\n\t\t\t\tklog.Errorf(\"create etcd %s ep failed:%v\", taskName, err)\n\t\t\t\treturn err\n\t\t\t}\n\t\t} else if err != nil {\n\t\t\tklog.Errorf(\"get etcd %s ep failed:%v\", taskName, err)\n\t\t\treturn err\n\t\t} else if !prom.EndpointIsEquivalent(curEp, newEp) {\n\t\t\tnewEp.ResourceVersion = curEp.ResourceVersion\n\t\t\t_, err = prom.UpdateEtcdEndpoint(newEp)\n\t\t\tif err != nil {\n\t\t\t\tklog.Errorf(\"failed to update etcd %s ep,err is %v\", taskName, err)\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\n\t// 3 init servicemonitor\n\tnewServiceMonitor, err := prom.initEtcdServiceMonitor(cluster)\n\tif err != nil {\n\t\treturn err\n\t}\n\tcurServiceMonitor, err := prom.GetServiceMonitorTask(cluster.GetNamespace(), taskName)\n\tif apierrors.IsNotFound(err) {\n\t\t_, err = prom.CreateServiceMonitor(newServiceMonitor)\n\t\tif err != nil {\n\t\t\tklog.Errorf(\"create etcd %s service monitor failed:%v\", taskName, err)\n\t\t\treturn err\n\t\t}\n\t} else if err != nil {\n\t\tklog.Errorf(\"get etcd %s service monitor failed:%v\", taskName, err)\n\t\treturn err\n\t} else if !prom.ServiceMonitorIsEquivalent(curServiceMonitor, newServiceMonitor) {\n\t\tnewServiceMonitor.ResourceVersion = curServiceMonitor.ResourceVersion\n\t\t_, err = prom.UpdateServiceMonitor(newServiceMonitor)\n\t\tif err != nil {\n\t\t\tklog.Errorf(\"failed to update etcd %s service monitor,err is %v\", taskName, err)\n\t\t\treturn err\n\t\t}\n\t}\n\n\tklog.V(2).Infof(\"add etcd task %s succ\", taskName)\n\treturn err\n}\n"
  },
  {
    "path": "pkg/router/router.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage router\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/http/httputil\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/gin-contrib/pprof\"\n\t\"github.com/gin-gonic/gin\"\n\tclientv3 \"go.etcd.io/etcd/client/v3\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/client-go/tools/clientcmd\"\n\tklog \"k8s.io/klog/v2\"\n\n\t\"tkestack.io/kstone/cmd/kstone-api/config\"\n\t\"tkestack.io/kstone/pkg/authentication/request\"\n\t\"tkestack.io/kstone/pkg/backup\"\n\t\"tkestack.io/kstone/pkg/controllers/util\"\n\t\"tkestack.io/kstone/pkg/etcd\"\n\t\"tkestack.io/kstone/pkg/featureprovider\"\n\t\"tkestack.io/kstone/pkg/middlewares\"\n\n\t_ \"tkestack.io/kstone/pkg/authentication/providers\" // import token and authenticator provider\n\n\t_ \"tkestack.io/kstone/pkg/backup/providers\" // import backup provider\n\n\t_ \"tkestack.io/kstone/pkg/featureprovider/providers\" // import feature provider\n\n\tclientset \"tkestack.io/kstone/pkg/generated/clientset/versioned\"\n)\n\nvar (\n\tKubeScheme    = \"https\"\n\tKubeTarget    = os.Getenv(\"KUBE_TARGET\")\n\tKubeToken     = os.Getenv(\"KUBE_TOKEN\")\n\tWorkNamespace = \"kstone\"\n)\n\nconst (\n\tGroupName   = \"kstone.tkestack.io\"\n\tVersionName = \"v1alpha2\"\n\tapiPrefix   = \"/apis\"\n)\n\n// SetWorkNamespace sets work namespace\nfunc SetWorkNamespace(namespace string) {\n\tWorkNamespace = namespace\n}\n\n// NewRouter generates router\nfunc NewRouter() *gin.Engine {\n\tr := gin.Default()\n\n\tif config.Cfg.EnableProfiling {\n\t\tpprof.Register(r, fmt.Sprintf(\"%s/debug/pprof\", apiPrefix))\n\t}\n\n\tpublic := r.Group(apiPrefix)\n\tprivate := r.Group(apiPrefix)\n\n\tprivate.Use(middlewares.Auth())\n\n\tpublic.POST(\"/login\", Login)\n\n\tprivate.GET(\"/:resource\", ReverseProxy())\n\tprivate.POST(\"/:resource\", ReverseProxy())\n\tprivate.GET(\"/:resource/:name\", ReverseProxy())\n\tprivate.PUT(\"/:resource/:name\", ReverseProxy())\n\tprivate.PATCH(\"/:resource/:name\", ReverseProxy())\n\tprivate.DELETE(\"/:resource/:name\", ReverseProxy())\n\n\tprivate.GET(\"/etcd/:etcdName\", EtcdKeyList)\n\tprivate.GET(\"/backup/:etcdName\", BackupList)\n\tprivate.GET(\"/features\", FeatureList)\n\n\tprivate.GET(\"/users\", UserList)\n\tprivate.PUT(\"/user\", UserUpdate)\n\tprivate.POST(\"/user\", UserAdd)\n\tprivate.DELETE(\"/user\", UserDelete)\n\n\treturn r\n}\n\n// ReverseProxy reverses proxy to kubernetes api\nfunc ReverseProxy() gin.HandlerFunc {\n\ttarget := KubeTarget\n\n\treturn func(c *gin.Context) {\n\t\tresource := c.Param(\"resource\")\n\t\tname := c.Param(\"name\")\n\n\t\tdirector := func(req *http.Request) {\n\t\t\treq.URL.Scheme = KubeScheme\n\t\t\treq.URL.Host = target\n\t\t\treq.Host = target\n\t\t\t// set Authorization to add k8s token\n\t\t\treq.Header = map[string][]string{\n\t\t\t\t\"Authorization\": {\n\t\t\t\t\tfmt.Sprintf(\"Bearer %s\", KubeToken),\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tvar path string\n\t\t\t// handle different resource according to the resource type\n\t\t\tswitch resource {\n\t\t\tcase \"etcdclusters\":\n\t\t\t\tif name == \"\" {\n\t\t\t\t\tpath = fmt.Sprintf(\"/apis/%s/%s/namespaces/%s/%s\", GroupName, VersionName, WorkNamespace, resource)\n\t\t\t\t} else {\n\t\t\t\t\tpath = fmt.Sprintf(\"/apis/%s/%s/namespaces/%s/%s/%s\", GroupName, VersionName, WorkNamespace, resource, name)\n\t\t\t\t}\n\t\t\tcase \"secrets\":\n\t\t\t\tif name == \"\" {\n\t\t\t\t\tif req.Method == http.MethodPost || req.Method == http.MethodGet {\n\t\t\t\t\t\tpath = fmt.Sprintf(\"/api/v1/namespaces/%s/%s\", WorkNamespace, resource)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tpath = fmt.Sprintf(\"/api/v1/namespaces/%s/%s/%s\", WorkNamespace, resource, name)\n\t\t\t\t}\n\t\t\tcase \"configmaps\":\n\t\t\t\tif name == \"\" {\n\t\t\t\t\tif req.Method == http.MethodPost || req.Method == http.MethodGet {\n\t\t\t\t\t\tpath = fmt.Sprintf(\"/api/v1/namespaces/%s/%s\", WorkNamespace, resource)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tpath = fmt.Sprintf(\"/api/v1/namespaces/%s/%s/%s\", WorkNamespace, resource, name)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treq.URL.Path = path\n\t\t\treq.RequestURI = path\n\t\t}\n\t\tproxy := &httputil.ReverseProxy{Director: director}\n\t\tproxy.Transport = &http.Transport{\n\t\t\tProxy:               http.ProxyFromEnvironment,\n\t\t\tTLSHandshakeTimeout: 10 * time.Second,\n\t\t\tTLSClientConfig:     &tls.Config{InsecureSkipVerify: true},\n\t\t}\n\t\tproxy.ServeHTTP(c.Writer, c.Request)\n\t}\n}\n\n// EtcdKeyList returns etcd key list\nfunc EtcdKeyList(ctx *gin.Context) {\n\tetcdName := ctx.Param(\"etcdName\")\n\tetcdKey := ctx.DefaultQuery(\"key\", \"\")\n\n\t// generate etcd client\n\tcfg, err := clientcmd.BuildConfigFromFlags(\"\", \"\")\n\tif err != nil {\n\t\tklog.Errorf(err.Error())\n\t\tctx.JSON(http.StatusInternalServerError, err)\n\t\treturn\n\t}\n\n\tclusterClient, err := clientset.NewForConfig(cfg)\n\tif err != nil {\n\t\tklog.Errorf(err.Error())\n\t\tctx.JSON(http.StatusInternalServerError, err)\n\t\treturn\n\t}\n\n\tcluster, err := clusterClient.KstoneV1alpha2().EtcdClusters(WorkNamespace).\n\t\tGet(context.TODO(), etcdName, metav1.GetOptions{})\n\tif err != nil {\n\t\tklog.Errorf(err.Error())\n\t\tctx.JSON(http.StatusInternalServerError, err)\n\t\treturn\n\t}\n\n\tannotations := cluster.Annotations\n\tsecretName := \"\"\n\tif annotations != nil {\n\t\tif _, found := annotations[\"certName\"]; found {\n\t\t\tsecretName = annotations[\"certName\"]\n\t\t}\n\t}\n\tclientConfigGetter := etcd.NewClientConfigSecretGetter(util.NewSimpleClientBuilder(\"\"))\n\tklog.Infof(\"secretName: %s\", secretName)\n\tpath := fmt.Sprintf(\"%s/%s\", cluster.Namespace, cluster.Name)\n\tconfig, err := clientConfigGetter.New(path, secretName)\n\tif err != nil {\n\t\tklog.Errorf(err.Error())\n\t\tctx.JSON(http.StatusInternalServerError, err)\n\t\treturn\n\t}\n\n\tconfig.Endpoints = []string{cluster.Status.ServiceName}\n\n\tklog.Infof(\"endpoint: %s, ca: %s, cert: %s, key: %s\", cluster.Status.ServiceName, config.CaCert, config.Cert, config.Key)\n\tclient, err := etcd.NewClientv3(config)\n\tif err != nil {\n\t\tklog.Errorf(err.Error())\n\t\tctx.JSON(http.StatusInternalServerError, err)\n\t\treturn\n\t}\n\tdefer client.Close()\n\n\tif etcdKey == \"\" {\n\t\tresp, err := client.Get(context.TODO(), \"\", clientv3.WithPrefix(), clientv3.WithKeysOnly())\n\t\tif err != nil {\n\t\t\tklog.Errorf(err.Error())\n\t\t\tctx.JSON(http.StatusInternalServerError, err)\n\t\t\treturn\n\t\t}\n\n\t\tdata := make([]string, 0)\n\t\tfor _, value := range resp.Kvs {\n\t\t\tdata = append(data, string(value.Key))\n\t\t}\n\n\t\tctx.JSON(http.StatusOK, map[string]interface{}{\n\t\t\t\"code\": 0,\n\t\t\t\"data\": data,\n\t\t})\n\t\treturn\n\t}\n\tklog.Infof(\"get value by key: %s\", etcdKey)\n\tresp, err := client.Get(context.TODO(), etcdKey, clientv3.WithPrefix())\n\tif err != nil {\n\t\tklog.Errorf(err.Error())\n\t\tctx.JSON(http.StatusInternalServerError, err)\n\t\treturn\n\t}\n\tif resp.Count == 0 {\n\t\tctx.JSON(http.StatusNotFound, map[string]interface{}{\n\t\t\t\"code\": 1,\n\t\t\t\"data\": \"\",\n\t\t})\n\t} else {\n\t\tresult := map[string]interface{}{\n\t\t\t\"code\": 0,\n\t\t\t\"err\":  \"\",\n\t\t}\n\t\tif cluster.Annotations[\"kubernetes\"] == \"true\" && etcdKey != \"compact_rev_key\" {\n\t\t\tjsonValue := etcd.ConvertToJSON(resp.Kvs[0])\n\t\t\tinMediaType, in, err := etcd.DetectAndExtract(resp.Kvs[0].Value)\n\t\t\tif err != nil {\n\t\t\t\tklog.Errorf(err.Error())\n\t\t\t\tctx.JSON(http.StatusInternalServerError, err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\trespData, err := etcd.ConvertToData(inMediaType, in)\n\t\t\tif err != nil {\n\t\t\t\tklog.Errorf(err.Error())\n\t\t\t\tif respData == nil {\n\t\t\t\t\trespData = make(map[string]string)\n\t\t\t\t}\n\t\t\t\tresult[\"err\"] = err.Error()\n\t\t\t}\n\t\t\trespData[\"json\"] = jsonValue\n\t\t\trespDataList := make([]map[string]string, 0)\n\t\t\tfor dataType, value := range respData {\n\t\t\t\trespDataList = append(respDataList, map[string]string{\n\t\t\t\t\t\"type\": dataType,\n\t\t\t\t\t\"data\": value,\n\t\t\t\t})\n\t\t\t}\n\t\t\tresult[\"data\"] = respDataList\n\t\t} else {\n\t\t\tresult[\"data\"] = []map[string]string{\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"javascript\",\n\t\t\t\t\t\"data\": string(resp.Kvs[0].Value),\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t\tctx.JSON(http.StatusOK, result)\n\t}\n}\n\n// BackupList returns backup list\nfunc BackupList(ctx *gin.Context) {\n\tetcdName := ctx.Param(\"etcdName\")\n\n\tclientBuilder := util.NewSimpleClientBuilder(\"\")\n\n\t// generate k8s client\n\tclusterClient, err := clientset.NewForConfig(clientBuilder.ConfigOrDie())\n\tif err != nil {\n\t\tklog.Errorf(err.Error())\n\t\tctx.JSON(http.StatusInternalServerError, err)\n\t\treturn\n\t}\n\n\t// get cluster\n\tcluster, err := clusterClient.KstoneV1alpha2().EtcdClusters(WorkNamespace).\n\t\tGet(context.TODO(), etcdName, metav1.GetOptions{})\n\tif err != nil {\n\t\tklog.Errorf(err.Error())\n\t\tctx.JSON(http.StatusInternalServerError, err)\n\t\treturn\n\t}\n\n\t// get backup config\n\tbackupConfig, err := backup.GetBackupConfig(cluster)\n\tif err != nil {\n\t\tklog.Errorf(\"failed to get backup config,cluster %s,err is %v\", cluster.Name, err)\n\t\tctx.JSON(http.StatusInternalServerError, err)\n\t}\n\n\t// get specified backup storage provider\n\tstorage, err := backup.GetBackupStorageProvider(string(backupConfig.StorageType), &backup.StorageConfig{\n\t\tKubeCli: clientBuilder.ClientOrDie(),\n\t})\n\tif err != nil {\n\t\tklog.Errorf(err.Error())\n\t\tctx.JSON(http.StatusInternalServerError, err)\n\t\treturn\n\t}\n\tresp, err := storage.List(cluster)\n\tif err != nil {\n\t\tklog.Errorf(err.Error())\n\t\tctx.JSON(http.StatusInternalServerError, err)\n\t\treturn\n\t}\n\tctx.JSON(http.StatusOK, resp)\n}\n\n// FeatureList returns all features\nfunc FeatureList(ctx *gin.Context) {\n\tfeatures := featureprovider.ListFeatureProvider()\n\tctx.JSON(http.StatusOK, features)\n}\n\n// UserList list all users\nfunc UserList(ctx *gin.Context) {\n\trsp, err := request.UserListRequest(ctx)\n\tif err != nil {\n\t\tctx.JSON(http.StatusInternalServerError, *rsp)\n\t\treturn\n\t}\n\tctx.JSON(http.StatusOK, *rsp)\n}\n\n// UserUpdate updates users info\nfunc UserUpdate(ctx *gin.Context) {\n\trsp, err := request.UserUpdateRequest(ctx)\n\tif err != nil {\n\t\tctx.JSON(http.StatusInternalServerError, *rsp)\n\t\treturn\n\t}\n\tctx.JSON(http.StatusOK, *rsp)\n}\n\n// UserAdd adds user\nfunc UserAdd(ctx *gin.Context) {\n\trsp, err := request.UserAddRequest(ctx)\n\tif err != nil {\n\t\tctx.JSON(http.StatusInternalServerError, *rsp)\n\t\treturn\n\t}\n\tctx.JSON(http.StatusOK, *rsp)\n}\n\n// UserDelete deletes user\nfunc UserDelete(ctx *gin.Context) {\n\trsp, err := request.UserDeleteRequest(ctx)\n\tif err != nil {\n\t\tctx.JSON(http.StatusInternalServerError, *rsp)\n\t\treturn\n\t}\n\tctx.JSON(http.StatusOK, *rsp)\n}\n\n// Login returns login info\nfunc Login(ctx *gin.Context) {\n\trsp, ok, err := request.LoginRequest(ctx)\n\tif !ok || err != nil {\n\t\tctx.JSON(http.StatusUnauthorized, *rsp)\n\t\treturn\n\t}\n\tctx.JSON(http.StatusOK, *rsp)\n}\n"
  },
  {
    "path": "pkg/signals/signal.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage signals\n\nimport (\n\t\"os\"\n\t\"os/signal\"\n)\n\nvar onlyOneSignalHandler = make(chan struct{})\n\n// SetupSignalHandler registered for SIGTERM and SIGINT. A stop channel is returned\n// which is closed on one of these signals. If a second signal is caught, the program\n// is terminated with exit code 1.\nfunc SetupSignalHandler() (stopCh <-chan struct{}) {\n\tclose(onlyOneSignalHandler) // panics when called twice\n\n\tstop := make(chan struct{})\n\tc := make(chan os.Signal, 2)\n\tsignal.Notify(c, shutdownSignals...)\n\tgo func() {\n\t\t<-c\n\t\tclose(stop)\n\t\t<-c\n\t\tos.Exit(1) // second signal. Exit directly.\n\t}()\n\n\treturn stop\n}\n"
  },
  {
    "path": "pkg/signals/signal_posix.go",
    "content": "//go:build !windows\n// +build !windows\n\n/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage signals\n\nimport (\n\t\"os\"\n\t\"syscall\"\n)\n\nvar shutdownSignals = []os.Signal{os.Interrupt, syscall.SIGTERM}\n"
  },
  {
    "path": "pkg/signals/signal_windows.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage signals\n\nimport (\n\t\"os\"\n)\n\nvar shutdownSignals = []os.Signal{os.Interrupt}\n"
  },
  {
    "path": "test/e2e/e2e_test.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage e2e\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/onsi/ginkgo\"\n\t\"github.com/onsi/gomega\"\n\tmonitoringv1 \"github.com/prometheus-operator/prometheus-operator/pkg/client/versioned/typed/monitoring/v1\"\n\tv1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/client-go/dynamic\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/client-go/rest\"\n\t\"k8s.io/client-go/tools/clientcmd\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\tclientset \"tkestack.io/kstone/pkg/generated/clientset/versioned\"\n\t\"tkestack.io/kstone/test/fixtures\"\n\t\"tkestack.io/kstone/test/testfiles\"\n)\n\nconst (\n\t// TestSuiteSetupTimeOut defines the time after which the suite setup times out.\n\tTestSuiteSetupTimeOut = 300 * time.Second\n\t// TestSuiteTeardownTimeOut defines the time after which the suite tear down times out.\n\tTestSuiteTeardownTimeOut = 300 * time.Second\n\t// pollInterval defines the interval time for a poll operation.\n\tpollInterval = 1 * time.Second\n\t// pollTimeout defines the time after which the poll operation times out.\n\tpollTimeout = 180 * time.Second\n)\n\nvar (\n\tkubeconfig        string\n\tfixturesDir       string\n\trestConfig        *rest.Config\n\tkubeClient        kubernetes.Interface\n\tetcdClusterClient clientset.Interface\n\tdynamicCli        dynamic.Interface\n\tpromCli           *monitoringv1.MonitoringV1Client\n)\n\nfunc TestE2E(t *testing.T) {\n\tgomega.RegisterFailHandler(ginkgo.Fail)\n\tginkgo.RunSpecs(t, \"e2e suite\")\n}\n\nvar _ = ginkgo.BeforeSuite(func() {\n\t// KUBECONFIG=/Users/etcd/.kube/config\n\tworkspace := os.Getenv(\"GITHUB_WORKSPACE\")\n\tgomega.Expect(workspace).ShouldNot(gomega.BeEmpty())\n\n\tkubeconfig = workspace + \"/\" + os.Getenv(\"E2E_KUBECONFIG_PATH\")\n\tgomega.Expect(kubeconfig).ShouldNot(gomega.BeEmpty())\n\n\t// FIXTURESDIR=/Users/etcd/go/src/tkestack.io/kstone/test/fixtures/manifests\n\tfixturesDir = workspace + \"/\" + os.Getenv(\"FIXTURES_DIR\")\n\tgomega.Expect(fixturesDir).ShouldNot(gomega.BeEmpty())\n\n\tvar err error\n\trestConfig, err = clientcmd.BuildConfigFromFlags(\"\", kubeconfig)\n\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\n\tkubeClient, err = kubernetes.NewForConfig(restConfig)\n\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\n\tdynamicCli, err = dynamic.NewForConfig(restConfig)\n\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\n\tetcdClusterClient, err = clientset.NewForConfig(restConfig)\n\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\n\tpromCli, err = monitoringv1.NewForConfig(restConfig)\n\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\n\ttestfiles.AddFileSource(testfiles.RootFileSource{Root: fixturesDir})\n\n\terr = CreateTmpTestEtcdCluster()\n\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\n\terr = createEtcdCluster(fixtures.DefaultHTTPKstoneEtcdOperatorClusterName, 1, kstonev1alpha2.EtcdClusterKstone, fixtures.DefaultFeatureGate, \"\", \"http\")\n\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\n\terr = createEtcdCluster(fixtures.DefaultHTTPSKstoneEtcdOperatorClusterName, 1, kstonev1alpha2.EtcdClusterKstone, fixtures.DefaultFeatureGate, \"\", \"https\")\n\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\n\tpodIP, err := getEtcdPodIP()\n\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\terr = createEtcdCluster(fixtures.DefaultImportedClusterName, 3, kstonev1alpha2.EtcdClusterImported, fixtures.DefaultFeatureGate, podIP+\":2379\", \"\")\n\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\n}, TestSuiteSetupTimeOut.Seconds())\n\nvar _ = ginkgo.AfterSuite(func() {\n\terr := DeleteTmpTestEtcdCluster()\n\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\n\terr = cleanAllEtcdCluster()\n\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\n}, TestSuiteTeardownTimeOut.Seconds())\n\nfunc CreateTmpTestEtcdCluster() error {\n\tsts, err := fixtures.StatefulSetFromManifest(fixtures.DefaultTestClusterStatefulsetYaml, fixtures.DefaultKstoneNamespace)\n\tif err != nil {\n\t\treturn err\n\t}\n\t_, err = kubeClient.AppsV1().StatefulSets(fixtures.DefaultKstoneNamespace).Create(context.TODO(), sts, metav1.CreateOptions{})\n\tif err != nil {\n\t\treturn err\n\t}\n\tsvc, err := fixtures.SvcFromManifest(fixtures.DefaultTestClusterSvcYaml)\n\tif err != nil {\n\t\treturn err\n\t}\n\t_, err = kubeClient.CoreV1().Services(fixtures.DefaultKstoneNamespace).Create(context.TODO(), svc, metav1.CreateOptions{})\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc GetTmpTestEtcdClusterPodIP() (string, error) {\n\tvar podIP string\n\tpodList, err := kubeClient.CoreV1().Pods(fixtures.DefaultKstoneNamespace).List(context.TODO(), metav1.ListOptions{LabelSelector: \"app=etcd-test\"})\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tfor i := 0; i < len(podList.Items); i++ {\n\t\tif podList.Items[i].Status.Phase == v1.PodRunning &&\n\t\t\tlen(podList.Items[i].Status.Conditions) > 0 &&\n\t\t\tpodList.Items[i].Status.Conditions[0].Status == v1.ConditionTrue &&\n\t\t\tpodList.Items[i].Status.PodIP != \"\" {\n\t\t\tpodIP = podList.Items[i].Status.PodIP\n\t\t\treturn podIP, nil\n\t\t}\n\t}\n\treturn podIP, fmt.Errorf(\"etcd pod ip is invalid\")\n}\n\nfunc DeleteTmpTestEtcdCluster() error {\n\tsts, err := fixtures.StatefulSetFromManifest(fixtures.DefaultTestClusterStatefulsetYaml, fixtures.DefaultKstoneNamespace)\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = kubeClient.AppsV1().StatefulSets(fixtures.DefaultKstoneNamespace).Delete(context.TODO(), sts.Name, metav1.DeleteOptions{})\n\tif err != nil {\n\t\treturn err\n\t}\n\tsvc, err := fixtures.SvcFromManifest(fixtures.DefaultTestClusterSvcYaml)\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = kubeClient.CoreV1().Services(fixtures.DefaultKstoneNamespace).Delete(context.TODO(), svc.Name, metav1.DeleteOptions{})\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "test/e2e/etcdcluster_test.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage e2e\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/onsi/ginkgo\"\n\t\"github.com/onsi/gomega\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/util/wait\"\n\t\"k8s.io/klog/v2\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\t\"tkestack.io/kstone/pkg/backup\"\n\t\"tkestack.io/kstone/test/fixtures\"\n)\n\nvar _ = ginkgo.Describe(\"imported etcdcluster\", getGinkgoFunc(fixtures.DefaultImportedClusterName, fixtures.DefaultImportedPodName))\nvar _ = ginkgo.Describe(\"kstone-etcd-operator http etcdcluster\", getGinkgoFunc(fixtures.DefaultHTTPKstoneEtcdOperatorClusterName, fixtures.DefaultHTTPKstoneEtcdOperatorPodName))\nvar _ = ginkgo.Describe(\"kstone-etcd-operator https etcdcluster\", getGinkgoFunc(fixtures.DefaultHTTPSKstoneEtcdOperatorClusterName, fixtures.DefaultHTTPSKstoneEtcdOperatorPodName))\n\nfunc getGinkgoFunc(clusterName, podName string) func() {\n\treturn func() {\n\t\tginkgo.Describe(\"create an etcdcluster and enable monitor,backup,healthy,request,consistency,alarm,backupcheck features\", func() {\n\n\t\t\tginkgo.It(\"ensure cluster status to be running\", func() {\n\t\t\t\terr := waitClusterStatusToRunning(clusterName)\n\t\t\t\tif err != nil {\n\t\t\t\t\tPrintTraceInfo(clusterName, podName)\n\t\t\t\t}\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should generate etcdinspection/consistency resources\", func() {\n\t\t\t\terr := CheckInspectionEnabled(clusterName, kstonev1alpha2.KStoneFeatureConsistency)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should generate etcdinspection/healthy resources\", func() {\n\t\t\t\terr := CheckInspectionEnabled(clusterName, kstonev1alpha2.KStoneFeatureHealthy)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should generate etcdinspection/request resources\", func() {\n\t\t\t\terr := CheckInspectionEnabled(clusterName, kstonev1alpha2.KStoneFeatureRequest)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should generate etcdinspection/alarm resources\", func() {\n\t\t\t\terr := CheckInspectionEnabled(clusterName, kstonev1alpha2.KStoneFeatureAlarm)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should generate etcdinspection/backupcheck resources\", func() {\n\t\t\t\terr := CheckInspectionEnabled(clusterName, kstonev1alpha2.KStoneFeatureBackupCheck)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should generate prometheus servicemonitor resources\", func() {\n\t\t\t\terr := CheckServiceMonitorEnabled(clusterName)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should generate etcdbackup resources\", func() {\n\t\t\t\terr := CheckBackupEnabled(clusterName)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should be able to disable etcdinspection/consistency feature\", func() {\n\t\t\t\terr := EnsureInspectionDisabled(clusterName, kstonev1alpha2.KStoneFeatureConsistency)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should be able to disable etcdinspection/healthy feature\", func() {\n\t\t\t\terr := EnsureInspectionDisabled(clusterName, kstonev1alpha2.KStoneFeatureHealthy)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should be able to disable etcdinspection/request feature\", func() {\n\t\t\t\terr := EnsureInspectionDisabled(clusterName, kstonev1alpha2.KStoneFeatureRequest)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should be able to disable etcdinspection/alarm feature\", func() {\n\t\t\t\terr := EnsureInspectionDisabled(clusterName, kstonev1alpha2.KStoneFeatureAlarm)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should be able to disable etcdinspection/backupcheck feature\", func() {\n\t\t\t\terr := EnsureInspectionDisabled(clusterName, kstonev1alpha2.KStoneFeatureBackupCheck)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should be able to disable prometheus servicemonitor feature\", func() {\n\t\t\t\terr := EnsureServiceMonitorDisabled(clusterName)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should be able to disable etcdbackup feature\", func() {\n\t\t\t\terr := EnsureBackupDisabled(clusterName)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\t\t})\n\n\t\tginkgo.Describe(\"delete an existed etcdcluster\", func() {\n\t\t\tginkgo.It(\"kstone should delete etcd cluster\", func() {\n\t\t\t\terr := deleteEtcdCluster(clusterName)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should delete servicemonitor resources\", func() {\n\t\t\t\terr := CheckServiceMonitorDisabled(clusterName)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should delete etcdinspection/healthy resources\", func() {\n\t\t\t\terr := CheckInspectionDisabled(clusterName, kstonev1alpha2.KStoneFeatureHealthy)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should delete etcdinspection/request resources\", func() {\n\t\t\t\terr := CheckInspectionDisabled(clusterName, kstonev1alpha2.KStoneFeatureRequest)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should delete etcdinspection/consistency resources\", func() {\n\t\t\t\terr := CheckInspectionDisabled(clusterName, kstonev1alpha2.KStoneFeatureConsistency)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should delete etcdinspection/alarm resources\", func() {\n\t\t\t\terr := CheckInspectionDisabled(clusterName, kstonev1alpha2.KStoneFeatureAlarm)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should delete etcdinspection/backupcheck resources\", func() {\n\t\t\t\terr := CheckInspectionDisabled(clusterName, kstonev1alpha2.KStoneFeatureBackupCheck)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t\tginkgo.It(\"kstone should delete etcdbackup resources\", func() {\n\t\t\t\terr := CheckBackupDisabled(clusterName)\n\t\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t\t})\n\n\t\t})\n\t}\n}\n\nfunc createEtcdCluster(name string, replicas uint, clusterType kstonev1alpha2.EtcdClusterType, featureGate, clusterAddr, scheme string) error {\n\tetcdcluster := fixtures.NewEtcdCluster(name, replicas, clusterType, featureGate, clusterAddr, scheme)\n\t_, err := etcdClusterClient.KstoneV1alpha2().EtcdClusters(fixtures.DefaultKstoneNamespace).Create(context.TODO(), etcdcluster, metav1.CreateOptions{})\n\treturn err\n}\n\nfunc deleteEtcdCluster(name string) error {\n\terr := etcdClusterClient.KstoneV1alpha2().EtcdClusters(fixtures.DefaultKstoneNamespace).Delete(context.TODO(), name, metav1.DeleteOptions{})\n\treturn err\n}\n\nfunc cleanAllEtcdCluster() error {\n\tclusters, err := etcdClusterClient.KstoneV1alpha2().EtcdClusters(fixtures.DefaultKstoneNamespace).List(context.TODO(), metav1.ListOptions{})\n\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\tfor i := 0; i < len(clusters.Items); i++ {\n\t\tif clusters.Items[i].Annotations[\"autoTest\"] == \"true\" {\n\t\t\terr = deleteEtcdCluster(clusters.Items[i].Name)\n\t\t\tgomega.Expect(err).ShouldNot(gomega.HaveOccurred())\n\t\t}\n\t}\n\treturn err\n}\n\nfunc getEtcdPodIP() (string, error) {\n\tvar podIP string\n\terr := wait.PollImmediate(pollInterval, pollTimeout, func() (done bool, err error) {\n\t\tpodIP, err = GetTmpTestEtcdClusterPodIP()\n\t\tif err != nil {\n\t\t\treturn false, nil\n\t\t}\n\t\treturn true, nil\n\t})\n\treturn podIP, err\n}\n\nfunc waitClusterStatusToRunning(clusterName string) error {\n\treturn wait.PollImmediate(pollInterval, pollTimeout, func() (done bool, err error) {\n\t\tcluster, err := etcdClusterClient.KstoneV1alpha2().EtcdClusters(fixtures.DefaultKstoneNamespace).Get(context.TODO(), clusterName, metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\tif apierrors.IsNotFound(err) {\n\t\t\t\treturn false, nil\n\t\t\t}\n\t\t\treturn false, err\n\t\t}\n\t\tif cluster.Status.Phase == kstonev1alpha2.EtcdClusterRunning {\n\t\t\treturn true, nil\n\t\t}\n\t\treturn false, nil\n\t})\n}\n\nfunc EnsureBackupDisabled(clusterName string) error {\n\treturn wait.PollImmediate(pollInterval, pollTimeout, func() (done bool, err error) {\n\t\terr = DisableFeature(clusterName, kstonev1alpha2.KStoneFeatureBackup)\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\terr = CheckBackupDisabled(clusterName)\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\treturn true, nil\n\t})\n}\n\nfunc CheckBackupEnabled(clusterName string) error {\n\treturn wait.PollImmediate(pollInterval, pollTimeout, func() (done bool, err error) {\n\t\t_, err = dynamicCli.Resource(backup.BackupSchema).Namespace(fixtures.DefaultKstoneNamespace).Get(context.TODO(), clusterName, metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\tif apierrors.IsNotFound(err) {\n\t\t\t\treturn false, nil\n\t\t\t}\n\t\t\treturn false, err\n\t\t}\n\t\treturn true, nil\n\t})\n}\n\nfunc CheckBackupDisabled(clusterName string) error {\n\treturn wait.PollImmediate(pollInterval, pollTimeout, func() (done bool, err error) {\n\t\t_, err = dynamicCli.Resource(backup.BackupSchema).Namespace(fixtures.DefaultKstoneNamespace).Get(context.TODO(), clusterName, metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\tif apierrors.IsNotFound(err) {\n\t\t\t\treturn true, nil\n\t\t\t}\n\t\t\treturn false, err\n\t\t}\n\t\treturn false, nil\n\t})\n}\n\nfunc EnsureServiceMonitorDisabled(clusterName string) error {\n\treturn wait.PollImmediate(pollInterval, pollTimeout, func() (done bool, err error) {\n\t\terr = DisableFeature(clusterName, kstonev1alpha2.KStoneFeatureMonitor)\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\terr = CheckServiceMonitorDisabled(clusterName)\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\treturn true, nil\n\t})\n}\n\nfunc CheckServiceMonitorEnabled(clusterName string) error {\n\treturn wait.PollImmediate(pollInterval, pollTimeout, func() (done bool, err error) {\n\t\t_, err = promCli.ServiceMonitors(fixtures.DefaultKstoneNamespace).Get(context.TODO(), clusterName, metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\tif apierrors.IsNotFound(err) {\n\t\t\t\treturn false, nil\n\t\t\t}\n\t\t\treturn false, err\n\t\t}\n\t\treturn true, nil\n\t})\n}\n\nfunc CheckServiceMonitorDisabled(clusterName string) error {\n\treturn wait.PollImmediate(pollInterval, pollTimeout, func() (done bool, err error) {\n\t\t_, err = promCli.ServiceMonitors(fixtures.DefaultKstoneNamespace).Get(context.TODO(), clusterName, metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\tif apierrors.IsNotFound(err) {\n\t\t\t\treturn true, nil\n\t\t\t}\n\t\t\treturn false, err\n\t\t}\n\t\treturn false, nil\n\t})\n}\n\nfunc EnsureInspectionDisabled(clusterName string, feature kstonev1alpha2.KStoneFeature) error {\n\treturn wait.PollImmediate(pollInterval, pollTimeout, func() (done bool, err error) {\n\t\terr = DisableFeature(clusterName, feature)\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\terr = CheckInspectionDisabled(clusterName, feature)\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\treturn true, nil\n\t})\n}\n\nfunc CheckInspectionEnabled(clusterName string, feature kstonev1alpha2.KStoneFeature) error {\n\treturn wait.PollImmediate(pollInterval, pollTimeout, func() (done bool, err error) {\n\t\t_, err = etcdClusterClient.KstoneV1alpha2().EtcdInspections(fixtures.DefaultKstoneNamespace).Get(context.TODO(), clusterName+\"-\"+string(feature), metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\tif apierrors.IsNotFound(err) {\n\t\t\t\treturn false, nil\n\t\t\t}\n\t\t\treturn false, err\n\t\t}\n\t\treturn true, nil\n\t})\n}\n\nfunc CheckInspectionDisabled(clusterName string, feature kstonev1alpha2.KStoneFeature) error {\n\treturn wait.PollImmediate(pollInterval, pollTimeout, func() (done bool, err error) {\n\t\t_, err = etcdClusterClient.KstoneV1alpha2().EtcdInspections(fixtures.DefaultKstoneNamespace).Get(context.TODO(), clusterName+\"-\"+string(feature), metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\tif apierrors.IsNotFound(err) {\n\t\t\t\treturn true, nil\n\t\t\t}\n\t\t\treturn false, err\n\t\t}\n\t\treturn false, nil\n\t})\n}\n\nfunc DisableFeature(clusterName string, feature kstonev1alpha2.KStoneFeature) error {\n\treturn wait.PollImmediate(pollInterval, pollTimeout, func() (done bool, err error) {\n\t\tcluster, err := etcdClusterClient.KstoneV1alpha2().EtcdClusters(fixtures.DefaultKstoneNamespace).Get(context.TODO(), clusterName, metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\tannotations := cluster.ObjectMeta.Annotations\n\t\tannotations = UpdateAnnotationFeature(annotations, feature, false)\n\t\tif annotations == nil {\n\t\t\treturn false, errors.New(\"can't change annotation\")\n\t\t}\n\t\t_, err = etcdClusterClient.KstoneV1alpha2().EtcdClusters(fixtures.DefaultKstoneNamespace).Update(context.TODO(), cluster, metav1.UpdateOptions{})\n\t\tif err != nil {\n\t\t\tif apierrors.IsConflict(err) {\n\t\t\t\treturn false, nil\n\t\t\t}\n\t\t\treturn false, err\n\t\t}\n\t\treturn true, nil\n\t})\n}\n\nfunc UpdateAnnotationFeature(annotations map[string]string, name kstonev1alpha2.KStoneFeature, open bool) map[string]string {\n\tif gates, found := annotations[kstonev1alpha2.KStoneFeatureAnno]; found && gates != \"\" {\n\t\tfeaturelist := strings.Split(gates, \",\")\n\t\tfeature := string(name)\n\t\tnewItem := feature + \"=\" + strconv.FormatBool(open)\n\t\tfor _, item := range featurelist {\n\t\t\tif strings.Contains(item, feature) {\n\t\t\t\tannotations[kstonev1alpha2.KStoneFeatureAnno] = strings.Replace(gates, item, newItem, 1)\n\t\t\t\treturn annotations\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc PrintTraceInfo(clusterName, podName string) {\n\tcmd1 := \"kubectl describe po \" + podName + \" -n \" + fixtures.DefaultKstoneNamespace\n\tcmd2 := \"kubectl describe cluster \" + clusterName + \" -n \" + fixtures.DefaultKstoneNamespace\n\tcmd3 := \"kubectl describe etcd \" + clusterName + \" -n \" + fixtures.DefaultKstoneNamespace\n\tcmd4 := \"kubectl logs \" + podName + \" -n \" + fixtures.DefaultKstoneNamespace\n\tcmds := []string{cmd1, cmd2, cmd3, cmd4}\n\tnodeName, err := os.Hostname()\n\tif err != nil {\n\t\tklog.Errorf(\"unable to get hostname\")\n\t} else {\n\t\tcmd5 := \"kubectl describe no \" + nodeName\n\t\tcmds = append(cmds, cmd5)\n\t}\n\tfor _, cmd := range cmds {\n\t\tcmnd, err := exec.Command(\"sh\", \"-c\", cmd).Output()\n\t\tif err != nil {\n\t\t\tklog.Errorf(\"failed to exec command, command is %s, err is %s\", cmd, err)\n\t\t} else {\n\t\t\tklog.Info(string(cmnd))\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "test/fixtures/fixtures.go",
    "content": "/*\n * Tencent is pleased to support the open source community by making TKEStack\n * available.\n *\n * Copyright (C) 2012-2023 Tencent. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the\n * License at\n *\n * https://opensource.org/licenses/Apache-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, WITHOUT\n * WARRANTIES OF ANY KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations under the License.\n */\n\npackage fixtures\n\nimport (\n\t\"fmt\"\n\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tv1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\tutilyaml \"k8s.io/apimachinery/pkg/util/yaml\"\n\tscheme \"k8s.io/client-go/kubernetes/scheme\"\n\n\tkstonev1alpha2 \"tkestack.io/kstone/pkg/apis/kstone/v1alpha2\"\n\ttestfiles2 \"tkestack.io/kstone/test/testfiles\"\n)\n\nconst (\n\tDefaultFeatureGate                        = \"monitor=true,consistency=true,healthy=true,request=true,backup=true,alarm=true,backupcheck=true\"\n\tDefaultTestClusterAddr                    = \"etcd-test-headless.default.svc.cluster.local:2379\"\n\tDefaultTestClusterStatefulsetYaml         = \"etcd_statefulset.yaml\"\n\tDefaultTestClusterSvcYaml                 = \"etcd_service.yaml\"\n\tDefaultKstoneNamespace                    = \"kstone\"\n\tDefaultImportedClusterName                = \"kstone-test\"\n\tDefaultImportedPodName                    = \"etcd-test-0\"\n\tDefaultNamespace                          = \"default\"\n\tDefaultHTTPKstoneEtcdOperatorClusterName  = \"kstone-etcd-operator-http-test\"\n\tDefaultHTTPKstoneEtcdOperatorPodName      = \"kstone-etcd-operator-http-test-etcd-0\"\n\tDefaultHTTPSKstoneEtcdOperatorClusterName = \"kstone-etcd-operator-https-test\"\n\tDefaultHTTPSKstoneEtcdOperatorPodName     = \"kstone-etcd-operator-https-test-etcd-0\"\n)\n\nfunc NewEtcdCluster(\n\tname string,\n\treplicas uint,\n\tclusterType kstonev1alpha2.EtcdClusterType,\n\tfeatureGate,\n\tclusterAddr,\n\tscheme string) *kstonev1alpha2.EtcdCluster {\n\tcluster := &kstonev1alpha2.EtcdCluster{\n\t\tTypeMeta: metav1.TypeMeta{APIVersion: kstonev1alpha2.SchemeGroupVersion.String()},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      name,\n\t\t\tNamespace: DefaultKstoneNamespace,\n\t\t\tLabels:    map[string]string{},\n\t\t\tAnnotations: map[string]string{\n\t\t\t\t\"autoTest\":     \"true\",\n\t\t\t\t\"featureGates\": featureGate,\n\t\t\t\t\"backup\": `\n{\n\t\"backupPolicy\": {\n\t\t\"backupIntervalInSecond\": 600,\n\t\t\"maxBackups\": 20,\n\t\t\"timeoutInSecond\": 10000\n\t},\n\t\"cos\": {\n\t\t\"cosSecret\": \"kstone-test\",\n\t\t\"path\": \"kstone-test.cos.ap-nanjing.myqcloud.com/kstone-test\"\n\t},\n\t\"storageType\": \"COS\"\n}\n`,\n\t\t\t},\n\t\t},\n\t\tSpec: kstonev1alpha2.EtcdClusterSpec{\n\t\t\tClusterType:    clusterType,\n\t\t\tSize:           replicas,\n\t\t\tDiskSize:       1,\n\t\t\tVersion:        \"3.4.13\",\n\t\t\tStorageBackend: \"v3\",\n\t\t},\n\t}\n\tswitch clusterType {\n\tcase kstonev1alpha2.EtcdClusterImported:\n\t\tcluster.ObjectMeta.Annotations[\"importedAddr\"] = clusterAddr\n\t\tcluster.ObjectMeta.Annotations[\"extClientURL\"] = fmt.Sprintf(\"127.0.0.1:2379->%s\", clusterAddr)\n\tcase kstonev1alpha2.EtcdClusterKstone:\n\t\tcluster.ObjectMeta.Annotations[\"scheme\"] = scheme\n\t}\n\treturn cluster\n}\n\nfunc NewEtcdInspection(name string, inspectionType kstonev1alpha2.KStoneFeature) *kstonev1alpha2.EtcdInspection {\n\treturn &kstonev1alpha2.EtcdInspection{\n\t\tTypeMeta: metav1.TypeMeta{APIVersion: kstonev1alpha2.SchemeGroupVersion.String()},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      name,\n\t\t\tNamespace: metav1.NamespaceDefault,\n\t\t\tLabels:    map[string]string{},\n\t\t},\n\t\tSpec: kstonev1alpha2.EtcdInspectionSpec{\n\t\t\tInspectionType: string(inspectionType),\n\t\t},\n\t}\n}\n\n// SvcFromManifest reads a .json/yaml file and returns the service in it.\nfunc SvcFromManifest(fileName string) (*v1.Service, error) {\n\tvar svc v1.Service\n\tdata, err := testfiles2.Read(fileName)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tjson, err := utilyaml.ToJSON(data)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), json, &svc); err != nil {\n\t\treturn nil, err\n\t}\n\treturn &svc, nil\n}\n\n// StatefulSetFromManifest returns a StatefulSet from a manifest stored in fileName in the Namespace indicated by ns.\nfunc StatefulSetFromManifest(fileName, ns string) (*appsv1.StatefulSet, error) {\n\tvar ss appsv1.StatefulSet\n\tdata, err := testfiles2.Read(fileName)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tjson, err := utilyaml.ToJSON(data)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), json, &ss); err != nil {\n\t\treturn nil, err\n\t}\n\tss.Namespace = ns\n\tif ss.Spec.Selector == nil {\n\t\tss.Spec.Selector = &metav1.LabelSelector{\n\t\t\tMatchLabels: ss.Spec.Template.Labels,\n\t\t}\n\t}\n\treturn &ss, nil\n}\n"
  },
  {
    "path": "test/fixtures/manifests/etcd_service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    app: etcd-test\n  name: etcd-test-headless\n  namespace: kstone\nspec:\n  clusterIP: None\n  ports:\n    - name: client\n      port: 2379\n      protocol: TCP\n      targetPort: client\n    - name: peer\n      port: 2380\n      protocol: TCP\n      targetPort: peer\n  selector:\n    app: etcd-test\n  sessionAffinity: None\n  type: ClusterIP"
  },
  {
    "path": "test/fixtures/manifests/etcd_statefulset.yaml",
    "content": "apiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n  name: etcd-test\n  labels:\n    app: etcd-test\nspec:\n  serviceName: etcd-test\n  replicas: 1\n  selector:\n    matchLabels:\n      app: etcd-test\n  template:\n    metadata:\n      name: etcd-test\n      labels:\n        app: etcd-test\n    spec:\n      containers:\n        - name: etcd\n          image: bitnami/etcd:latest\n          imagePullPolicy: Always\n          ports:\n            - containerPort: 2380\n              name: peer\n            - containerPort: 2379\n              name: client\n          resources:\n            requests:\n              cpu: 100m\n              memory: 512Mi\n          env:\n            - name: ALLOW_NONE_AUTHENTICATION\n              value: \"yes\"\n            - name: INITIAL_CLUSTER_SIZE\n              value: \"3\"\n            - name: SET_NAME\n              value: etcd"
  },
  {
    "path": "test/fixtures/manifests/etcdcluster_imported.yaml",
    "content": "apiVersion: kstone.tkestack.io/v1alpha2\nkind: EtcdCluster\nmetadata:\n  annotations:\n    certName: kstone/cls-test\n    extClientURL: >-\n      10.206.16.63:2379->10.1.2.3:12861,10.206.16.86:2379->10.1.2.3:12730,10.206.16.140:2379->10.1.2.3:12105\n    featureGates: monitor=true,consistency=true,healthy=true,request=true,backup=false\n    importedAddr: https://10.1.2.3:12846\n    kubernetes: 'true'\n  creationTimestamp: '2021-08-12T08:18:10Z'\n  generation: 152228\n  labels:\n    backup: 'false'\n    clusterType: imported\n    consistency: 'true'\n    etcdName: cls-test\n    healthy: 'true'\n    monitor: 'true'\n    request: 'true'\n  name: cls-test\n  namespace: kstone\n  resourceVersion: '31278498'\n  uid: 9e9ddd34-9c92-4aee-bc3d-68d1a223cd13\nspec:\n  affinity: {}\n  authConfig: {}\n  clusterType: imported\n  description: cls-test\n  diskSize: 50\n  diskType: ssd\n  name: cls-test\n  size: 3\n  version: ''\nstatus:\n  featureGatesStatus:\n    consistency: done\n    healthy: done\n    monitor: done\n    request: done\n  members:\n    - clientUrl: https://10.206.16.86:2379\n      endpoint: 10.206.16.86\n      extensionClientUrl: https://10.1.2.3:12730\n      memberId: '71412298143718490'\n      name: 10.206.16.86\n      port: '2379'\n      role: Follower\n      status: Running\n      version: 3.4.9\n    - clientUrl: https://10.206.16.63:2379\n      endpoint: 10.206.16.63\n      extensionClientUrl: https://10.1.2.3:12861\n      memberId: '8991984052334821064'\n      name: 10.206.16.63\n      port: '2379'\n      role: Leader\n      status: Running\n      version: 3.4.9\n    - clientUrl: https://10.206.16.140:2379\n      endpoint: 10.206.16.140\n      extensionClientUrl: https://10.1.2.3:12105\n      memberId: '17985372337265212585'\n      name: 10.206.16.140\n      port: '2379'\n      role: Follower\n      status: Running\n      version: 3.4.9\n  phase: Running\n  serviceName: https://10.1.2.3:12846"
  },
  {
    "path": "test/scripts/kstone.sh",
    "content": "#!/usr/bin/env bash\n\nset -ex\nkubectl create ns kstone\ncd charts && helm install kstone . -n kstone -f values.test.yaml --set global.kstone.tag=$VERSION\necho \"kstone component images:\"\nkubectl get deployment -n kstone -o yaml | grep image: | grep -v \"f:image:\"\n"
  },
  {
    "path": "test/scripts/minikube.sh",
    "content": "#!/usr/bin/env bash\n\n# This script is copied from github.com/aeraki-framework/aeraki\n# ----------------------------------------------------------------------------\n# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  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,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n# ----------------------------------------------------------------------------\n\nset -x\n\nK8S_VER=${K8S_VER:-'k8s-v1.20.11'}\nfunction waitMinikube() {\n  set +e\n  kubectl cluster-info\n  # This for loop waits until kubectl can access the api server that Minikube has created.\n  for _ in {1..24}; do # Timeout for 240 seconds.\n    kubectl get po --all-namespaces\n    if [ $? -ne 1 ]; then\n      break\n    fi\n    sleep 10\n  done\n  if ! kubectl get all --all-namespaces; then\n    echo \"Kubernetes failed to start\"\n    ps ax\n    netstat -an\n    docker images\n    cat /var/lib/localkube/localkube.err\n    printf '\\n\\n\\n'\n    kubectl cluster-info dump\n    exit 1\n  fi\n\n  echo \"Minikube is running\"\n\n  for _ in {1..6}; do # Timeout for 60 seconds.\n    echo \"$(sudo -E minikube ip) minikube.local\" | sudo tee -a /etc/hosts\n    ip=$(cat /etc/hosts | grep minikube.local | cut -d' ' -f1 | xargs)\n    if [ -n \"$ip\" ]; then\n      break\n    fi\n    sleep 10\n  done\n\n  ip=$(cat /etc/hosts | grep minikube.local | cut -d' ' -f1 | xargs)\n  if [ -n \"$ip\" ]; then\n    echo \"minikube.local is mapped to $ip\"\n  else\n    exit 1\n  fi\n}\n\n# startMinikubeNone starts real kubernetes minikube with none driver. This requires `sudo`.\nfunction startMinikubeNone() {\n  export MINIKUBE_WANTUPDATENOTIFICATION=false\n  export MINIKUBE_WANTREPORTERRORPROMPT=false\n  export MINIKUBE_HOME=$HOME\n  export CHANGE_MINIKUBE_NONE_USER=true\n\n  sudo -E minikube config set WantUpdateNotification false\n  sudo -E minikube config set WantReportErrorPrompt false\n  sudo -E minikube start --kubernetes-version=${K8S_VER#k8s-} --driver=none\n\n  echo $GITHUB_WORKSPACE\n  echo $E2E_KUBECONFIG_PATH\n  kubectl config view > ${GITHUB_WORKSPACE}\"/\"${E2E_KUBECONFIG_PATH}\n  cat ${GITHUB_WORKSPACE}\"/\"${E2E_KUBECONFIG_PATH}\n}\n\nfunction stopMinikube() {\n  sudo minikube stop\n}\n\ncase \"$1\" in\n  start) startMinikubeNone ;;\n  stop) stopMinikube ;;\n  wait) waitMinikube ;;\nesac\n"
  },
  {
    "path": "test/scripts/pre.sh",
    "content": "#!/usr/bin/env bash\n\n# This file is copied from github.com/aeraki-framework/aeraki\n# ----------------------------------------------------------------------------\n# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  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,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n# ----------------------------------------------------------------------------\n\nset -ex\n\nHELMVERSION=${HELMVERSION:-'helm-v3.0.0'}\nMINIKUBEVERESION=${MINIKUBEVERESION:-'minikube-v1.23.1'}\nK8SVERSION=${K8SVERSION:-'k8s-v1.20.11'}\n\ncurl -sSL https://get.helm.sh/${HELMVERSION}-linux-amd64.tar.gz | \\\n    sudo tar xz -C /usr/local/bin --strip-components=1 linux-amd64/helm\n\nsudo mkdir -p /usr/local/bin\ncurl -sSL \"https://storage.googleapis.com/minikube/releases/${MINIKUBEVERESION#minikube-}/minikube-linux-amd64\" -o /tmp/minikube\nchmod +x /tmp/minikube\nsudo mv /tmp/minikube /usr/local/bin/minikube\n\ncurl -sSL \"https://storage.googleapis.com/kubernetes-release/release/${K8SVERSION#k8s-}/bin/linux/amd64/kubectl\" -o /tmp/kubectl\nchmod +x /tmp/kubectl\nsudo mv /tmp/kubectl /usr/local/bin/kubectl\n\nsudo apt-get install -y socat conntrack\n\n"
  },
  {
    "path": "test/testfiles/testfiles.go",
    "content": "/*\nCopyright 2018 The Kubernetes Authors.\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\n// Package testfiles provides a wrapper around various optional ways\n// of retrieving additional files needed during a test run:\n// - builtin bindata\n// - filesystem access\n//\n// Because it is a is self-contained package, it can be used by\n// test/e2e/framework and test/e2e/manifest without creating\n// a circular dependency.\npackage testfiles\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n)\n\nvar filesources []FileSource\n\n// AddFileSource registers another provider for files that may be\n// needed at runtime. Should be called during initialization of a test\n// binary.\nfunc AddFileSource(filesource FileSource) {\n\tfilesources = append(filesources, filesource)\n}\n\n// FileSource implements one way of retrieving test file content.  For\n// example, one file source could read from the original source code\n// file tree, another from bindata compiled into a test executable.\ntype FileSource interface {\n\t// ReadTestFile retrieves the content of a file that gets maintained\n\t// alongside a test's source code. Files are identified by the\n\t// relative path inside the repository containing the tests, for\n\t// example \"cluster/gce/upgrade.sh\" inside kubernetes/kubernetes.\n\t//\n\t// When the file is not found, a nil slice is returned. An error is\n\t// returned for all fatal errors.\n\tReadTestFile(filePath string) ([]byte, error)\n\n\t// DescribeFiles returns a multi-line description of which\n\t// files are available via this source. It is meant to be\n\t// used as part of the error message when a file cannot be\n\t// found.\n\tDescribeFiles() string\n}\n\n// ReadOrDie tries to retrieve the desired file content from\n// one of the registered file sources. In contrast to FileSource, it\n// will either return a valid slice or abort the test by calling the fatal function,\n// i.e. the caller doesn't have to implement error checking.\nfunc ReadOrDie(filePath string) []byte {\n\tdata, err := Read(filePath)\n\tif err != nil {\n\t\treturn nil\n\t}\n\treturn data\n}\n\n// Read tries to retrieve the desired file content from\n// one of the registered file sources.\nfunc Read(filePath string) ([]byte, error) {\n\tif len(filesources) == 0 {\n\t\treturn nil, fmt.Errorf(\"no file sources registered (yet?), cannot retrieve test file %s\", filePath)\n\t}\n\tfor _, filesource := range filesources {\n\t\tdata, err := filesource.ReadTestFile(filePath)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"fatal error retrieving test file %s: %s\", filePath, err)\n\t\t}\n\t\tif data != nil {\n\t\t\treturn data, nil\n\t\t}\n\t}\n\t// Here we try to generate an error that points test authors\n\t// or users in the right direction for resolving the problem.\n\terror := fmt.Sprintf(\"Test file %q was not found.\\n\", filePath)\n\tfor _, filesource := range filesources {\n\t\terror += filesource.DescribeFiles()\n\t\terror += \"\\n\"\n\t}\n\treturn nil, errors.New(error)\n}\n\n// Exists checks whether a file could be read. Unexpected errors\n// are handled by calling the fail function, which then should\n// abort the current test.\nfunc Exists(filePath string) bool {\n\tfor _, filesource := range filesources {\n\t\tdata, err := filesource.ReadTestFile(filePath)\n\t\tif err != nil {\n\t\t\treturn false\n\t\t}\n\t\tif data != nil {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// RootFileSource looks for files relative to a root directory.\ntype RootFileSource struct {\n\tRoot string\n}\n\n// ReadTestFile looks for the file relative to the configured\n// root directory. If the path is already absolute, for example\n// in a test that has its own method of determining where\n// files are, then the path will be used directly.\nfunc (r RootFileSource) ReadTestFile(filePath string) ([]byte, error) {\n\tvar fullPath string\n\tif path.IsAbs(filePath) {\n\t\tfullPath = filePath\n\t} else {\n\t\tfullPath = filepath.Join(r.Root, filePath)\n\t}\n\tdata, err := ioutil.ReadFile(fullPath)\n\tif os.IsNotExist(err) {\n\t\t// Not an error (yet), some other provider may have the file.\n\t\treturn nil, nil\n\t}\n\treturn data, err\n}\n\n// DescribeFiles explains that it looks for files inside a certain\n// root directory.\nfunc (r RootFileSource) DescribeFiles() string {\n\tdescription := fmt.Sprintf(\"Test files are expected in %q\", r.Root)\n\tif !path.IsAbs(r.Root) {\n\t\t// The default in test_context.go is the relative path\n\t\t// ../../, which doesn't really help locating the\n\t\t// actual location. Therefore we add also the absolute\n\t\t// path if necessary.\n\t\tabs, err := filepath.Abs(r.Root)\n\t\tif err == nil {\n\t\t\tdescription += fmt.Sprintf(\" = %q\", abs)\n\t\t}\n\t}\n\tdescription += \".\"\n\treturn description\n}\n\n// BindataFileSource handles files stored in a package generated with bindata.\ntype BindataFileSource struct {\n\tAsset      func(string) ([]byte, error)\n\tAssetNames func() []string\n}\n\n// ReadTestFile looks for an asset with the given path.\nfunc (b BindataFileSource) ReadTestFile(filePath string) ([]byte, error) {\n\tfileBytes, err := b.Asset(filePath)\n\tif err != nil {\n\t\t// It would be nice to have a better way to detect\n\t\t// \"not found\" errors :-/\n\t\tif strings.HasSuffix(err.Error(), \"not found\") {\n\t\t\treturn nil, nil\n\t\t}\n\t}\n\treturn fileBytes, nil\n}\n\n// DescribeFiles explains about gobindata and then lists all available files.\nfunc (b BindataFileSource) DescribeFiles() string {\n\tvar lines []string\n\tlines = append(\n\t\tlines,\n\t\t\"The following files are built into the test executable via gobindata. \"+\n\t\t\t\"For questions on maintaining gobindata, contact the sig-testing group.\",\n\t)\n\tassets := b.AssetNames()\n\tsort.Strings(assets)\n\tlines = append(lines, assets...)\n\tdescription := strings.Join(lines, \"\\n   \")\n\treturn description\n}\n"
  },
  {
    "path": "third_party/etcd-operator/.github/PULL_REQUEST_TEMPLATE.md",
    "content": "\nPlease read https://github.com/coreos/etcd-operator/blob/master/CONTRIBUTING.md#contribution-flow\n"
  },
  {
    "path": "third_party/etcd-operator/.gitignore",
    "content": "# Compiled Object files, Static and Dynamic libs (Shared Objects)\n*.o\n*.a\n*.so\n\n# Folders\n_obj\n_test\n_output\n.kube\n.vscode\n.idea\n\n# Architecture specific extensions/prefixes\n*.[568vq]\n[568vq].out\n\n*.cgo1.go\n*.cgo2.c\n_cgo_defun.c\n_cgo_gotypes.go\n_cgo_export.*\n\n_testmain.go\n\n*.exe\n*.test\n*.prof\n\n# vendor\nvendor/\n"
  },
  {
    "path": "third_party/etcd-operator/CHANGELOG.md",
    "content": "## [Unreleased]\n\n### Added\n\n- Added `spec.Pod.ClusterDomain` to explicitly set the cluster domain used for the etcd member URLs. [#2082](https://github.com/coreos/etcd-operator/pull/2082)\n\n### Changed\n\n### Removed\n\n### Fixed\n\n- Don't expose unready nodes via client service. [#2063](https://github.com/coreos/etcd-operator/pull/2063)\n- Azure blob storage: use correct list prefix [#2071](https://github.com/coreos/etcd-operator/pull/2071)\n\n### Deprecated\n\n### Security\n\n## [Release 0.9.4]\n\n### Added\n\n- Added `spec.BackupSource.S3.ForcePathStyle` to `EtcdBackup` to force path style s3 uploads. [#2036](https://github.com/coreos/etcd-operator/pull/2036)\n- Added `spec.RestoreSource.S3.ForcePathStyle` to `EtcdRestore` to force path style s3 downloads. [#2036](https://github.com/coreos/etcd-operator/pull/2036)\n\n### Changed\n\n- Update Go version to 1.11.5\n- Update k8s to 1.12.6\n- EtcdBackup: Support periodic backups. This change added 3 new fields to EtcdBackup schema, 2 variables in spec, 1 variables in status.\n  - in spec.backupPolicy\n    - maxBackup: maximum number of backups to keep.\n    - backupIntervalInSecond: how often to perform backup operation.\n  - in status\n    - LastSuccessDate: last time to succeed in taking backup\n\n### Fixed\n\n- Fixed a bug where `same CR names` in different namespaces with cluster-wide operator were not working as expected [#2026](https://github.com/coreos/etcd-operator/pull/2026)\n- Fixed a bug where cluster names could exceed 63 octets the maximum defined by [RFC 1035 section 2.3.4](https://tools.ietf.org/html/rfc1035) resulting in hanging pods [2027](https://github.com/coreos/etcd-operator/pull/2027).\n\n## [Release 0.9.3]\n\n### Added\n\n- Added `spec.pod.DNSTimeoutInSecond` to `EtcdCluster` that allows setting a maximum allowed time for the init container of the etcd pod to reverse DNS lookup its IP given the hostname.\n\n### Changed\n\n- Update Go version to 1.11.2\n- Update k8s to 1.11.4\n- k8s codegen updates are longer performed via container. Go dependencies are now vendored\n  and updates are performed with shell script locally.\n\n### Fixed\n\n- Fixed leaking http connections while verifying backup snapshots. [#1976](https://github.com/coreos/etcd-operator/pull/1976)\n\n## [Release 0.9.2]\n\n### Added\n\n- Added the field `spec.pod.securityContext` to `EtcdCluster` that allows setting a specific [PodSecurityContext](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) for the etcd pods. [#1949](https://github.com/coreos/etcd-operator/pull/1949)\n\n### Changed\n\n- Update Go version to 1.10\n- Build `gcr.io/coreos-k8s-scale-testing/etcd-operator-builder:0.4.1-2` container\n  with Go 1.10 and dep 0.4.1\n- etcd pod containers no longer run with a non-root security context by default. This setting can be configured per cluster via the PodPolicy.\n\n## [Release 0.9.1]\n\n### Added\n\n- Added optional flag `--cluster-wide` to etcd-operator to allow it to manage etcd clusters across all namespaces. [#1777](https://github.com/coreos/etcd-operator/pull/1777)\n- Added support for annotation `etcd.database.coreos.com/scope: clusterwide` in `EtcdCluster` to allow it to be managed by a cluster wide operator. [#1777](https://github.com/coreos/etcd-operator/pull/1777)\n- Added the field `spec.pod.busyboxImage` to the `PodPolicy` of the `EtcdCluster` to allow overriding the default busybox image used for the etcd pod's init container. [#1928](https://github.com/coreos/etcd-operator/pull/1928)\n\n### Fixed\n\n- Fixed a bug where the informer watch stream would timeout after 30s of not receiving an event. [#1936](https://github.com/coreos/etcd-operator/pull/1936)\n\n## [Release 0.9.0]\n\nSame as v0.8.4. The version is bumping to 0.9.0 due to adding a new ABS backup API into etcd-backup-operator.\n\n## [Release 0.8.4]\n\n### Added\n\n- Added ABS support for backup and restore\n- Added tag to initContainer to enable offline deploys\n- Enabled configurable backup timeout in backup operator\n\n### Changed\n\n- Set 30s default request timeout for kube client\n- Change check-dns init container image to busybox:1.28.0-glibc to fix nslookup failure in some environment.\n\n### Removed\n\n- Removed self-hosted code\n\n## [Release 0.8.3]\n\n### Added\n\n- Added the option to use PersistentVolume as non-stable storage for etcd pods. This feature is still alpha and subject to change in future releases [#1861](https://github.com/coreos/etcd-operator/pull/1861)\n\n### Changed\n\n- Changed etcd pod member names to be unique by having a random suffix instead of a sequence number. This change is backward compatible and should not affect operator upgrade.\n    Previously the etcd pod names would look like:\n    ```\n    NAME                            READY     STATUS    RESTARTS   AGE\n    example-etcd-cluster-0000       1/1       Running   0          1m\n    example-etcd-cluster-0001       1/1       Running   0          1m\n    example-etcd-cluster-0002       1/1       Running   0          1m\n    ```\n    After this change:\n    ```\n    NAME                                  READY     STATUS    RESTARTS   AGE\n    example-etcd-cluster-2885zjw9he       1/1       Running   0          1m\n    example-etcd-cluster-gghrmbeid4       1/1       Running   0          1m\n    example-etcd-cluster-w5q9sn37fd       1/1       Running   0          1m\n    ```\n\n### Fixed\n\n- Fixed a bug where the restore operator would fail to restore the seed member because recreating an etcd pod with the same name as a recently deleted one would conflict as the older pod and its resources, like the DNS name, might still not be deleted. [#1825](https://github.com/coreos/etcd-operator/issues/1825)\n\n\n## [Release 0.8.2]\n\n### Added\n\n- Add support for backup and restore from custom S3 endpoint.\n\n### Changed\n\n- All etcd pod containers now run as non-root.\n\n\n## [Release 0.8.1]\n\n### Changed\n\n- etcd-restore-operator will create a service for itself as the backup storage proxy. Delete the service in deployment yaml.\n\n### Fixed\n\n- Fix etcd-restore-operator wouldn't report error and keep looping if EtcdRestore name is different than EtcdCluster name.\n\n\n## [Release 0.8.0]\n\n**Important Changes**\n\nBoth etcd backup operator and etcd restore operator have changed their CR definition.\nPlease follow the latest backup/restore CR definition for future backup and restore.\n\n### Added\n\n- Add readiness probe to etcd pod. The readiness state will be reflected on `status.members.ready/unready`.\n- TLS etcd cluster support in backup/restore-operator.\n- Add spec validation in restore operator.\n- Add BackupStorageType to EtcdRestore.RestoreSpec to indicate type of the backup storage which is used as RestoreSource and validation of BackupStorageType in restore operator.\n- Add EtcdClusterRef to EtcdRestore.RestoreSpec to reference an EtcdCluster resource whose metadata and spec will be used to create the new restored EtcdCluster CR.\n- Add create-crd flag to etcd backup operator allowing user to disable automatic backup CRD creation.\n- Add create-crd flag to etcd restore operator allowing user to disable automatic restore CRD creation.\n- Add EtcdVersion and EtcdRevision to EtcdBackup.BackupStatus.\n- BackupStatus: Add detailed error when backup fails.\n\n### Changed\n\n- Rename BackupCRStatus to BackupStatus.\n- EtcdBackup: BackupSpec passes in S3BackupSource.Path as the S3 path to save the backup.\n- EtcdBackup: BackupSpec spec uses etcd endpoints to retrieve snapshot.\n- Change default etcd version to `3.2.13`.\n\n### Removed\n\n- EtcdBackup: BackupSpec removed ClusterName field in favor of etcd endpoints.\n- EtcdCluster: ClusterSpec removed deprecated BaseImage field.\n\n\n## [Release 0.7.2]\n\n> Note: This is a bug fix release.\n\nWhen we bump the etcd version to 3.2, the images were only available on gcr.io . But now it is added on quay.io .\nWe'd better use quay.io and keep it compatible to work for 3.1 versions of etcd.\n\n## [Release 0.7.1]\n\n### Added\n\n- TLS etcd cluster feature for EtcdBackup\n- Log collector program for collecting logs in e2e test.\n- ClusterSpec: In PodPolicy, add generic `Affinity` field to substitute bool `AntiAffinity` field.\n- ClusterSpec: Add `Repository` field to substitute `BaseImage` field.\n\n### Changed\n\n- Default base image is changed to `gcr.io/etcd-development/etcd`, default etcd version is `3.2.11`.\n- Migrate dependency management tooling from glide to dep.\n- Containerize e2e test in a pod instead of running on raw jenkin slave.\n\n### Removed\n\n- ClusterSpec: Remove `PodPolicy.AutomountServiceAccountToken` field.\n  No etcd pod will have service account token mounted.\n\n### Fixed\n\n- Ignore Terminating pods when polling etcd pods.\n\n### Deprecated\n\n- ClusterSpec: `BaseImage` is deprecated. It will be automatically converted to `Repository` in this release.\n- ClusterSpec: In PodPolicy, `AntiAffinity` is deprecated. It will be automatically converted to `Affinity.PodAntiAffinity`\n  terms with label selector on given cluster name and topology key on node in this release.\n\n### Security\n\n- All operator images by default uses user `etcd-operator` instead of root.\n\n\n## [Release 0.7.0]\n\nExisting backup and restore features in EtcdCluster API won’t be supported after 0.7.0 release.\nSee [Decoupling Backup and Restore Logic from Etcd Operator](https://github.com/coreos/etcd-operator/issues/1626) for more detail.\n\nIf applicable then see the [upgrade guide](./doc/user/upgrade/upgrade_guide.md) on how to upgrade from `v0.6.1` to `v0.7.0` .\n\n### Added\n\n- Add `ServiceName` and `ClientPort` into ClusterStatus.\n- Add etcd backup operator for backing up an etcd cluster.\n- Add etcd restore operator for restoring an etcd cluster.\n\n### Removed\n\n- Remove `pv-provisioner` flag from etcd operator.\n- Remove etcd cluster Backup feature from etcd operator.\n- Remove etcd cluster Restore from etcd operator.\n\n\n## [Release 0.6.1]\n\nThe operator will no longer create a storage class specified by `--pv-provisioner` by default. If applicable then see the [upgrade guide](./doc/user/upgrade/upgrade_guide.md) on how to upgrade from `v0.6.0` to `v0.6.1` .\n\n### Added\n\n- backup binary supports serving backup defined by backupSpec. In addition, when backupSpec\nis specified, backup binary changes to serve http backup requests only mode.\n- Add operator flag `--create-crd`. By default it is `true` and operator will create EtcdCluster CRD.\n  It can be set to `false` and operator won't create EtcdCluster CRD.\n- Add operator flag `--create-storage-class`. By default it is `false` and operator won't create default storage class.\n  It can be set to `true` and operator will create default storage class.\n\n### Changed\n\n- An EtcdCluster CR with an invalid spec will not be marked as failed. Any changes that result in an invalid spec will be ignored and logged by the operator.\n\n### Fixed\n\n- Fix the problem that operator might keep failing on version conflict updating CR status.\n\n### Deprecated\n\n- The operator flag `--pv-provisioner` is depercated. We recommend to use per cluster storageClass.\n\n\n## [Release 0.6.0]\n\n**BREAKING CHANGE**: operator level S3 backup is removed. See [upgrade](./doc/user/upgrade/upgrade_guide.md) on how to upgrade from 0.5.x to 0.6.0.\n\n### Added\n\n- Add cluster events into EtcdCluster custom resource. See `doc/user/conditions_and_events.md` .\n\n### Changed\n\n- Redefine status.conditions. See `doc/user/conditions_and_events.md` .\n\n### Removed\n\n- Remove operator level S3 flag.\n- Remove analytics flag. Disable Google analytics.\n\n\n## [Release 0.5.2]\n\n### Added\n\n- Expose `/metrics` endpoint at port 8080\n- Add cluster S3 spec `prefix` feature. Let user choose a prefix under the bucket.\n- Add `automountServiceAccountToken` to pod policy. Let users disable automounting of the Kubernetes access token into etcd-operator controlled pods.\n- Cluster backups can now be saved using Azure Blob Storage (ABS).\n\n### Deprecated\n\n- Deprecate operator S3 flag. Add warning note for using it in this release. The flag will be removed in 0.6.0 release.\n\n\n## [Release 0.5.1]\n\nUpgrade notice for TLS cluster users:\nIf you are using TLS-enabled etcd cluster, the SAN domain has been changed. See [TLS docs](./doc/user/cluster_tls.md).\nBefore upgrading operator, you need to rotate certs on each secrets to allow both the old and new domains.\nThen restart each etcd pod -- the simplest way is to \"upgrade\" cluster version.\nFinally, it is safe to upgrade operator. It's highly recommended to save a backup before upgrade.\n\n### Added\n\n- A new `StorageClass` spec field, allowing more granular control over how etcd clusters are backed up to PVs.\n\n### Changed\n\n- Default timeout for snapshots done by backup sidecar increased from 5 seconds to 1 minute\n\n### Fixed\n\n- Fix periodFullGC only executed once problem.\n- [GH-1021] Use the cluster domain provided by kubelet instead of hardcoded `.cluster.local` .\n\n\n## [Release 0.5.0]\n\n**BREAKING CHANGE**: The cluster object will now be defined via a [Custom Resource Definition(CRD)](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions/) instead of a [Third Party Resource(TPR)](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-third-party-resource/). See the `Changed` section below for details.\n\n### Changed\n\n- With k8s 1.7 and onwards TPRs have been deprecated and are replaced with CRD. See the k8s 1.7 [blogpost](http://blog.kubernetes.io/2017/06/kubernetes-1.7-security-hardening-stateful-application-extensibility-updates.html) or [release notes](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG.md#major-themes) for more details. For this release a live migration of the cluster spec from TPR to CRD is not supported. To preserve the cluster state during the upgrade you will need to create a backup of the cluster and recreate the cluster from the backup after upgrading the operator. See the [upgrade guide](https://github.com/coreos/etcd-operator/blob/master/doc/user/upgrade/upgrade_guide.md) for more detailed steps on how to do that.\n\n- Changes in the cluster object's type metadata:\n  - The `apiVersion` field has been changed from `etcd.coreos.com/v1beta1` to `etcd.database.coreos.com/v1beta2`\n  - The `kind` field has been changed from `Cluster` to `EtcdCluster`\n\n\n## [Release 0.4.2]\n\n### Added\n\n- [GH-1232](https://github.com/coreos/etcd-operator/pull/1232) the operator can now log critical actions like pod creation/deletion to a user specified path via the optional flag `debug-logfile-path`. The logs will only be generated if the cluster is self hosted and the flag is set. This can be used in conjunction with a persistent volume to persist the critical actions to disk for later inspection.\n\n### Changed\n\n- enable alpha feature \"tolerate unready endpoints\" on etcd client and peer service\n\n### Fixed\n\n- Fix append-hosts init-container not run on some restart cases.\n\n\n## [Release 0.4.1]\n\nThis is a bug-fix release. We have done a lot of testing against k8s 1.7\nand making it stable on 1.7 .\n\n### Added\n\n- New self-hosted field `SkipBootMemberRemoval` allows users to skip the\n  auto-deletion of the boot etcd member.\n\n### Fixed\n\n- Make sure etcd pod's FQDN is resolvable before running etcd commands .\n\n\n## [Release 0.4.0]\n\n**BREAKING CHANGE**: Re-naming of TLS spec and TLS secrets' fields.\n\nTLS spec:\n- member's `clientSecret` is changed to `serverSecret`\n\nTLS secrets:\n- member's `peerSecret`'s fields change:\n  - peer-crt.pem -> peer.crt\n  - peer-key.pem -> peer.key\n  - peer-ca-crt.pem -> peer-ca.crt\n- member's `clientSecret` is changed to `serverSecret`, its fields change:\n  - client-crt.pem -> server.crt\n  - client-key.pem -> server.key\n  - client-ca-crt.pem -> server-ca.crt\n- `operatorSecret`'s fields change:\n  - etcd-crt.pem -> etcd-client.crt\n  - etcd-key.pem -> etcd-client.key\n  - etcd-ca-crt.pem -> etcd-client-ca.crt\n\n\n**BREAKING CHANGE**: Backup spec: `CleanupBackupsOnClusterDelete` field is renamed to `AutoDelete`.\n\nPrevious spec like this one\n\n```yaml\nspec:\n  backup:\n    storageType: \"PersistentVolume\"\n    ...\n    cleanupBackupsOnClusterDelete: true\n```\n\nshould be changed to\n\n```yaml\nspec:\n  backup:\n    storageType: \"PersistentVolume\"\n    ...\n    autoDelete: true\n```\n\n\n## [Release 0.3.3]\n\n### Added\n\n- Adds ability for users to specify base image for etcd pods in a cluster.\n  Default base image is `quay.io/coreos/etcd-operator`.\n\n### Fixed\n\n- [GH-1138] Fixed operator stucks in managing selfhosted cluster when there are not enough nodes to start new etcd member.\n- [GH-1196] Fixed etcd operator could not start S3 backup sidecar if given non-root user.\n\n\n## [Release 0.3.2]\n\nBug fix release to fix self-hosted etcd issue [GH-1171] .\n\n## [Release 0.3.1]\n\n\n**Notes for self-hosted etcd**:\nThe newly introduced TLS feature for self hosted etcd is a breaking change.\nExisting self hosted etcd cluster MUST be recreated for updating to this release.\n\n### Added\n\n- Self-hosted etcd: if `etcd-hosts.checkpoint` file exists under `${datadir}/`,\n  etcd pod will restore the hosts mapping from it before etcd bootstraps.\n- Add static TLS support for self-hosted etcd mode.\n- The operator will now post Kubernetes [events](https://kubernetes.io/docs/resources-reference/v1.6/#event-v1-core). To allow this the necessary RBAC rule for the resource `events` must be added to the clusterrole. See the [rbac guide](https://github.com/coreos/etcd-operator/blob/master/doc/user/rbac.md#create-clusterrole) to see how to set up RBAC rules for the operator. If the rbac rule for 'events' is not present then the operator will continue to function normally but will also print out an error message on the failure to post an event.\n- Add revision field in backup status.\n- Support getting a specific backup with version and revision from the backup service.\n\n### Changed\n\n- Self-hosted etcd: use FQDN for client/peer URL.\n- Updated RBAC rules for resources `thirdpartyresources` and `storageclasses` to all verbs `*` . We loose granularity early so that we have more flexibility to use other methods (e.g. Get) later.\n\n### Removed\n\n- Update default etcd version to 3.1.8\n\n### Fixed\n\n- [GH-1108] selfHosted: fix backup unable to talk to etcd pods\n\n### Deprecated\n\n### Security\n\n\n## [Release 0.3.0]\n\n### Upgrade Notice\n\nCheck https://github.com/coreos/etcd-operator/blob/master/doc/user/upgrade/upgrade_guide.md#v02x-to-v03x\n\n### Added\n\n- Added support for backup policy to be dynamically added, updated\n- Added per cluster policy support for S3.\n\n### Changed\n\n- Backup sidecar deployment created with `Recreate` strategy.\n- Spec.Backup.MaxBackups meaning change: 0 means unlimited backups; < 0 will be rejected.\n\n### Removed\n\n### Fixed\n\n- [GH-1068] Backup sidecar deployment stuck at upgrading\n\n### Deprecated\n\n### Security\n\n\n## [Release 0.2.6]\n\n### Upgrade Notice\n\n- Once operator is upgraded, all backup-enabled cluster will go through an upgrade process that\n  deletes backup sidecar's ReplicaSet and creates new Deployment for sidecar.\n  If upgrading failed for any reason, cluster TPR's `status.phase` will be FAILED.\n  Recreate of the cluster TPR is needed on failure case.\n\n### Added\n\n- PodPolicy provides `EtcdEnv` option to add custom env to the etcd process.\n- PodPolicy provides `Labels` option to add custom labels to the etcd pod.\n- TLS feature: user can now create TLS-secured cluster via operator.\n  See [TLS guide](https://github.com/coreos/etcd-operator/blob/master/doc/user/cluster_tls.md).\n\n### Changed\n\n- Self-hosted etcd pod's anti-affinity label selector is changed to select `{\"app\": \"etcd\"}`.\n  That is, no two etcd pods should sit on the same node, even if they belongs to different clusters.\n- Using Deployment to manage backup sidecar instead of ReplicaSet.\n- S3 backup path is changed to `${BUCKET_NAME}/v1/${NAMESPACE}/${CLUSTER_NAME}/`.\n\n### Removed\n\n### Fixed\n\n- Fixed an issue where liveness probes failed when authentication was enabled. [#1957](https://github.com/coreos/etcd-operator/issues/1957)\n\n### Deprecated\n\n### Security\n\n\n## [Release 0.2.5]\n\n### Added\n\n- Add \"none\" PV provisioner option. If operator flag \"pv-provisioner\" is set to \"none\",\n  operator won’t create any storage class and users couldn’t make use of operator’s PV backup feature.\n- Add headless service `${clusterName}` which selects etcd pods of given cluster.\n- Pod Tolerations.\n\n### Changed\n\n- TLSSpec json tag changed as `omitempty`\n- Time related fields in spec, i.e. TransitionTime and CreationTime, is changed to type `string`.\n  This should be backward compatible and no effect on operator upgrade.\n- Update default etcd version to 3.1.4\n- Self-hosted etcd pod is started with \"--metrics extensive\" flag.\n  This is only available in etcd 3.1+.\n- Change client LB service name to `${clusterName}-client`.\n- Add hostname and subdomain to etcd pods, which makes them have A records formatted in `${memberName}.${clusterName}.${namespace}.svc.cluster.local` .\n  For more info, see https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ .\n  We also change PeerURL of etcd members to use such hostnames.\n\n### Removed\n\n- Individual etcd member's services were removed. Use hostname and subdomain of etcd pod instead.\n\n### Fixed\n\n- [GH-910] Operator keeps updating status even if there is no change.\n\n### Deprecated\n\n### Security\n\n\n## [Release 0.2.4]\n\n### Added\n\n### Changed\n\n### Removed\n\n### Fixed\n\n- [GH-900] Fix looping of reconcile skip due to unready members\n\n### Deprecated\n\n### Security\n\n\n## [Release 0.2.3]\n\n### Added\n\n### Changed\n\n### Removed\n\n### Fixed\n\n- [GH-890] Fix a race that when majority of members went down cluster couldn't recover\n- Fix self-hosted cluster reboot case\n\n### Deprecated\n\n### Security\n\n\n## [Release 0.2.2]\n\n### Added\n\n- Backup creation time is added in backup status.\n- Total size of backups time is added in backup service status.\n- Cluster members that are ready and unready to serve requests are tracked via the ClusterStatus fields `Members.Ready` and `Members.Unready`\n\n### Changed\n\n- PodPolicy `resourceRequirements` field is renamed to `resources`\n- Default etcd version is changed to `3.1.2`\n- Self-hosted etcd pod uses hostPath with path `/var/etcd/$ns-$member`\n\n### Removed\n\n### Fixed\n\n- [GH-851] Fixed a race that caused nil pointer access panic\n- [GH-823] Fixed backup service status not shown in TPR status\n\n### Deprecated\n\n### Security\n\n\n## [Release 0.2.1]\n### Added\n\n- Experimental client for interacting with backup service\n- The operator panics itself when it gets stuck unexpectedly. It relies on Kubernetes to\nget restarted.\n- Add resource requirements field in `Spec.Pod` . Users can specify resource requirements for the\netcd container with this new field.\n- Add status endpoint to backup sidecar service.\n- Service account of the etcd operator pod is passed to backup pod.\n- Add backup service status into cluster status.\n\n### Changed\n\n- Example deployments pin to the released version of the operator image\n- Downward API of pod's namespace and name is required to start etcd operator pod.\n  See `example/deployment.yaml` .\n\n### Removed\n\n- Drop etcd operator command line flags: \"masterHost\", \"cert-file\", \"key-file\", \"ca-file\".\n\n### Fixed\n\n### Deprecated\n\n### Security\n"
  },
  {
    "path": "third_party/etcd-operator/CONTRIBUTING.md",
    "content": "# How to Contribute\n\nCoreOS projects are [Apache 2.0 licensed](LICENSE) and accept contributions via\nGitHub pull requests.  This document outlines some of the conventions on\ndevelopment workflow, commit message formatting, contact points and other\nresources to make it easier to get your contribution accepted.\n\n# Certificate of Origin\n\nBy contributing to this project you agree to the Developer Certificate of\nOrigin (DCO). This document was created by the Linux Kernel community and is a\nsimple statement that you, as a contributor, have the legal right to make the\ncontribution. See the [DCO](DCO) file for details.\n\n# Email and Chat\n\nThe project currently uses the general CoreOS email list and IRC channel:\n- Email: [coreos-dev](https://groups.google.com/forum/#!forum/coreos-dev)\n- IRC: #[coreos](irc://irc.freenode.org:6667/#coreos) IRC channel on freenode.org\n\nPlease avoid emailing maintainers found in the MAINTAINERS file directly. They\nare very busy and read the mailing lists.\n\n## Getting Started\n\n- Fork the repository on GitHub\n- Read the [README](README.md) for build and test instructions\n- Play with the project, submit bugs, submit patches!\n\n## Contribution Flow\n\nThis is a rough outline of what a contributor's workflow looks like:\n\n- Create a topic branch from where you want to base your work (usually master).\n- Make commits of logical units.\n- Make sure your commit messages are in the proper format (see below).\n- Push your changes to a topic branch in your fork of the repository.\n- Make sure the tests pass, and add any new tests as appropriate.\n- Submit a pull request to the original repository.\n\nThanks for your contributions!\n\n### Coding Style\n\nCoreOS projects written in Go follow a set of style guidelines that we've documented \n[here](https://github.com/coreos/docs/tree/master/golang). Please follow them when \nworking on your contributions.\n\n### Format of the Commit Message\n\nWe follow a rough convention for commit messages that is designed to answer two\nquestions: what changed and why. The subject line should feature the what and\nthe body of the commit should describe the why.\n\n```\nscripts: add the test-cluster command\n\nthis uses tmux to setup a test cluster that you can easily kill and\nstart for debugging.\n\nFixes #38\n```\n\nThe format can be described more formally as follows:\n\n```\n<subsystem>: <what changed>\n<BLANK LINE>\n<why this change was made>\n<BLANK LINE>\n<footer>\n```\n\nThe first line is the subject and should be no longer than 70 characters, the\nsecond line is always blank, and other lines should be wrapped at 80 characters.\nThis allows the message to be easier to read on GitHub as well as in various\ngit tools.\n"
  },
  {
    "path": "third_party/etcd-operator/DCO",
    "content": "Developer Certificate of Origin\nVersion 1.1\n\nCopyright (C) 2004, 2006 The Linux Foundation and its contributors.\n660 York Street, Suite 102,\nSan Francisco, CA 94110 USA\n\nEveryone is permitted to copy and distribute verbatim copies of this\nlicense document, but changing it is not allowed.\n\n\nDeveloper's Certificate of Origin 1.1\n\nBy making a contribution to this project, I certify that:\n\n(a) The contribution was created in whole or in part by me and I\n    have the right to submit it under the open source license\n    indicated in the file; or\n\n(b) The contribution is based upon previous work that, to the best\n    of my knowledge, is covered under an appropriate open source\n    license and I have the right under that license to submit that\n    work with modifications, whether created in whole or in part\n    by me, under the same open source license (unless I am\n    permitted to submit under a different license), as indicated\n    in the file; or\n\n(c) The contribution was provided directly to me by some other\n    person who certified (a), (b) or (c) and I have not modified\n    it.\n\n(d) I understand and agree that this project and the contribution\n    are public and that a record of the contribution (including all\n    personal information I submit with it, including my sign-off) is\n    maintained indefinitely and may be redistributed consistent with\n    this project or the open source license(s) involved.\n"
  },
  {
    "path": "third_party/etcd-operator/Dockerfile",
    "content": "FROM golang:1.12 as builder\nMAINTAINER simotang \"simotang@tencent.com\"\n\nENV TZ=Asia/Shanghai\nRUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone\n\nAdd . /go/src/github.com/kstone/etcd-operator\nWORKDIR /go/src/github.com/coreos/etcd-operator\n\nRUN make\n\n\nFROM alpine:3.6\n\nCOPY --from=builder /usr/share/zoneinfo/ /usr/share/zoneinfo/\n\nENV TZ=Asia/Shanghai\nRUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone\n\nRUN apk add --no-cache ca-certificates\n\nCOPY --from=builder /go/src/github.com/coreos/etcd-operator/_output/bin/ /usr/local/bin/\n\nRUN adduser -D etcd-operator\nUSER etcd-operator"
  },
  {
    "path": "third_party/etcd-operator/Gopkg.toml",
    "content": "# Force dep to vendor the code generators, which aren't imported just used at dev time.\nrequired = [\n  \"k8s.io/code-generator/cmd/defaulter-gen\",\n  \"k8s.io/code-generator/cmd/deepcopy-gen\",\n  \"k8s.io/code-generator/cmd/conversion-gen\",\n  \"k8s.io/code-generator/cmd/client-gen\",\n  \"k8s.io/code-generator/cmd/lister-gen\",\n  \"k8s.io/code-generator/cmd/informer-gen\",\n  \"k8s.io/code-generator/cmd/openapi-gen\",\n  \"k8s.io/gengo/args\",\n]\n\n[[override]]\n  name = \"k8s.io/code-generator\"\n  version = \"kubernetes-1.12.6\"\n\n[[override]]\n  name = \"k8s.io/api\"\n  version = \"kubernetes-1.12.6\"\n\n[[override]]\n  name = \"k8s.io/apiextensions-apiserver\"\n  version = \"kubernetes-1.12.6\"\n\n[[override]]\n  name = \"k8s.io/apimachinery\"\n  version = \"kubernetes-1.12.6\"\n\n[[override]]\n  name = \"k8s.io/client-go\"\n  version = \"kubernetes-1.12.6\"\n\n[[constraint]]\n  name = \"github.com/coreos/etcd\"\n  version = \"=3.2.13\"\n\n[[override]]\n  name = \"google.golang.org/grpc\"\n  version = \"=1.14.0\"\n\n[[constraint]]\n  name = \"github.com/aws/aws-sdk-go\"\n  version = \"=1.13.8\"\n\n[[constraint]]\n  name = \"github.com/pborman/uuid\"\n  version = \"=1.1\"\n\n[[constraint]]\n  name = \"github.com/pkg/errors\"\n  version = \"=0.8.0\"\n\n[[constraint]]\n  name = \"github.com/prometheus/client_golang\"\n  version = \"=0.8.0\"\n\n[[constraint]]\n  name = \"github.com/sirupsen/logrus\"\n  version = \"=1.0.4\"\n\n[[constraint]]\n  name = \"github.com/Azure/azure-sdk-for-go\"\n  version = \"=11.3.0-beta\"\n\n[[constraint]]\n  name = \"cloud.google.com/go\"\n  version = \"0.19.0\"\n\n[prune]\n  go-tests = true\n  non-go = true\n\n  [[prune.project]]\n    name = \"k8s.io/code-generator\"\n    non-go = false\n\n[[constraint]]\n  name = \"github.com/aliyun/aliyun-oss-go-sdk\"\n  version = \"=1.9.4\"\n\n[[constraint]]\n  name = \"github.com/tencentyun/cos-go-sdk-v5\"\n  version = \"=0.7.31\"\n"
  },
  {
    "path": "third_party/etcd-operator/LICENSE",
    "content": "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 {yyyy} {name of copyright owner}\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"
  },
  {
    "path": "third_party/etcd-operator/MAINTAINERS",
    "content": "Hongchao Deng <hongchao.deng@coreos.com> (@hongchaodeng)\nXiang Li <xiang.li@coreos.com> (@xiang90)\nHaseeb Tariq <haseeb.tariq@coreos.com> (@hasbro17)\nFanmin Shi <fanmin.shi@coreos.com> (@fanminshi)\n\nJingtao Ren <jiren@microsoft.com> (@rjtsdl): Azure ABS backup and restore\n"
  },
  {
    "path": "third_party/etcd-operator/Makefile",
    "content": "DEFAULT_GOAL := build-all\nbuild-all:\n\tcurl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh\n\t./hack/update_vendor.sh\n\t./hack/build/operator/build\n\t./hack/build/backup-operator/build\n\t./hack/build/restore-operator/build \n\ndev:\n\t@docker build --network=host -t ccr.ccs.tencentyun.com/ccs-dev/etcd-operator:dev .\n\t@docker push ccr.ccs.tencentyun.com/ccs-dev/etcd-operator:dev"
  },
  {
    "path": "third_party/etcd-operator/NOTICE",
    "content": "CoreOS Project\nCopyright 2015 CoreOS, Inc\n\nThis product includes software developed at CoreOS, Inc.\n(http://www.coreos.com/).\n"
  },
  {
    "path": "third_party/etcd-operator/README.md",
    "content": "# etcd operator\nunit/integration:\n[![Build Status](https://jenkins-etcd-public.prod.coreos.systems/job/etcd-operator-unit-master/badge/icon)](https://jenkins-etcd-public.prod.coreos.systems/job/etcd-operator-unit-master/lastBuild/)\ne2e (Kubernetes stable):\n[![Build Status](https://jenkins-etcd-public.prod.coreos.systems/buildStatus/icon?job=etcd-operator-master)](https://jenkins-etcd-public.prod.coreos.systems/job/etcd-operator-master/)\ne2e (upgrade):\n[![Build Status](https://jenkins-etcd.prod.coreos.systems/buildStatus/icon?job=etcd-operator-upgrade)](https://jenkins-etcd.prod.coreos.systems/job/etcd-operator-upgrade/)\n\n### Project status: beta\n\nMajor planned features have been completed, and while no breaking API changes are currently planned, we reserve the right to address bugs and API changes in a backwards incompatible way before the project is declared stable. See [upgrade guide](./doc/user/upgrade/upgrade_guide.md) for a safe upgrade process.\n\nCurrently user facing etcd cluster objects are created as [Kubernetes Custom Resources](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions/), however, taking advantage of [User Aggregated API Servers](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/aggregated-api-servers.md) to improve reliability, validation and versioning is planned. The use of Aggregated API should be minimally disruptive to existing users but may change what Kubernetes objects are created or how users deploy the etcd operator.\n\nWe expect to consider the etcd operator stable soon; backwards incompatible changes will not be made once the project reaches stability.\n\n### Overview\n\nThe etcd operator manages etcd clusters deployed to [Kubernetes][k8s-home] and automates tasks related to operating an etcd cluster.\n\n- [Create and Destroy](#create-and-destroy-an-etcd-cluster)\n- [Resize](#resize-an-etcd-cluster)\n- [Failover](#failover)\n- [Rolling upgrade](#upgrade-an-etcd-cluster)\n- [Backup and Restore](#backup-and-restore-an-etcd-cluster)\n\nThere are [more spec examples](./doc/user/spec_examples.md) on setting up clusters with different configurations\n\nRead [Best Practices](./doc/best_practices.md) for more information on how to better use etcd operator.\n\nRead [RBAC docs](./doc/user/rbac.md) for how to setup RBAC rules for etcd operator if RBAC is in place.\n\nRead [Developer Guide](./doc/dev/developer_guide.md) for setting up a development environment if you want to contribute.\n\nSee the [Resources and Labels](./doc/user/resource_labels.md) doc for an overview of the resources created by the etcd-operator.\n\n## Requirements\n\n- Kubernetes 1.8+\n- etcd 3.2.13+\n\n## Demo\n\n## Getting started\n\n![etcd Operator demo](https://raw.githubusercontent.com/coreos/etcd-operator/master/doc/gif/demo.gif)\n\n### Deploy etcd operator\n\nSee [instructions on how to install/uninstall etcd operator](doc/user/install_guide.md) .\n\n### Create and destroy an etcd cluster\n\n```bash\n$ kubectl create -f example/example-etcd-cluster.yaml\n```\n\nA 3 member etcd cluster will be created.\n\n```bash\n$ kubectl get pods\nNAME                            READY     STATUS    RESTARTS   AGE\nexample-etcd-cluster-gxkmr9ql7z   1/1       Running   0          1m\nexample-etcd-cluster-m6g62x6mwc   1/1       Running   0          1m\nexample-etcd-cluster-rqk62l46kw   1/1       Running   0          1m\n```\n\nSee [client service](doc/user/client_service.md) for how to access etcd clusters created by the operator.\n\nIf you are working with [minikube locally](https://github.com/kubernetes/minikube#minikube), create a nodePort service and test that etcd is responding:\n\n```bash\n$ kubectl create -f example/example-etcd-cluster-nodeport-service.json\n$ export ETCDCTL_API=3\n$ export ETCDCTL_ENDPOINTS=$(minikube service example-etcd-cluster-client-service --url)\n$ etcdctl put foo bar\n```\n\nDestroy the etcd cluster:\n\n```bash\n$ kubectl delete -f example/example-etcd-cluster.yaml\n```\n\n### Resize an etcd cluster\n\nCreate an etcd cluster:\n\n```\n$ kubectl apply -f example/example-etcd-cluster.yaml\n```\n\nIn `example/example-etcd-cluster.yaml` the initial cluster size is 3.\nModify the file and change `size` from 3 to 5.\n\n```\n$ cat example/example-etcd-cluster.yaml\napiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdCluster\"\nmetadata:\n  name: \"example-etcd-cluster\"\nspec:\n  size: 5\n  version: \"3.2.13\"\n```\n\nApply the size change to the cluster CR:\n```\n$ kubectl apply -f example/example-etcd-cluster.yaml\n```\nThe etcd cluster will scale to 5 members (5 pods):\n```\n$ kubectl get pods\nNAME                            READY     STATUS    RESTARTS   AGE\nexample-etcd-cluster-cl2gpqsmsw   1/1       Running   0          5m\nexample-etcd-cluster-cx2t6v8w78   1/1       Running   0          5m\nexample-etcd-cluster-gxkmr9ql7z   1/1       Running   0          7m\nexample-etcd-cluster-m6g62x6mwc   1/1       Running   0          7m\nexample-etcd-cluster-rqk62l46kw   1/1       Running   0          7m\n```\n\nSimilarly we can decrease the size of the cluster from 5 back to 3 by changing the size field again and reapplying the change.\n\n```\n$ cat example/example-etcd-cluster.yaml\napiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdCluster\"\nmetadata:\n  name: \"example-etcd-cluster\"\nspec:\n  size: 3\n  version: \"3.2.13\"\n```\n```\n$ kubectl apply -f example/example-etcd-cluster.yaml\n```\n\nWe should see that etcd cluster will eventually reduce to 3 pods:\n\n```\n$ kubectl get pods\nNAME                            READY     STATUS    RESTARTS   AGE\nexample-etcd-cluster-cl2gpqsmsw   1/1       Running   0          6m\nexample-etcd-cluster-gxkmr9ql7z   1/1       Running   0          8m\nexample-etcd-cluster-rqk62l46kw   1/1       Running   0          9mp\n```\n\n### Failover\n\nIf the minority of etcd members crash, the etcd operator will automatically recover the failure.\nLet's walk through this in the following steps.\n\nCreate an etcd cluster:\n\n```\n$ kubectl create -f example/example-etcd-cluster.yaml\n```\n\nWait until all three members are up. Simulate a member failure by deleting a pod:\n\n```bash\n$ kubectl delete pod example-etcd-cluster-cl2gpqsmsw --now\n```\n\nThe etcd operator will recover the failure by creating a new pod `example-etcd-cluster-n4h66wtjrg`:\n\n```bash\n$ kubectl get pods\nNAME                            READY     STATUS    RESTARTS   AGE\nexample-etcd-cluster-gxkmr9ql7z   1/1       Running   0          10m\nexample-etcd-cluster-n4h66wtjrg   1/1       Running   0          26s\nexample-etcd-cluster-rqk62l46kw   1/1       Running   0          10m\n```\n\nDestroy etcd cluster:\n```bash\n$ kubectl delete -f example/example-etcd-cluster.yaml\n```\n\n### etcd operator recovery\n\nLet's walk through operator recovery in the following steps.\n\nCreate an etcd cluster:\n\n```\n$ kubectl create -f example/example-etcd-cluster.yaml\n```\n\nWait until all three members are up. Then stop the etcd operator and delete one of the etcd pods:\n\n```bash\n$ kubectl delete -f example/deployment.yaml\ndeployment \"etcd-operator\" deleted\n\n$ kubectl delete pod example-etcd-cluster-8gttjl679c --now\npod \"example-etcd-cluster-8gttjl679c\" deleted\n```\n\nNext restart the etcd operator. It should recover itself and the etcd clusters it manages.\n\n```bash\n$ kubectl create -f example/deployment.yaml\ndeployment \"etcd-operator\" created\n\n$ kubectl get pods\nNAME                              READY     STATUS    RESTARTS   AGE\nexample-etcd-cluster-m8gk76l4ns   1/1       Running   0          3m\nexample-etcd-cluster-q6mff85hml   1/1       Running   0          3m\nexample-etcd-cluster-xnfvm7lg66   1/1       Running   0          11s\n```\n\n### Upgrade an etcd cluster\n\nCreate and have the following yaml file ready:\n\n```\n$ cat upgrade-example.yaml\napiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdCluster\"\nmetadata:\n  name: \"example-etcd-cluster\"\nspec:\n  size: 3\n  version: \"3.1.10\"\n  repository: \"quay.io/coreos/etcd\"\n```\n\nCreate an etcd cluster with the version specified (3.1.10) in the yaml file:\n\n```\n$ kubectl apply -f upgrade-example.yaml\n$ kubectl get pods\nNAME                              READY     STATUS    RESTARTS   AGE\nexample-etcd-cluster-795649v9kq   1/1       Running   1          3m\nexample-etcd-cluster-jtp447ggnq   1/1       Running   1          4m\nexample-etcd-cluster-psw7sf2hhr   1/1       Running   1          4m\n```\n\nThe container image version should be 3.1.10:\n\n```\n$ kubectl get pod example-etcd-cluster-795649v9kq -o yaml | grep \"image:\" | uniq\n    image: quay.io/coreos/etcd:v3.1.10\n```\n\nNow modify the file `upgrade-example` and change the `version` from 3.1.10 to 3.2.13:\n\n```\n$ cat upgrade-example\napiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdCluster\"\nmetadata:\n  name: \"example-etcd-cluster\"\nspec:\n  size: 3\n  version: \"3.2.13\"\n```\n\nApply the version change to the cluster CR:\n\n```\n$ kubectl apply -f upgrade-example\n```\n\nWait ~30 seconds. The container image version should be updated to v3.2.13:\n\n```\n$ kubectl get pod example-etcd-cluster-795649v9kq -o yaml | grep \"image:\" | uniq\n    image: gcr.io/etcd-development/etcd:v3.2.13\n```\n\nCheck the other two pods and you should see the same result.\n\n\n### Backup and Restore an etcd cluster\n> Note: The provided etcd backup/restore operators are example implementations.\n\nFollow the [etcd backup operator walkthrough](./doc/user/walkthrough/backup-operator.md) to backup an etcd cluster.\n\nFollow the [etcd restore operator walkthrough](./doc/user/walkthrough/restore-operator.md) to restore an etcd cluster on Kubernetes from backup.\n\n### Manage etcd clusters in all namespaces\n\nSee [instructions on clusterwide feature](doc/user/clusterwide.md).\n\n[k8s-home]: http://kubernetes.io\n"
  },
  {
    "path": "third_party/etcd-operator/ROADMAP.md",
    "content": "# Roadmap\n\nThis document defines a high level roadmap for the etcd cluster operator development.\n\nThe dates below should not be considered authoritative, but rather indicative of the projected timeline of the project.\n\n\n### 2017 Q1\n\n#### Features\n\n- Backup and recovery\n  - Recover an etcd cluster from a PV backup -> finished\n  - Backup an etcd cluster to S3 -> finished\n  - Recover an etcd cluster from a S3 backup -> finished\n\n- Operationality\n  - Pause/Resume the control for an etcd cluster -> finished\n\n- Metrics and logging\n  - More structured logging\n      - Add prefix for different clusters -> finished\n      - Use infof, warningf, errorf consistently -> finished\n  - Expose operator metrics\n      - How many clusters it manages\n      - How many actions it does\n   - Expose the running status of the etcd cluster\n      - cluster size, version\n   - Expose errors \n     -  bad version, bad cluster size, dead cluster\n\n- Security\n  - Server side TLS support\n\n\n#### Stability/Reliability\n\n- Verify user inputs\n  - desired version\n  - cluster size (do not stupidly increase cluster size to an unreasonable number)\n\n- More soak testing\n- 60%+ unit tests coverage\n"
  },
  {
    "path": "third_party/etcd-operator/cmd/backup-operator/doc.go",
    "content": "// Copyright 2017 The etcd-operator 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// backup-operator is an example implementation of backing up an etcd cluster to S3.\n// user must not depend backup-operator for production usage and should\n// follow the design principle of backup-operator to create his/her own backup\n// mechanism.\npackage main\n"
  },
  {
    "path": "third_party/etcd-operator/cmd/backup-operator/main.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"net/http\"\n\t_ \"net/http/pprof\"\n\t\"os\"\n\t\"runtime\"\n\t\"time\"\n\n\tcontroller \"github.com/coreos/etcd-operator/pkg/controller/backup-operator\"\n\t\"github.com/coreos/etcd-operator/pkg/util/constants\"\n\t\"github.com/coreos/etcd-operator/pkg/util/etcdutil\"\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\tversion \"github.com/coreos/etcd-operator/version\"\n\n\t\"github.com/sirupsen/logrus\"\n\tv1 \"k8s.io/api/core/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/client-go/kubernetes/scheme\"\n\tv1core \"k8s.io/client-go/kubernetes/typed/core/v1\"\n\t\"k8s.io/client-go/tools/leaderelection\"\n\t\"k8s.io/client-go/tools/leaderelection/resourcelock\"\n\t\"k8s.io/client-go/tools/record\"\n)\n\nvar (\n\tcreateCRD bool\n)\n\n// etcd client tls configuration\nvar (\n\tetcdClientCertFile      = flag.String(\"etcd-client-cert-file\", etcdutil.DefaultCliCertFile, `The name of etcd client cert file`)\n\tetcdClientKeyFile      = flag.String(\"etcd-client-key-file\", etcdutil.DefaultCliKeyFile, `The name of etcd client key file`)\n\tetcdClientCaFile      = flag.String(\"etcd-client-ca-file\", etcdutil.DefaultCliCAFile, `The name of etcd client trusted CA File`)\n)\n\n\nfunc init() {\n\tflag.BoolVar(&createCRD, \"create-crd\", true, \"The backup operator will not create the EtcdBackup CRD when this flag is set to false.\")\n\tflag.Parse()\n}\n\nfunc main() {\n\tetcdutil.InitEtcdTLSConfig(*etcdClientCertFile,*etcdClientKeyFile,*etcdClientCaFile)\n\tnamespace := os.Getenv(constants.EnvOperatorPodNamespace)\n\tif len(namespace) == 0 {\n\t\tlogrus.Fatalf(\"must set env %s\", constants.EnvOperatorPodNamespace)\n\t}\n\tname := os.Getenv(constants.EnvOperatorPodName)\n\tif len(name) == 0 {\n\t\tlogrus.Fatalf(\"must set env %s\", constants.EnvOperatorPodName)\n\t}\n\tid, err := os.Hostname()\n\tif err != nil {\n\t\tlogrus.Fatalf(\"failed to get hostname: %v\", err)\n\t}\n\n\tlogrus.Infof(\"Go Version: %s\", runtime.Version())\n\tlogrus.Infof(\"Go OS/Arch: %s/%s\", runtime.GOOS, runtime.GOARCH)\n\tlogrus.Infof(\"etcd-backup-operator Version: %v\", version.Version)\n\tlogrus.Infof(\"Git SHA: %s\", version.GitSHA)\n\n\tif len(os.Getenv(constants.EnvOperatorWatchNamespace)) > 0 {\n\t\tlogrus.Infof(\"operator watch namespace: %s\", os.Getenv(constants.EnvOperatorWatchNamespace))\n\t} else {\n\t\tlogrus.Infof(\"operator watch namespace: all\")\n\t}\n\n\tgo func() {\n\t\tlogrus.Info(http.ListenAndServe(\":6060\", nil))\n\t}()\n\n\tkubecli := k8sutil.MustNewKubeClient()\n\trl, err := resourcelock.New(\n\t\tresourcelock.EndpointsResourceLock,\n\t\tnamespace,\n\t\t\"etcd-backup-operator\",\n\t\tkubecli.Core(),\n\t\tresourcelock.ResourceLockConfig{\n\t\t\tIdentity:      id,\n\t\t\tEventRecorder: createRecorder(kubecli, name, namespace),\n\t\t},\n\t)\n\tif err != nil {\n\t\tlogrus.Fatalf(\"error creating lock: %v\", err)\n\t}\n\n\tctx, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\n\tleaderelection.RunOrDie(ctx, leaderelection.LeaderElectionConfig{\n\t\tLock:          rl,\n\t\tLeaseDuration: 15 * time.Second,\n\t\tRenewDeadline: 10 * time.Second,\n\t\tRetryPeriod:   2 * time.Second,\n\t\tCallbacks: leaderelection.LeaderCallbacks{\n\t\t\tOnStartedLeading: run,\n\t\t\tOnStoppedLeading: func() {\n\t\t\t\tlogrus.Fatalf(\"leader election lost\")\n\t\t\t},\n\t\t},\n\t})\n}\n\nfunc createRecorder(kubecli kubernetes.Interface, name, namespace string) record.EventRecorder {\n\teventBroadcaster := record.NewBroadcaster()\n\teventBroadcaster.StartLogging(logrus.Infof)\n\teventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubecli.Core().RESTClient()).Events(namespace)})\n\treturn eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: name})\n}\n\nfunc run(ctx context.Context) {\n\tctx, cancel := context.WithCancel(ctx)\n\tdefer cancel()\n\tc := controller.New(createCRD)\n\terr := c.Start(ctx)\n\tif err != nil {\n\t\tlogrus.Fatalf(\"operator stopped with error: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/cmd/operator/main.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"os\"\n\t\"runtime\"\n\t\"time\"\n\n\t\"github.com/coreos/etcd-operator/pkg/chaos\"\n\t\"github.com/coreos/etcd-operator/pkg/client\"\n\t\"github.com/coreos/etcd-operator/pkg/controller\"\n\t\"github.com/coreos/etcd-operator/pkg/util/constants\"\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\t\"github.com/coreos/etcd-operator/pkg/util/probe\"\n\t\"github.com/coreos/etcd-operator/pkg/util/retryutil\"\n\t\"github.com/coreos/etcd-operator/version\"\n\t\"github.com/prometheus/client_golang/prometheus\"\n\n\t\"github.com/sirupsen/logrus\"\n\t\"golang.org/x/time/rate\"\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/client-go/kubernetes\"\n\t\"k8s.io/client-go/kubernetes/scheme\"\n\tv1core \"k8s.io/client-go/kubernetes/typed/core/v1\"\n\t\"k8s.io/client-go/tools/leaderelection\"\n\t\"k8s.io/client-go/tools/leaderelection/resourcelock\"\n\t\"k8s.io/client-go/tools/record\"\n)\n\nvar (\n\tnamespace  string\n\tname       string\n\tlistenAddr string\n\tgcInterval time.Duration\n\n\tchaosLevel int\n\n\tprintVersion bool\n\n\tcreateCRD bool\n\n\tclusterWide bool\n)\n\nfunc init() {\n\tflag.StringVar(&listenAddr, \"listen-addr\", \"0.0.0.0:8080\", \"The address on which the HTTP server will listen to\")\n\t// chaos level will be removed once we have a formal tool to inject failures.\n\tflag.IntVar(&chaosLevel, \"chaos-level\", -1, \"DO NOT USE IN PRODUCTION - level of chaos injected into the etcd clusters created by the operator.\")\n\tflag.BoolVar(&printVersion, \"version\", false, \"Show version and quit\")\n\tflag.BoolVar(&createCRD, \"create-crd\", true, \"The operator will not create the EtcdCluster CRD when this flag is set to false.\")\n\tflag.DurationVar(&gcInterval, \"gc-interval\", 10*time.Minute, \"GC interval\")\n\tflag.BoolVar(&clusterWide, \"cluster-wide\", false, \"Enable operator to watch clusters in all namespaces\")\n\tflag.Parse()\n}\n\nfunc main() {\n\tnamespace = os.Getenv(constants.EnvOperatorPodNamespace)\n\tif len(namespace) == 0 {\n\t\tlogrus.Fatalf(\"must set env (%s)\", constants.EnvOperatorPodNamespace)\n\t}\n\tname = os.Getenv(constants.EnvOperatorPodName)\n\tif len(name) == 0 {\n\t\tlogrus.Fatalf(\"must set env (%s)\", constants.EnvOperatorPodName)\n\t}\n\n\tif printVersion {\n\t\tfmt.Println(\"etcd-operator Version:\", version.Version)\n\t\tfmt.Println(\"Git SHA:\", version.GitSHA)\n\t\tfmt.Println(\"Go Version:\", runtime.Version())\n\t\tfmt.Printf(\"Go OS/Arch: %s/%s\\n\", runtime.GOOS, runtime.GOARCH)\n\t\tos.Exit(0)\n\t}\n\n\tlogrus.Infof(\"etcd-operator Version: %v\", version.Version)\n\tlogrus.Infof(\"Git SHA: %s\", version.GitSHA)\n\tlogrus.Infof(\"Go Version: %s\", runtime.Version())\n\tlogrus.Infof(\"Go OS/Arch: %s/%s\", runtime.GOOS, runtime.GOARCH)\n\n\tid, err := os.Hostname()\n\tif err != nil {\n\t\tlogrus.Fatalf(\"failed to get hostname: %v\", err)\n\t}\n\n\tkubecli := k8sutil.MustNewKubeClient()\n\n\thttp.HandleFunc(probe.HTTPReadyzEndpoint, probe.ReadyzHandler)\n\thttp.Handle(\"/metrics\", prometheus.Handler())\n\tgo http.ListenAndServe(listenAddr, nil)\n\n\trl, err := resourcelock.New(resourcelock.EndpointsResourceLock,\n\t\tnamespace,\n\t\t\"etcd-operator\",\n\t\tkubecli.CoreV1(),\n\t\tresourcelock.ResourceLockConfig{\n\t\t\tIdentity:      id,\n\t\t\tEventRecorder: createRecorder(kubecli, name, namespace),\n\t\t})\n\tif err != nil {\n\t\tlogrus.Fatalf(\"error creating lock: %v\", err)\n\t}\n\n\tctx, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\n\tleaderelection.RunOrDie(ctx, leaderelection.LeaderElectionConfig{\n\t\tLock:          rl,\n\t\tLeaseDuration: 15 * time.Second,\n\t\tRenewDeadline: 10 * time.Second,\n\t\tRetryPeriod:   2 * time.Second,\n\t\tCallbacks: leaderelection.LeaderCallbacks{\n\t\t\tOnStartedLeading: run,\n\t\t\tOnStoppedLeading: func() {\n\t\t\t\tlogrus.Fatalf(\"leader election lost\")\n\t\t\t},\n\t\t},\n\t})\n\n\tpanic(\"unreachable\")\n}\n\nfunc run(ctx context.Context) {\n\tctx, cancel := context.WithCancel(ctx)\n\tdefer cancel()\n\tcfg := newControllerConfig()\n\n\tstartChaos(context.Background(), cfg.KubeCli, cfg.Namespace, chaosLevel)\n\n\tc := controller.New(cfg)\n\terr := c.Start()\n\tlogrus.Fatalf(\"controller Start() failed: %v\", err)\n}\n\nfunc newControllerConfig() controller.Config {\n\tkubecli := k8sutil.MustNewKubeClient()\n\n\tserviceAccount, err := getMyPodServiceAccount(kubecli)\n\tif err != nil {\n\t\tlogrus.Fatalf(\"fail to get my pod's service account: %v\", err)\n\t}\n\n\tcfg := controller.Config{\n\t\tNamespace:      namespace,\n\t\tClusterWide:    clusterWide,\n\t\tServiceAccount: serviceAccount,\n\t\tKubeCli:        kubecli,\n\t\tKubeExtCli:     k8sutil.MustNewKubeExtClient(),\n\t\tEtcdCRCli:      client.MustNewInCluster(),\n\t\tCreateCRD:      createCRD,\n\t}\n\n\treturn cfg\n}\n\nfunc getMyPodServiceAccount(kubecli kubernetes.Interface) (string, error) {\n\tvar sa string\n\terr := retryutil.Retry(5*time.Second, 100, func() (bool, error) {\n\t\tpod, err := kubecli.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\tlogrus.Errorf(\"fail to get operator pod (%s): %v\", name, err)\n\t\t\treturn false, nil\n\t\t}\n\t\tsa = pod.Spec.ServiceAccountName\n\t\treturn true, nil\n\t})\n\treturn sa, err\n}\n\nfunc startChaos(ctx context.Context, kubecli kubernetes.Interface, ns string, chaosLevel int) {\n\tm := chaos.NewMonkeys(kubecli)\n\tls := labels.SelectorFromSet(map[string]string{\"app\": \"etcd\"})\n\n\tswitch chaosLevel {\n\tcase 1:\n\t\tlogrus.Info(\"chaos level = 1: randomly kill one etcd pod every 30 seconds at 50%\")\n\t\tc := &chaos.CrashConfig{\n\t\t\tNamespace: ns,\n\t\t\tSelector:  ls,\n\n\t\t\tKillRate:        rate.Every(30 * time.Second),\n\t\t\tKillProbability: 0.5,\n\t\t\tKillMax:         1,\n\t\t}\n\t\tgo func() {\n\t\t\ttime.Sleep(60 * time.Second) // don't start until quorum up\n\t\t\tm.CrushPods(ctx, c)\n\t\t}()\n\n\tcase 2:\n\t\tlogrus.Info(\"chaos level = 2: randomly kill at most five etcd pods every 30 seconds at 50%\")\n\t\tc := &chaos.CrashConfig{\n\t\t\tNamespace: ns,\n\t\t\tSelector:  ls,\n\n\t\t\tKillRate:        rate.Every(30 * time.Second),\n\t\t\tKillProbability: 0.5,\n\t\t\tKillMax:         5,\n\t\t}\n\n\t\tgo m.CrushPods(ctx, c)\n\n\tdefault:\n\t}\n}\n\nfunc createRecorder(kubecli kubernetes.Interface, name, namespace string) record.EventRecorder {\n\teventBroadcaster := record.NewBroadcaster()\n\teventBroadcaster.StartLogging(logrus.Infof)\n\teventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubecli.Core().RESTClient()).Events(namespace)})\n\treturn eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: name})\n}\n"
  },
  {
    "path": "third_party/etcd-operator/cmd/restore-operator/doc.go",
    "content": "// Copyright 2017 The etcd-operator 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// restore-operator is an example implementation of restoring etcd cluster from S3.\n// user must not depend restore-operator for production usage and should\n// follow the design principle of restore-operator to create their own restore\n// mechanism.\npackage main\n"
  },
  {
    "path": "third_party/etcd-operator/cmd/restore-operator/main.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"os\"\n\t\"runtime\"\n\t\"time\"\n\n\tcontroller \"github.com/coreos/etcd-operator/pkg/controller/restore-operator\"\n\t\"github.com/coreos/etcd-operator/pkg/util/constants\"\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\tversion \"github.com/coreos/etcd-operator/version\"\n\n\t\"github.com/sirupsen/logrus\"\n\tv1 \"k8s.io/api/core/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/client-go/kubernetes/scheme\"\n\tv1core \"k8s.io/client-go/kubernetes/typed/core/v1\"\n\t\"k8s.io/client-go/tools/leaderelection\"\n\t\"k8s.io/client-go/tools/leaderelection/resourcelock\"\n\t\"k8s.io/client-go/tools/record\"\n)\n\nvar (\n\tnamespace string\n\tcreateCRD bool\n)\n\nconst (\n\tserviceNameForMyself = \"etcd-restore-operator\"\n\tservicePortForMyself = 19999\n)\n\nfunc init() {\n\tflag.BoolVar(&createCRD, \"create-crd\", true, \"The restore operator will not create the EtcdRestore CRD when this flag is set to false.\")\n\tflag.Parse()\n}\n\nfunc main() {\n\tnamespace = os.Getenv(constants.EnvOperatorPodNamespace)\n\tif len(namespace) == 0 {\n\t\tlogrus.Fatalf(\"must set env %s\", constants.EnvOperatorPodNamespace)\n\t}\n\tname := os.Getenv(constants.EnvOperatorPodName)\n\tif len(name) == 0 {\n\t\tlogrus.Fatalf(\"must set env %s\", constants.EnvOperatorPodName)\n\t}\n\tid, err := os.Hostname()\n\tif err != nil {\n\t\tlogrus.Fatalf(\"failed to get hostname: %v\", err)\n\t}\n\n\tlogrus.Infof(\"Go Version: %s\", runtime.Version())\n\tlogrus.Infof(\"Go OS/Arch: %s/%s\", runtime.GOOS, runtime.GOARCH)\n\tlogrus.Infof(\"etcd-restore-operator Version: %v\", version.Version)\n\tlogrus.Infof(\"Git SHA: %s\", version.GitSHA)\n\n\tkubecli := k8sutil.MustNewKubeClient()\n\n\terr = createServiceForMyself(kubecli, name, namespace)\n\tif err != nil {\n\t\tlogrus.Fatalf(\"create service failed: %+v\", err)\n\t}\n\n\trl, err := resourcelock.New(\n\t\tresourcelock.EndpointsResourceLock,\n\t\tnamespace,\n\t\t\"etcd-restore-operator\",\n\t\tkubecli.Core(),\n\t\tresourcelock.ResourceLockConfig{\n\t\t\tIdentity:      id,\n\t\t\tEventRecorder: createRecorder(kubecli, name, namespace),\n\t\t},\n\t)\n\tif err != nil {\n\t\tlogrus.Fatalf(\"error creating lock: %v\", err)\n\t}\n\n\tctx, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\n\tleaderelection.RunOrDie(ctx, leaderelection.LeaderElectionConfig{\n\t\tLock:          rl,\n\t\tLeaseDuration: 15 * time.Second,\n\t\tRenewDeadline: 10 * time.Second,\n\t\tRetryPeriod:   2 * time.Second,\n\t\tCallbacks: leaderelection.LeaderCallbacks{\n\t\t\tOnStartedLeading: run,\n\t\t\tOnStoppedLeading: func() {\n\t\t\t\tlogrus.Fatalf(\"leader election lost\")\n\t\t\t},\n\t\t},\n\t})\n}\n\nfunc createRecorder(kubecli kubernetes.Interface, name, namespace string) record.EventRecorder {\n\teventBroadcaster := record.NewBroadcaster()\n\teventBroadcaster.StartLogging(logrus.Infof)\n\teventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubecli.Core().RESTClient()).Events(namespace)})\n\treturn eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: name})\n}\n\nfunc run(ctx context.Context) {\n\tctx, cancel := context.WithCancel(ctx)\n\tdefer cancel()\n\tc := controller.New(createCRD, namespace, fmt.Sprintf(\"%s:%d\", serviceNameForMyself, servicePortForMyself))\n\terr := c.Start(ctx)\n\tif err != nil {\n\t\tlogrus.Fatalf(\"etcd restore operator stopped with error: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/cmd/restore-operator/service.go",
    "content": "// Copyright 2018 The etcd-operator 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\npackage main\n\nimport (\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\n\t\"github.com/pkg/errors\"\n\t\"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/util/intstr\"\n\t\"k8s.io/client-go/kubernetes\"\n)\n\n// createServiceForMyself gets restore-operator pod labels, strip away \"pod-template-hash\",\n// and then use it as selector to create a service for current restore-operator.\nfunc createServiceForMyself(kubecli kubernetes.Interface, name, namespace string) error {\n\tpod, err := kubecli.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn errors.WithStack(err)\n\t}\n\t// strip away replicaset-specific label added by deployment.\n\tdelete(pod.Labels, \"pod-template-hash\")\n\tsvc := &v1.Service{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      serviceNameForMyself,\n\t\t\tNamespace: namespace,\n\t\t\tLabels:    pod.Labels,\n\t\t},\n\t\tSpec: v1.ServiceSpec{\n\t\t\tPorts: []v1.ServicePort{{\n\t\t\t\tPort:       int32(servicePortForMyself),\n\t\t\t\tTargetPort: intstr.FromInt(servicePortForMyself),\n\t\t\t\tProtocol:   v1.ProtocolTCP,\n\t\t\t}},\n\t\t\tSelector: pod.Labels,\n\t\t},\n\t}\n\t_, err = kubecli.CoreV1().Services(namespace).Create(svc)\n\tif err != nil && !k8sutil.IsKubernetesResourceAlreadyExistError(err) {\n\t\treturn errors.WithStack(err)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/code-of-conduct.md",
    "content": "## CoreOS Community Code of Conduct\n\n### Contributor Code of Conduct\n\nAs contributors and maintainers of this project, and in the interest of\nfostering an open and welcoming community, we pledge to respect all people who\ncontribute through reporting issues, posting feature requests, updating\ndocumentation, submitting pull requests or patches, and other activities.\n\nWe are committed to making participation in this project a harassment-free\nexperience for everyone, regardless of level of experience, gender, gender\nidentity and expression, sexual orientation, disability, personal appearance,\nbody size, race, ethnicity, age, religion, or nationality.\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery\n* Personal attacks\n* Trolling or insulting/derogatory comments\n* Public or private harassment\n* Publishing others' private information, such as physical or electronic addresses, without explicit permission\n* Other unethical or unprofessional conduct.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct. By adopting this Code of Conduct,\nproject maintainers commit themselves to fairly and consistently applying these\nprinciples to every aspect of managing this project. Project maintainers who do\nnot follow or enforce the Code of Conduct may be permanently removed from the\nproject team.\n\nThis code of conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community.\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting a project maintainer, Brandon Philips\n<brandon.philips@coreos.com>, and/or Rithu John <rithu.john@coreos.com>.\n\nThis Code of Conduct is adapted from the Contributor Covenant\n(http://contributor-covenant.org), version 1.2.0, available at\nhttp://contributor-covenant.org/version/1/2/0/\n\n### CoreOS Events Code of Conduct\n\nCoreOS events are working conferences intended for professional networking and\ncollaboration in the CoreOS community. Attendees are expected to behave\naccording to professional standards and in accordance with their employer’s\npolicies on appropriate workplace behavior.\n\nWhile at CoreOS events or related social networking opportunities, attendees\nshould not engage in discriminatory or offensive speech or actions including\nbut not limited to gender, sexuality, race, age, disability, or religion.\nSpeakers should be especially aware of these concerns.\n\nCoreOS does not condone any statements by speakers contrary to these standards.\nCoreOS reserves the right to deny entrance and/or eject from an event (without\nrefund) any individual found to be engaging in discriminatory or offensive\nspeech or actions.\n\nPlease bring any concerns to the immediate attention of designated on-site\nstaff, Brandon Philips <brandon.philips@coreos.com>, and/or Rithu John <rithu.john@coreos.com>.\n"
  },
  {
    "path": "third_party/etcd-operator/codecov.yaml",
    "content": "# Pull Request comment report\ncomment: off\n"
  },
  {
    "path": "third_party/etcd-operator/doc/alpha-features.md",
    "content": "# Alpha Features\n\nTracking document for alpha features of Kubernetes that etcd operator makes use of.\n\nWe track these alpha features as their behavior may change or be deprecated between Kubernetes versions.\nTherefore clusters that use these features need to keep track of any potential changes in upstream releases.\nSee the upstream [api versioning documentation](https://github.com/kubernetes/community/blob/master/contributors/devel/api_changes.md#alpha-beta-and-stable-versions) for more information.\n\n\n### TolerateUnreadyEndpointsAnnotation\n\nUsed by the etcd client and peer service object.\n\nThis alpha annotation will retain the endpoints even if the etcd pod isn't ready.\nThis feature is always enabled in endpoint controller in k8s even it is alpha.\n\nReferences:\n- https://github.com/coreos/etcd-operator/issues/622\n- https://github.com/coreos/etcd-operator/issues/1257\n"
  },
  {
    "path": "third_party/etcd-operator/doc/best_practices.md",
    "content": "# Best practices\n\n## Large-scale deployment\n\nTo run etcd cluster at large-scale, it is important to assign etcd pods to nodes with desired resources, such as SSD, high performance network.\n\n### Assign to nodes with desired resources\n\nKubernetes nodes can be attached with labels. Users can [assign pods to nodes with given labels](http://kubernetes.io/docs/user-guide/node-selection/). Similarly for the etcd-operator, users can specify `Node Selector` in the pod policy to select nodes for etcd pods. For example, users can label a set of nodes with SSD with label `\"disk\"=\"SSD\"`. To assign etcd pods to these node, users can specify `\"disk\"=\"SSD\"` node selector in the cluster spec.\n\n### Assign to dedicated node\n\nEven with container isolation, not all resources are isolated. Thus, performance interference can still affect etcd clusters' performance unexpectedly. We recommend dedicating nodes for each etcd pod to achieve predictable performance.\n\nKubernetes node can be [tainted](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/scheduling/taint-toleration-dedicated.md) with keys. Together with node selector feature, users can create nodes that are dedicated for only running etcd clusters. This is the **suggested way** to run high performance large scale etcd clusters.\n\nUse kubectl to taint the node with kubectl taint nodes etcd dedicated. Then only etcd pods, which tolerate this taint will be assigned to the nodes.\n"
  },
  {
    "path": "third_party/etcd-operator/doc/design/abs_backup.md",
    "content": "# Backups using Azure Blob Service (ABS)\n\n## Cluster configured with ABS backup\n\nTo create a cluster with backups to ABS, set `backup.storageType` to `\"ABS\"`, supply the name of the ABS container to `abs.absContainer` and provide the Kubernetes secret storing the Azure Storage account credentials to `abs.absSecret`.  The latter two resources must exist prior to cluster creation.\n\nAn example cluster manifest would look like:\n\n```bash\napiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdCluster\"\nmetadata:\n  name: \"etcd-cluster-with-abs-backup\"\nspec:\n  ...\n  backup:\n    ...\n    storageType: \"ABS\"\n    abs:\n      absContainer: \"myabscontainer\"\n      absSecret: \"abs-credentials\"\n\n``` \n\n### In Detail:\n\n- `\"absSecret\"` represents the name of the Kubernetes secret object that stores the environment variables needed for ABS storage account authorization, namely, the storage account name and the storage account key.\n\n  The Kubernetes secret manifest looks like:\n  ```\n  apiVersion: v1\n  kind: Secret\n  metadata:\n    name: abs-credentials\n  type: Opaque\n  stringData:\n    storage-account: <storage-account-name>\n    storage-key: <storage-key>\n  ```\n\n  To create the secret object from the manifest above:\n\n  ```bash\n  $ kubectl create -f secret-abs-credentials.yaml\n  ```\n\n- `\"absContainer\"` represents the name of the ABS container in which the operator will store backups.\n\n  The backups of each cluster are saved in individual directories under the given container.\n\n  As a reminder, to create a container via Azure's `az` command line, one may do the following:\n\n  ```bash\n  $ az storage container create -n etcd-backups\n  ```\n\n  The full directory/file format looks like: `*container_name/<prefix>/cluster_name/<backup file>`, where `<prefix>` includes version (`v1`) and the Kubernetes namespace the cluster lies in (`etcd-ns`) and `<backup file>` represents the backup filename.\n\n  For example, given container \"etcd-backups\" and cluster \"etcd-a\", we should see the backup files after running the following command:\n\n  ```bash\n  $ az storage blob list -c etcd-backups\n  Name                                                 Blob Type      Length  Content Type              Last Modified\n  --------------------------------------------------   -----------  --------  ------------------------  -------------------------\n  v1/etcd-ns/etcd-a/3.1.8_0000000000000326_etcd.backup BlockBlob      647200  application/octet-stream  2017-06-29T20:19:32+00:00\n  ...\n  ```\n\n  Alternatively, one many login into the Azure Portal to view these backups.\n"
  },
  {
    "path": "third_party/etcd-operator/doc/design/backup_operator.md",
    "content": "# etcd Backup Operator Design Document\n\n## Problem\n\nCurrently, etcd-operator supports various backup strategies such as PV, S3, and Azure Blob Store. However, those strategies are embedded into the etcd operator code itself. Support for new backup strategy are required to be pushed into etcd-operator codebase. As more backup strategies are added, the etcd-operator code base would be hard to maintain. In Addition, users may want to implement their backup strategy without confining to the current etcd-operator’s backup spec and may not want to dependent on etcd-operator codebase for backup.\n\n## Solution\n\nTo give user the flexibility of handling etcd backup his/her own way and to decouple backup logic out of etcd operator, a standalone etcd-backup operator can be used to manage the backup.\n\n## A Proposed Architecture \n\nIn order to control backup of etcd clusters, a standalone etcd backup operator can be used to listen for a customized backup CRD:\n\nFirst, User creates a backup CRD that etcd backup operator will be watching on:\n\n```yaml\napiVersion: apiextentions.k8s.io/v1beta2\nkind: CustomResourceDefiniton\nmetadata:\n  name: etcdbackups.etcd.database.coreos.com\nspec:\n  group: etcd.database.coreos.com\n  version: v1beta2\n  Scope: Namespaced\n  names: \n    kind: EtcdBackup\n    plural: etcdbackups\n```\n\nThen, start the etcd-backup-operator where it does the following:\n\n* checks if CRD exists.\n* watches for new backup CR. \n* manages backup according to `EtcdBackupSpec`.\n* reports backup status. \n\n`EtcdBackupSpec` definition:\n\n```go\ntype EtcdBackupSpec struct {\n    // clusterName is the etcd cluster name that needs backup.\n    ClusterName string `json:\"clusterName,omitempty\"`\n    // StorageType is the type of backup storage.\n    StorageType string `json:\"storageType\"`\n    // StorageSource details storage sources.\n    StorageSource `json:\",inline\"`\n    // Any additional backup configs.\n}\ntype StorageSource struct {\n    // S3 contains resources that operator needs to store backup on S3.\n    S3 *S3Source\n}\ntype S3Source struct {\n\t// The name of the AWS S3 bucket to store backups in.\n\t// S3Bucket overwrites the default etcd operator wide bucket.\n\tS3Bucket string `json:\"s3Bucket,omitempty\"`\n\n\t// Prefix is the S3 prefix used to prefix the bucket path.\n\t// It's the prefix at the beginning.\n\t// After that, it will have version and cluster specific paths.\n\tPrefix string `json:\"prefix,omitempty\"`\n\n\t// The name of the secret object that stores the AWS credential and config files.\n\t// The file name of the credential MUST be 'credentials'.\n\t// The file name of the config MUST be 'config'.\n\t// The profile to use in both files will be 'default'.\n\t//\n\t// AWSSecret overwrites the default etcd operator wide AWS credential and config.\n\tAWSSecret string `json:\"awsSecret,omitempty\"`\n}\n```\n\n"
  },
  {
    "path": "third_party/etcd-operator/doc/design/cluster_creation.md",
    "content": "# Cluster creation\n\nThe create a cluster when it receives an `added` event.\n\nTo initialize a cluster, we first need to create a seed etcd member. Then we can rely on resize to increase the cluster size to the desired number of members.\n\n1. receive added event\n2. create a member with setting --initial-cluster-state to new with a random cluster token\n3. END.\n\n## Failure recovery\n\nIf operator fails before creating the first member, we will end up with a cluster with no running pods.\n\nRecovery can be challenging if this happens. It is impossible for us to differentiate a dead cluster from a uninitialized cluster.\n\nWe choose the simplest solution here. We always consider a cluster with no running pods a failed cluster. The operator will\ntry to recover it from existing backups. If there is no backup, we mark the cluster dead.\n"
  },
  {
    "path": "third_party/etcd-operator/doc/design/cluster_lifecycle.md",
    "content": "# etcd cluster lifecycle in etcd operator\n\nLet's talk about the lifecycle of etcd cluster \"A\".\n\n- Initially, \"A\" doesn't exist. Operator considers this cluster has 0 members.\n  Any cluster with 0 members would be considered as non-existed.\n- At some point of time, a user creates an object for \"A\".\n  Operator would receive \"ADDED\" event and create this cluster.\n  For the entire lifecycle, an etcd cluster could be created only once.\n- Then user might update 0 or more times on the spec of \"A\".\n  Operator would receive \"MODIFIED\" events and reconcile actual state gradually to desired state of given spec.\n- Finally, a user deletes the object of \"A\". Operator will delete and recycle all resources of \"A\".\n  For the entire lifecycle, an etcd cluster could be deleted only once."
  },
  {
    "path": "third_party/etcd-operator/doc/design/cluster_restore.md",
    "content": "# Restore Cluster From Existing Backup\n\nWe want to restore an etcd cluster from existing backup that operator has saved before.\n\nWe add a field in ClusterSpec:\n\n```Go\ntype ClusterSpec struct {\n    ...\n    // RestorePolicy defines the policy to restore cluster form existing backup if not nil.\n    RestorePolicy *RestorePolicy\n}\n\ntype RestorePolicy struct {\n    // BackupClusterName is the cluster name of the backup to recover from.\n    BackupClusterName string\n\n    // StorageType specifies the type of storage device to store backup files.\n    // If it's not set by user, the default is \"PersistentVolume\".\n    StorageType BackupStorageType\n}\n```\n\nFor example, let's say, a user has a cluster \"etcd-A\" running. For some reason, it stops working.\nAt the end, the cluster is killed by user or dead by itself. Fortunately, the cluster was run with\nvalid BackupPolicy and saved with backup. Now, user can restore the cluster by adding \"restorePolicy\"\nto previous yaml file:\n\n```yaml\napiVersion: \"etcd.coreos.com/v1beta1\"\nkind: \"Cluster\"\nmetadata:\n  name: \"etcd-A\"\nspec:\n  ...\n  restorePolicy:\n    backupClusterName: \"etcd-A\"\n    storageType: \"PersistentVolume\"\n```\n\nIt is not necessary to restore the exact same cluster as before.\nUser can restore a new cluster \"etcd-B\" from \"etcd-A\", with different size, backup policy, etc.\n"
  },
  {
    "path": "third_party/etcd-operator/doc/design/cluster_status.md",
    "content": "## Cluster status reporting\n\nAn etcd cluster permanently fails when all its members are dead and no backup is available. A user might update etcd cluster TPR with invalid input or format. The operator needs to notify users about these bad events.\n\nA common way to do this in the Kubernetes world is through status field, like pod.status. The etcd operator will write out cluster status similar to pod status.\n\n```go\ntype EtcdCluster struct {\n    unversioned.TypeMeta `json:\",inline\"`\n    api.ObjectMeta       `json:\"metadata,omitempty\"`\n    Spec                 ClusterSpec `json:\"spec\"`\n    Status               ClusterStatus `json:\"status\"`\n}\n\nType ClusterStatus struct {\n    Paused bool `json:\"paused\"`\n    ...\n}\n```\n\nThe etcd operator keeps the truth of the cluster status, and update the TPR item after each cluster reconciliation atomically. Note that users can:\n\n - modify TPR item concurrently with the operator.\n - update TPR and overwrite the status filed with empty or bad input\n\n The operator MUST handle these two cases gracefully. Thus, the operator MUST NOT overwrite the user input on spec field. The operator CANNOT trust the existing status filed in TPR.\n\nTo not overwrite the user input, the etcd operator will set resource version, and do a compare and swap on resource version to update the status. If the compare and swap fails, the operator knows that the user updated the spec concurrently, and it will retry later after get the new spec.\n\nTo not be affected by the potential empty or broken status accidentally written by the user, the etcd operator will never read the status from TPR. It always keeps the source of truth in memory.\n\nIn summary, the TPR:\n\n- receive spec update (or initialize spec) with a resource version\n- collect cluster status during reconciliation\n- atomically update cluster status with known resource version after reconciliation if there is a status change\n  - retry if resource version does not match\n"
  },
  {
    "path": "third_party/etcd-operator/doc/design/cluster_tls.md",
    "content": "# etcd cluster TLS\n\n## Abstract\n\nThe primary goals etcd-operator cluster TLS:\n * Encrypt etcd client/peer communication\n * Cryptographically attestable identities for following components:\n    * etcd operator\n    * etcd cluster TPR objects\n    * backup sidecar pods\n    * etcd pods\n * Cryptographically enforced cluster isolation (backup pod from cluster A CANNOT possibly talk to etcd pod in cluster B)\n\n## Intra-Cluster PKI overview\n\nHere is the overview for etcd-operator TLS flow, which should set us up well for integrating with pre-existing external PKI.\n\n### Trust delegation diagram:\n\n```\n    -----------------\n    | external PKI  |  (something that can sign the operator's CSRs)\n    -----------------\n          |     |\n          |  | /|\\ CERT\n          |  |  |   |\n          |  |  |   |\n          |  | CSR \\|/\n          |  |\n          |  |\n          |  |\n          |  |---> [ operator client-interface CA ]\n          |         |\n          |            |                    --------------> [ etcd-cluster-A client-interface CLIENT CERT ]\n          |            |                    |\n          |            |             DIRECT | SIGN\n          |            |                     |\n          |            |-------->  [ etcd-cluster-A client-interface CERTIFICATE AUTHORITY ]\n          |            |                    |\n          |         D  |                    |  etcd-cluster-A-0000\n          |         I  |                    |-------------> [ client-interface SERVER CERT ]\n          |         R  |           /|\\ CERT |\n          |         E  |            |   |   |  etcd-cluster-A-0001\n          |         C  |           CSR \\|/  |-------------> [ client-interface SERVER CERT ]\n          |         T  |                    |\n          |            |                    |  etcd-cluster-A-0002\n          |         S  |                    |-------------> [ client-interface SERVER CERT ]\n          |         I  |                    |\n          |         G  |                    |  cluster-A-backup-sidecar\n          |         N  |                    |-------------> [ client-interface CLIENT CERT ]\n          |            |                    |\n          |            |                    |\n          |            |                    |\n          |            |                    --------------> [ etcd-cluster-B client-interface CLIENT CERT ]\n          |            |                    |\n          |            |             DIRECT | SIGN\n          |            |                    |\n          |            |                    |-------->  [ etcd-cluster-B client-interface CERTIFICATE AUTHORITY ]\n     /|\\  | CERT       |                    |\n      |   |  |         |                    |  etcd-cluster-B-0000\n      |      |         |                    |------> ...\n     CSR  | \\|/        |\n          |            | ...\n          |\n          |\n          |------> [ operator peer-interface CA ]\n                    |\n                    |\n                    |-------->  [ etcd-cluster-A peer interface CERTIFICATE AUTHORITY ]\n                    |                    |\n                 D  |                    |  etcd-cluster-A-0000\n                 I  |                    |-------------> [ peer-interface SERVER CERT ]\n                 R  |           /|\\ CERT |\n                 E  |            |   |   |  etcd-cluster-A-0001\n                 C  |           CSR \\|/  |-------------> [ peer-interface SERVER CERT ]\n                 T  |                    |\n                    |                    |  etcd-cluster-A-0002\n                 S  |                    |-------------> [ peer-interface SERVER CERT ]\n                 I  |\n                 G  |\n                 N  |\n                    |-------->  [ etcd-cluster-B peer interface CERTIFICATE AUTHORITY ]\n                    |                     |\n                    |                     |  etcd-cluster-B-0000\n                    |                     |------> ...\n                    |\n                    | ...\n```\n\n\n\n### Certificate signing procedure\n\n1. etcd-operator pod startup:\n  * generate `operator CA` private key\n  * generate `operator CA` certificate (peer and client) (select one of following)\n      * generate self-signed cert (default for now, useful for development mode)\n      * generate CSR, wait for external entity to sign it and return cert via Kubernetes API (production mode, allows integration with arbitrary external PKI systems)\n\n2. etcd cluster creation (in operator pod):\n  * generate private key\n  * generate `operator CA` as a subordinate CA of `cluster CA` using parameter from cluster spec\n\n3. etcd node pod startup (in the etcd pod, prior to etcd application starting):\n  * generate private key\n  * generate a CSR for `CN=etcd-cluster-xxxx`, submit for signing via annotation  (peer and client)\n\n4. etcd node enrollment (in operator pod) (peer and client)\n  * observe new CSR annotation on `pod/etcd-cluster-xxxx`\n  * sign CSR with the `cluster CA` for `pod/etcd-cluster-xxxx`\n  * --> return certificate via annotation to `pod/etcd-cluster-xxxx`\n\n5. etcd node startup (in etcd pod)\n  * observe new signed certificate in annotation on `pod/etcd-cluster-xxxx`  (peer and client)\n  * bring up etcd application with private key, peer cert, client cert, and `cluster CA` certificate\n\n### Signing Mechanisms\n\n#### Direct Sign (intra-component)\n\n```\n           [ signer ]\n               |\n               |\n        DIRECT | SIGN\n               |\n               |\n               -----> [ signee ]\n```\n\nIn the case that the _signer_ and _signee_ are within the same component, we have the _signer's_ private key material immediately available to produce a signed certificate for the _signee_. No need for CSR exchange.\n\n#### CSR/Cert exchange (inter-component)\n\n```\n           [ signer ]\n               |\n     /|\\ CERT  |\n      |   |    |\n      |   |    |\n     CSR \\|/   |\n               -----> [ signee ]\n```\n\n\nThis is a symbol for a _signee_ submitting a CSR to a _signer_, and receiving back a signed certificate back.\n\nIn the case of etcd-operator, this will be coordinated via the Kubernetes API server.\n\n-----\n\nHere are the steps:\n\n1. _signer_ schedules _signee_ pod to the Kubernetes cluster\n\n2. _signer_ sets up a watch on _signee_\n\n3. _singee_ sets up a watch on _signer_\n\n4. _signee_ generates a private key and then a CSR, containing desired metadata\n\n5. _signee_ annotates itself with `kubeEtcdCSR=<CSR-base64-bytes>`\n\n6. _singer_ sees `kubeEtcdCSR` annotation, verifies metadata, and generates a signed certificate from the incoming CSR\n\n7. _signer_ annotates _signee_ pod with `kubeEtcdCert=<cert-base64-bytes`\n\n8. _signee_ processes `kubeEtcdCert` annotation and writes incoming cert to file system\n\n9. _signee_ launches application\n\n_note: steps 2-9 can be repeated to implement a primitive cert refresh mechanism_\n\n------\n\n\nHere's a table showing how this process is currently used in the etcd operator TLS infrastructure:\n\n| _signer_      | signing CA     |  _singee_  | signed identities  | identity type |\n| ------------- | -------------- | ---------- | ----------------- | ------------- |\n| external PKI  | external CA    | operator | <ul><li>operator peer CA</li><li>operator client CA</li></ul> | CERTIFICATE AUTHORITY |\n| operator      | clusterA peer CA | etcd-xxxx | etcd-xxxx-peer-interface | SERVER CERTIFICATE |\n| operator      | clusterA client CA | etcd-xxxx | etcd-xxxx, client-interface | SERVER CERTIFICATE  |\n| operator      | clusterA client CA | clusterA-backup-sidecar | clusterA-backup-sidecar, client CA | CLIENT CERTIFICATE |\n\n## Things to note:\n* **Private Keys Stay Put:** If a private key is needed, is its generated on and never leaves the component that uses it. The business of shuffling around private key material across networks is a dangerous business.\n\n  Most importantly, the external PKI component must be allowed to sign the operator's CSR _without_ divulging it's CA private key to the cluster.\n\n* **Separate peer and client cert chains:** The motivation is to provide the ability to isolate the etcd peer (data) plane from the etcd client (control) plane.\n\n  The client interface CA will be expected to sign CSRs for any new entity that wants to \"talk to\" the cluster- this includes entirely external components like backup operators, load-balancers, etc.\n\n  The peer interface CA, on the other hand, will sign CSRs only for new entities that want to join the cluster.\n\n* **CSR attestation:** As of now, there has been discussion (but no planning done) towards providing a discrete mechanism for a  _signer_ to verify that an incoming CSR is actually from the claimed _signee_ before producing a certificate.\n\n  It's unclear what the role or scope of such a mechanism should be, in light of the fact that the CSR metadata is already tied to a Kubernetes object.\n\n  In theory, Kubernetes-provided isolation mechanisms alone should allow a _signer_ to:\n   * create a _signee_ pod\n   * observe an `kubeEtcdCSR` annotation on that _signee_ pod\n   * be guaranteed that the _signee_ pod itself annotated that CSR.\n\n\n\n"
  },
  {
    "path": "third_party/etcd-operator/doc/design/cluster_upgrade.md",
    "content": "# Cluster upgrade\n\n## etcd upgrade story\n\n- A user “kubectl apply” a new version in EtcdCluster object\n- etcd operator detects the version and\n  - if the targeted version is allowed, does rolling upgrade\n  - otherwise, rejects it in admission control; We will write an admission plug-in to verify EtcdCluster object.\n\n## Diagram\n![](./upgrade.jpg)\n\n## Rolling upgrade\n\n- We have an annotation key for the version of etcd cluster\n- During upgrade, we will list pods of this cluster, and differentiate them by two versions. Then do\n  - if num(old) + num(new) == total, try to update \"old\" pod to new version.\n  - otherwise, falls to normal reconcile path.\n\n## Support notes\n\n- Upgrade path: We only support one minor version upgrade, e.g. 3.0 -> 3.1, no 3.0 -> 3.2. Only support 3.0+\n- Rollback: We relies on etcd operator to do periodic backup.\n  For alpha release, we will provide features to do manual rollback.\n  In the future, we might consider support automatic rollback.\n\n\n## etcd upgrade policy\n\n- etcd supports rolling upgrade from one minor release version to its next minor release version. For example, we can directly upgrade etcd 3.0.7 to 3.1.0.\n- etcd supports rolling upgrade within one minor release. For example, we can upgrade etcd 3.0.1 to 3.0.7.\n- etcd supports minor version upgrade unconcerned with patch version, e.g. from 3.0.1 to 3.1.0. Nonetheless it's recommended to upgrade from 3.0.1 to 3.0.n (n is latest) and then from 3.0.n to 3.1.0.\n"
  },
  {
    "path": "third_party/etcd-operator/doc/design/disaster_recovery.md",
    "content": "# Disaster Recovery\n\n## Overview\n\nIf a cluster has less than majority of members alive, operator considers it disastrous failure. There might be other disastrous failures. Operator will do disaster recovery on such cases and try to recover entire cluster from snapshot.\n\nWe have a backup pod to save checkpoints of the cluster.\n\nIf disastrous failure happened but no checkpoint is found, operator would consider the cluster dead.\n\n## Technical details\n\nWe have a backup pod as sidecar:\n- We use Kubernetes replication set to manage the backup pod to achieve highly availability.\n- It periodically pull snapshots from the etcd cluster.\n- It persists the pulled snapshot into attached stable storage like Persistent Volume or cloud storage like GCS/S3.\n- It serves latest snapshot to etcd members for disaster recovery.\n\n## Disaster recovery process\n\nRecovery process of entire cluster:\n- If there is any running members, we first save snapshot of the member with the highest storage revision.\n  Then we kill all running members.\n- Restart the cluster as a one member cluster. The seed member will do recovery process described below.\n- Then the reconciliation will start to bring the etcd cluster back to the desired number of members.\n\nRecovery process of an etcd emember:\n- pull the latest snapshot from its backup pod, and use etcdctl recovery to prepare initial state.\n- start etcd process.\nNote that this could happen not only in disaster recovery, but also in partial recovery.\n\n## Architecture diagram\n![](./arch.png)"
  },
  {
    "path": "third_party/etcd-operator/doc/design/dynamic_tls.md",
    "content": "# Dynamic TLS Certs\n\nAuthors: Eric Chiang(eric.chiang@coreos.com), Hongchao Deng(hongchao.deng@coreos.com)\n\n## Background\n\nMotivations:\n- Simplify TLS cert generation for etcd cluster.\n- Self-hosted etcd wants to depend on Node IP, not hostnames.\n\nRequirements:\n- Dynamically generate certs per etcd pod\n- Able to use host IP in self hosted.\n\n\n## Proposed solution\n\n### Design\n\n> For initial design, we focus on self-hosted etcd use case, although the same methodology applies to app etcd.\n\n[Kubernetes certificates API][k8s_csr] provides the ability to send and approve CSR.\nEach etcd pod will request certs via CSR API based on its hostname/IP.\n\nThere is a [ongoing effort][auto_tls] on upstream to develop an auto-approver for self-hosted k8s components.\nWe can make use of that instead of creating our own.\n\nWorkflow:\n- etcd operator creates an etcd pod.\n  A service account that has access to CSR API should be assigned to each etcd pod.\n- etcd pod first runs an init container to send a CSR and wait for approval.\n- An external process should verify the CSR and approve it if correct.\n- Once approved, etcd pod gets the certs and bootstraps.\n\nPros:\n- Hooks into existing k8s.\n- Delegates CA signing cert management. Not touching the signing certs and keys directly.\n\nCons:\n- Share the same CA signing cert + key as k8s.\n- Requires etcd to be trusted by k8s cluster CA (probably only appropriate for self-hosted etcd).\n- Requires additional approver setup.\n\n\n\n### API Changes\n\nAdd DynamicTLS into existing TLSPolicy:\n\n```Go\ntype TLSPolicy struct {\n\t// DynamicTLS sets how to generate TLS certs dynamically.\n\tDynamic *DynamicTLS\n}\n\ntype DynamicTLS struct {\n  // EtcdPodServiceAccount is the service account used by each etcd pod to send CSR to APIServer.\n\tEtcdPodServiceAccount string\n}\n```\n\n### Implementation and testing plan\n\nWe will first implement self-hosted case, and then normal app case.\nBecause we will have self-hosted user scenario.\nFor self-hosted case, we will implement dynamic peer TLS first.\nThen dependence on hostnames should be gone and kubeadm can be unblocked in prototyping.\n\nImplementation plan:\n\n1. Change self-hosted etcd to use pod IP for server and peer URL.\n2. Implement dynamic peer TLS for self-hosted etcd.\n   We will still use static TLS for client, server certs initially.\n\nTODO: We focus on self-hosted use case initially. We will add more on normal app case later.\n\nTesting plan:\n\n- Once step 2 is finished, add a test for self-hosted case.\n\n\n## Alternatives\n\n### Option 2: CA signing cert + key, etcd operator generates certs\n\netcd operator generates certs for a new member and puts them into a secret.\nThen etcd operator creates an etcd pod mounted with the secret.\n\nWorkflow:\n- CA signing cert + key are provided by user in a secret.\n- Before creating etcd pod, etcd operator generates etcd server + peer certs, stores the certs in a secret.\n  When creating etcd pod, the TLS secret is mounted as a volume.\n\nPros:\n- Each etcd cluster has its own CA.\n\nCons:\n- Hard for self-hosted etcd because the etcd-operator doesn't schedule pods directly onto nodes,\n  so it doesn't know what serving address to sign ahead of time.\n  This might be good for application etcd which uses hostnames known for each member.\n\n\n## Appendix\n\n- [Support using Kubernetes CA for certificates](https://github.com/coreos/etcd-operator/issues/1465)\n- [Allow members to advertise using IPs ](https://github.com/coreos/etcd-operator/issues/1617)\n- [etcd: Require a specific cert CN from peer client certificate](https://github.com/coreos/etcd/issues/8262)\n- [bootkube: auto-approval for kubelet](https://github.com/kubernetes-incubator/bootkube/pull/663)\n\n\n\n[k8s_csr]:https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/#requesting-a-certificate\n[auto_tls]:https://docs.google.com/document/d/1POXVGyEoySvSnx_OftQ2CIWM0HCk27j2VZSOR4XVCDg/edit#heading=h.e742mn9kyevr"
  },
  {
    "path": "third_party/etcd-operator/doc/design/gcs_backup.md",
    "content": "# Backups using Google Cloud Storage (GCS)\n\n## Cluster configured with GCS backup\n\nTo create a cluster with backups to GCS, set `backup.storageType` to `\"GCS\"`, supply the path (in the format \"<gcs-bucket-name>/<path-to-backup-object>\") in `gcs.path` and provide the Kubernetes secret storing the Google Cloud Platform account credentials to `gcs.gcpSecret`.  The bucket and secret must exist prior to backup creation.\n\nAn example cluster manifest would look like:\n\n```bash\napiVersion: etcd.database.coreos.com/v1beta2\nkind: EtcdCluster\nmetadata:\n  name: etcd-cluster-with-gcs-backup\nspec:\n  ...\n  backup:\n    ...\n    storageType: GCS\n    gcs:\n      path: my-etcd-backups-bucket/my-etcd-backup-object\n      gcpSecret: gcp-credentials\n\n``` \n\n### In Detail:\n\n- `\"gcpSecret\"` represents the name of the Kubernetes secret object that stores the credentials needed for GCP authorization, namely an authorization token or JSON credentials.\n\n  The Kubernetes secret manifest looks like either:\n  ```yaml\n  apiVersion: v1\n  kind: Secret\n  metadata:\n    name: gcp-credentials\n  type: Opaque\n  stringData:\n    access-token: <token>\n  ```\n\n  Or:\n  ```yaml\n  apiVersion: v1\n  kind: Secret\n  metadata:\n    name: gcp-credentials\n  type: Opaque\n  stringData:\n    credentials.json: <JSON-credentials>\n  ```\n\n  Example of the latter:\n\n  ```bash\n  # create account\n  BACKUP_ACCOUNT='backup-creator'\n  BACKUP_ACCOUNT_EMAIL=\"${BACKUP_ACCOUNT}@$(gcloud config get-value project).iam.gserviceaccount.com\"\n  gcloud iam service-accounts create \"$BACKUP_ACCOUNT\" --display-name='Backup creator service account'\n\n  # set permissions\n  BACKUP_BUCKET='my-etcd-backups-bucket'\n  gsutil mb \"$BACKUP_BUCKET\"\n  gsutil iam ch \"serviceAccount:${BACKUP_ACCOUNT_EMAIL}:objectCreator\" \"$BACKUP_BUCKET\"\n\n  # create secret\n  kubectl create secret generic gcp-credentials \\\n      --from-literal=\"credentials.json=$(gcloud iam service-accounts keys create - --iam-account=\"$BACKUP_ACCOUNT_EMAIL\")\"\n  ```\n"
  },
  {
    "path": "third_party/etcd-operator/doc/design/operator_recovery.md",
    "content": "# Operator recovery\n\n- Create TPR\n - If the creation succeed, then the operator is a new one and does not require recovery. END.\n- Find all existing clusters\n - loop over the third part resource items to get all created clusters\n- Reconstruct clusters\n - for each cluster, find running pods that belong to it by label selection\n - recover the membership by issuing member list call\n - recover nextID by finding the etcd member with the largest ID in its name\n"
  },
  {
    "path": "third_party/etcd-operator/doc/design/oss_backup.md",
    "content": "# Backups using Alibaba Cloud Object Storage Service (OSS)\n\n## Cluster configured with OSS backup\n\nTo create a backup in OSS, set `backup.storageType` to `\"OSS\"`, supply the path (in the format `<oss-bucket-name>/<path-to-backup-object>`) in `oss.path` and provide the Kubernetes secret storing the Alibaba Cloud account credentials to `oss.ossSecret`.  The secret must exist prior to backup creation. Etcd backup operator will create the bucket and object if not found. The field `oss.endpoint` is the target OSS service endpoint where the data is backed up. By default, `http://oss-cn-hangzhou.aliyuncs.com` will be used. If you want to back up the data to other regions, please specify another endpoint from [the list of region endpoints](https://www.alibabacloud.com/help/doc-detail/31837.htm).\n\n\nAn example backup manifest would look like:\n\n```yaml\napiVersion: etcd.database.coreos.com/v1beta2\nkind: EtcdBackup\nmetadata:\n  name: etcd-cluster-with-oss-backup\n  namespace: my-namespace\nspec:\n  backupPolicy:\n    ...\n  etcdEndpoints:\n    - \"http://example-etcd-cluster-client:2379\"\n  storageType: OSS\n  oss:\n    endpoint: http://oss-cn-hangzhou.aliyuncs.com\n    ossSecret: my-oss-credentials\n    path: my-etcd-backups-bucket/etcd.backup\n```\n\n### In Detail:\n\n- `\"ossSecret\"` represents the name of the Kubernetes secret object that stores the credentials needed for Alibaba Cloud authorization, namely an authorization token.\n\n  The Kubernetes secret manifest must have the following format:\n  ```yaml\n  apiVersion: v1\n  kind: Secret\n  metadata:\n    name: my-oss-credentials\n  type: Opaque\n  data:\n    accessKeyID: <my-access-key-id>\n    accessKeySecret: <my-access-key-secret>\n ```\n"
  },
  {
    "path": "third_party/etcd-operator/doc/design/persistent_volumes_etcd_data.md",
    "content": "# Use Persistent Volumes for etcd data\n\n## Proposal and Motivation\n\nToday etcd-operator creates ephemeral etcd members: in their pods the etcd data is stored inside a volume of type emptyDir and the pod restart policy is set to `Never`.\nThis has the following failure cases.\n\n### Failure cases\n\nAssume a N members etcd cluster with all members healthy\n\n#### Case A\n\n##### Event\n\nOne of these events happens:\n* one etcd member process exits (processes crashes, killed etc...)\n* a k8s node executing one etcd member pod reboots and comes back before node controller pod eviction triggers\n\n##### Effect\n\nThe pod will go in failed state, the etcd cluster remains quorate. Etcd-operator will remove the member from the etcd cluster and add a new member to the cluster and creates a new pod with a new name.\n\n#### Case B\n\n##### Event\n\n* a k8s node executing one etcd member pod becomes partitioned (network partitioning, goes down, etc...) and cannot talk to the api server, after some time the node controller will evict its pods.\n\n##### Effect\n\nThe pod will go in an unknown/failed state, the etcd cluster remains quorate. Etcd-operator will remove the member from the etcd cluster and add a new member to the cluster and creates a new pod with a new name.\n\n#### Case C\n\n##### Event\n\nOne of these events happens:\n* a majority of etcd processes exits (processes crashes, killed etc...) \n* k8s nodes scheduling a majority of etcd members pods reboots and come back before node controller pod eviction triggers\n\n##### Effect\n\nThe pods will go in failed state, the etcd cluster becomes unquorate. Etcd-operator can only restore the cluster from a backup.\n\n#### Case D\n\n##### Event\n\n* k8s nodes executing a majority of etcd members pods becomes partitioned (network partitioning, goes down, etc...) and cannot talk to the api server, after some time the node controller will evict their pods.\n\n##### Effect\n\nThe pods will go in an unknown/failed state and eventually be removed from the API server, the etcd cluster becomes unquorate. Etcd-operator can only restore the cluster from a backup.\n\n\n### Current failure handling\n\nCurrently etcd operator handles cases A and B but when a cluster becomes unquorate (cases C and D) the current option is to restore the cluster from a backup.\n\nUser may desire consistency over availability and prefer to wait for the cluster the return in a quorate state instead of restoring from a backup (that will contain old data).\n\nThis proposal aims to fix cases C and D permitting to the cluster the return in a quorate state without the need to restore from a backup.\n\n## Proposed Changes\n\nThe design to be effective is split in two parts.\n\n### Part 1\n\nThese changes will put the basis for initial persistent volume management\n\nThis first part won't fix case C and D.\n\n- Add to the cluster spec PodPolicy an option to enable putting etcd data inside a Persistent Volume\n- If podPolicy has persistent volumes enabled, when creating a new member also create a Persistent Volume Claim and use it as the volume source for etcd-data\n- Handle etcd data persistent volume claims cleanup:\n  - set PVC ownerRef to EtcdCluster object, which enables GC to clean up if cluster is deleted.\n  - PVC lifecycle is bound to etcd member's lifecycle. PVC is added/removed when etcd member is added/removed (in the implementation we could choose to remove PVC only if there's not pod referencing them to avoid strange behaviors)\n\n#### Pod name to Persistent Volume Claim name mapping\n\nThe pod and related PVC are mapped 1 to 1 so their names be easily generated and deducted. I.E. if the pod is called `etcd-0000` its related PVC name will be `etcd-0000-pvc`\n\n\n### Part 2\n\nUsing persistent volumes to store etcd data will add additional failure cases:\n\n- volume failure (failing to bind PV to pod).\n- corrupted data (filesystem ok but missing/corrupted files) that will cause etcd to exit. Previously an etcd member with corrupted data will be deleted and a new member added, using a persistent volume we have to avoid reusing the same corrupted data volume.\n\nThis parts will fix cases C and D and the above corrupted data case.\n\nIt's a change to the reconcile logic to handle deleted pods from the k8s API server that had a persistent volume. To handle corrupted data failures, the reconcile logic change defined below will be used only if the cluster is unquorate. Instead, if the cluster is quorate, the current logic of deleting the member and adding a new member will be used.\n\n- If the cluster is unquorate and a pod of an etcd cluster member is deleted from the API server and it had a persistent volume claim associated, instead of removing the etcd member from the etcd cluster and adding a new member just recreate it (keeping its pod name) binding the existing persistent volume claim. The pod recreation will happen only if the pod doesn't exists anymore in the API because we'll keep the same pod name. This also enable a MANDATORY property: at most once pod existence logic to avoid having in the API at the same time two pods with associated the same PVC.\n\n\n### Future enhancements\n\nHandle failures introduced by this design and not covered with the previous parts:\n\n- volume failure (failing to bind PV to pod).\n\n\n\n## Related issues\n\n- [Explore Local PV](https://github.com/coreos/etcd-operator/issues/1201)\n- [Persistent/Durable etcd cluster](https://github.com/coreos/etcd-operator/issues/1323)\n- [Pod Safety, Consistency Guarantees, and Storage Implications](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/pod-safety.md)\n"
  },
  {
    "path": "third_party/etcd-operator/doc/design/reconciliation.md",
    "content": "# Cluster Membership Reconciliation\n\n## Reconciliation\n\nGiven a desired size S, we have two membership states:\n- running pods P in k8s cluster\n- membership M in operator knowledge\n\nReconciliation is the process to make these two states consistent with the desired size S.\n\nFor each reconciling cycle, we get P from k8s API. Comparing M and P, we have the following steps:\n\n1. Remove all pods from set P that does not belong to set M\n2. P’ consist of remaining pods of P\n3. If P’ = M, the current state matches the membership state. GOTO Resize.\n4. If len(P’) < len(M)/2 + 1, quorum lost. Go to recovery process (TODO).\n5. Remove one member that in M but does not in P's. GOTO Resize.\n\n### Resize\n\nGiven a desired size S, membership M and current running pods P:\n\n1. If len(P) != len(M), then END.\n2. If S = len(M), then END.\n3. If S > len(M), add one member. END.\n4. If S < len(M), remove one member. END\n"
  },
  {
    "path": "third_party/etcd-operator/doc/design/resource_ownership_and_GC.md",
    "content": "# Resource Ownership and GC\n\n## Resource Ownership\n\nAn etcd cluster creates and manages pods, services and replica set. Those resources are owned by the cluster.\nTwo cluster owns completely disjoint set of resources, even if they have the same name.\nFor example, etcd cluster \"A\" was deleted and later etcd cluster \"A\" was created again; we think these are two different clusters.\nThus, the new cluster should not mange the resources from the old one. The old resources should be treated as garbage and to be collected.\n\nAs discussed in https://github.com/coreos/etcd-operator/issues/517,\nwe correlate owner (i.e. cluster) and its resources by making use of `ObjectMeta.OwnerReferences` field.\n\nFor etcd pods and services, they will have only one owner -- its managing cluster.\n\n## GC\n\nGithub issue: https://github.com/coreos/etcd-operator/issues/518\n\nWe will talk about two strategies to do GC in the following.\nWe are only covering etcd pods, services, although the algorithm applies to more resources.\n\n### Lazy deletion\n\nWe should remove resources when deleting or creating a cluster.\nWe remove them via label convention:\n- remove pods with selector label{\"etcd_cluster\": $cluster_name, \"app\": \"etcd\"}\n- remove services with selector label{\"etcd_cluster\": $cluster_name}\n\nAs a side note on creating a cluster:\nRight before creating a cluster, if a pod or svc was selected out, then it must hangs around as garbage.\nThis could lead to confusing, even harmful cases.\nSo we must delete all related garbage resources before we start the new cluster.\n\n\n### Periodic full GC\n\nEvery interval (10 mins or so), we find out orphaned pods/svcs.\n\nInitially, our use case would be O(10) clusters, and thus total selected items would be at most O(100).\n\nA simple full scanning algorithm:\n- List pods, services.\n- Controller have the knowledge of etcd clusters.\n- Find out pods, services whose OwnerRef-ed cluster doesn't exist in controller knowledge.\n"
  },
  {
    "path": "third_party/etcd-operator/doc/design/restore_operator.md",
    "content": "# Restore Operator Design\n\nRestore operator restores an etcd cluster from existing backup.\n\n## General design\n\nThe new design will assume EtcdCluster have three phases:\n\n- **Creating**: etcd operator will create a seed member.\n- **Running**: etcd operator will keep reconciling cluster membership, \n  actual running pods, and desired size.\n- **Failed**: Encountered unrecoverable failure, e.g. lose majority of the cluster.\n\nFor this design, restore operator is going to restore an etcd seed member that\netcd operator understands. etcd operator will skip Creating phase and jump directly\ninto Running phase.\n\n## Restore operator API\n\nRestore operator API will be exposed as CRD:\n\n```yaml\napiVersion: apiextentions.k8s.io/v1beta2\nkind: CustomResourceDefiniton\nmetadata:\n  name: etcdrestores.etcd.database.coreos.com\nspec:\n  group: etcd.database.coreos.com\n  version: v1beta2\n  Scope: Namespaced\n  names: \n    kind: EtcdRestore\n    plural: etcdrestores\n```\n\nRestore Spec defined as:\n\n```Go\n// RestoreSpec defines how to restore an etcd cluster from existing backup.\ntype RestoreSpec struct {\n\t// EtcdCluster defines the same spec that etcd operator will run later.\n\t// Using this spec, restore operator will prepare the seed that\n\t// etcd operator will pick up later.\n\tEtcdCluster ClusterSpec\n\t// EtcdBackup defines the same spec that backup operator uses to save the backup.\n\t// Restore operator will have the same logic as backup operator to discover\n\t// any existing backups and find the one with largest revision.\n\tEtcdBackup EtcdBackupSpec\n}\n\n\n// RestoreStatus reports the status of this restore operation.\ntype RestoreStatus struct {\n\t// Succeeded indicates if the restore has Succeeded.\n\tSucceeded bool\n\t// Reason indicates the reason for any restore related failures.\n\tReason string\n}\n```\n"
  },
  {
    "path": "third_party/etcd-operator/doc/design/s3_backup.md",
    "content": "# Store Backup in S3\n\nWe want to have an option to store backup in S3.\n\n## Flags of etcd operator\n\nWhen staring etcd operator, we need to provide flags in order to access aws:\n```bash\n$ etcd-operator --backup-aws-secret ${secret_name} --backup-aws-config ${configmap_name} --backup-s3-bucket ${bucket_name} ...\n```\n\nLet's explain them one by one:\n- \"backup-aws-secret\" takes the name of the kube secret object that stores the aws credential file.\n\nWe can create a secret object by doing:\n```bash\n$ kubectl create secret generic aws-credential --from-file=${aws_credential_file}\n```\n\"aws-credential\" is the ${secret_name}.\nThe \"aws_credential_file\" file is documented [here](http://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html#aws-credentials-file-format).\nWe only use \"default\" profile.\nAn example credential file:\n```\n[default]\naws_access_key_id=AKIAIOSFODNN7EXAMPLE\naws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\n```\n\n- \"backup-aws-config\" takes the name of the kube configmap object that presents the aws config file.\n\nWe can create a configmap by doing:\n```bash\n$ kubectl create configmap aws-config --from-file=${aws_config_file}\n```\n\"aws-config\" is the ${configmap_name}.\nThe \"aws_config_file\" file is described [here](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-config-files).\nWe only use \"default\" profile. Note that \"region\" must be set.\nAn example config file:\n```\n[default]\nregion=us-west-1\n```\n\n- \"backup-s3-bucket\" takes the name of the s3 bucket in which the operator stores backup.\nThe backups of each cluster are saved in individual directories under given bucket.\nThe format would look like: *bucket_name/cluster_name/* .\n\nFor example, given bucket \"etcd-backups\" and if operator has saved backups of cluster \"etcd-A\", we should see backup files running commands:\n```bash\n$ aws s3 ls s3://etcd-backups/etcd-A/\n```\nOr just login into aws console to view it.\n\n## How to create a cluster with backup in S3\n\nWhen we create a cluster with backup, we set the backup.storageType to \"S3\".\nFor example, a yaml file would look like:\n```\napiVersion: \"etcd.coreos.com/v1beta1\"\nkind: \"Cluster\"\nmetadata:\n  name: \"etcd-cluster-with-backup\"\nspec:\n  ...\n  backup:\n    ...\n    storageType: \"S3\"\n``` \n"
  },
  {
    "path": "third_party/etcd-operator/doc/dev/debug_e2e_flake.md",
    "content": "# Debug E2E Test Flake\n\nE2E flakes will cost more and more effort and bring more and more trouble as time passes by.\nIt is better to solve them as early as possible.\n\nRules when a flake happened:\n\n- Do not hide the failure.\n  If test flake happened, don't just rerun the test.\n  Comment or create an issue to track the problem.\n- Figure out why the failure happened.\n  The end goal should be either a code fix or some docs explaining the limitatons.\n\n## How to debug\n\nFiguring out the root cause of failures is usually easier and less time-consuming than it's assumed to.\n\nHere is one process to help start the debugging process:\n\n- Have a automated script to reproduce the test consistently. For example, a script to run locally:\n  ```shell\n  go test -c ./test/e2e\n  for ((n=0;n<30;n++))\n  do\n  echo \"${n} round...\"\n  ./e2e.test --kubeconfig=${HOME}/.kube/config \\\n      --operator-image=${IMAGE} \\\n      --test.run=${TEST_SELECTOR}\n  sleep 15 # LE lock expiration\n  done\n  ```\n  Note that there might be additional setup before running the test.\n- Narrow down the root cause.\n  In this phase, observability is the key. Add more logs, metrics.\n- Once a bug is hunt down, follow up on the issue with detailed report.\n"
  },
  {
    "path": "third_party/etcd-operator/doc/dev/developer_guide.md",
    "content": "# Developer guide\n\nThis document explains how to setup your dev environment. \n\n## Fetch dependency\n\nWe use [dep](https://github.com/golang/dep) to manage dependency.\nInstall dependency if you haven't:\n\n```\n./hack/update_vendor.sh\n```\n\n## How to build\n\nRequirement:\n- Go 1.10+\n\nBuild in project root dir:\n\n```\n./hack/build/operator/build\n./hack/build/backup-operator/build\n./hack/build/restore-operator/build\n```\n"
  },
  {
    "path": "third_party/etcd-operator/doc/dev/release.md",
    "content": "# Release Workflow\n\n**NOTE**: During release, don't merge any PR other than bumping the version.\n\nLet's say we are releasing $VERSION (e.g. `v1.2.3`) .\n\n## Create git tag\n\n- Bump up version (e.g. 0.8.0 -> 0.8.1):\n  ```bash\n  ./hack/release/bump_version.sh 0.8.0 0.8.1\n  ```\n\n- Update CHANGELOG.md.\n\n- Send a PR. After it's merged, cut a tag:\n\n  ```bash\n  git tag $VERSION\n  git push ${upstream_remote} tags/$VERSION\n  ```\n\n\n## Push Image to Quay\n\n- Login to quay.io using docker if haven't:\n\n  ```bash\n  docker login quay.io\n  ```\n\nFollow the prompts.\n\n- git checkout tag (created above)\n\n- Follow [developer_guide.md](./developer_guide.md) for build instructions.\n\n- After build, push image:\n\n```bash\n$ IMAGE=quay.io/coreos/etcd-operator:$VERSION hack/build/docker_push\n```\n\n- Retag \"latest\":\n\n```bash\n$ docker tag quay.io/coreos/etcd-operator:$VERSION quay.io/coreos/etcd-operator:latest\n$ docker push quay.io/coreos/etcd-operator:latest\n```\n\n## Github release\n\n- Click \"releases\" in the top bar.\n\n- Click \"$VERSION\" tag.\n\n- Click \"Edit Tag\".\n\n- Fill in title and release notes.\n\n- If it's not stable release, click \"This is a pre-release\".\n\n## Bump version\n\nIn version/version.go, bump version again:\n\n```go\n\t// Version = \"0.2.2+git\" (without \"v\" prefix) \n\tVersion = \"$VERSION+git\"\n```\n\nSend another PR and merge it.\n"
  },
  {
    "path": "third_party/etcd-operator/doc/user/abs_backup.md",
    "content": "# Backups using Azure Blob Service (ABS)\n\nEtcd backup operator backups the data of an etcd cluster running on Kubernetes to a remote storage such as Azure Blob Service (ABS). If it is not deployed yet, please follow [here](walkthrough/backup-operator.md#deploy-etcd-backup-operator) to deploy it, e.g. by running\n\n```sh\nkubectl apply -f example/etcd-backup-operator/deployment.yaml\n```\n\n## Setup Azure Secret\n\nCreate a secret file `abs-secret.yaml`:\n\n```yaml\napiVersion: v1\nkind: Secret\nmetadata:\n  name: abs-credentials\n  namespace: etcd\ntype: Opaque\nstringData:\n  storage-account: \"<storage-account>\"\n  storage-key: \"<storage-key>\"\n  cloud: \"<cloud>\"\n```\n\nIn above secret, following data should be provided:\n\n- `storage-account`: the name of Azure storage account.\n- `storage-key`: the storage key of storage account.\n- `cloud`: the name of cloud environment, e.g. `AzurePublicCloud` or `AzureChinaCloud`. Optional. If not specified, it is defaulted to `AzurePublicCloud`.\n\nAnd then create the secret:\n\n```sh\nkubectl apply -f abs-secret.yaml\n```\n\n## Create EtcdBackup CR\n\nFirst, create a container in the storage account:\n\n```sh\naz storage container create -n etcd-backups --account-name <storage-account> --account-key <storage-key>\n```\n\nThen create a `EtcdBackup` CR file `etcdbackup.yaml` which uses secret `abs-credentials`:\n\n```yaml\napiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdBackup\"\nmetadata:\n  name: example-etcd-cluster-backup\n  namespace: etcd\nspec:\n  etcdEndpoints: [\"http://example-etcd-cluster-client:2379\"]\n  storageType: ABS\n  abs:\n    # The format of the path must be: \"<abs-container-name>/<path-to-backup-file>\"\n    path: etcd-backups/etcd.backup\n    absSecret: abs-credentials\n```\n\nFinally apply it to kubernetes cluster:\n\n```sh\nkubectl apply -f etcdbackup.yaml\n```\n\nCheck the `status` section of the `EtcdBackup` CR:\n\n```sh\n$ kubectl get EtcdBackup example-etcd-cluster-backup -o yaml\napiVersion: etcd.database.coreos.com/v1beta2\nkind: EtcdBackup\n...\nspec:\n  abs:\n    absSecret: abs-credentials\n    path: etcd-backups/etcd.backup\n  etcdEndpoints:\n  - http://example-etcd-cluster-client:2379\n  storageType: ABS\nstatus:\n  etcdRevision: 1\n  etcdVersion: 3.2.13\n  succeeded: true\n\n```\n\nWe should see the backup files after running the following command:\n\n```bash\n$ az storage blob list -c etcd-backups --account-name <storage-account> --account-key <storage-key>\nName         Blob Type    Blob Tier      Length  Content Type              Last Modified              Snapshot\n-----------  -----------  -----------  --------  ------------------------  -------------------------  ----------\netcd.backup  BlockBlob                    24608  application/octet-stream  2018-08-13T05:42:03+00:00\n```\n\nAlternatively, you can also login into the Azure Portal to view these backups.\n\n## Create EtcdRestore CR\n\nEtcd restore operator is in charge of restoring etcd cluster from backup. If it is not deployed, please deploy by following command:\n\n```yaml\nkubectl apply -f example/etcd-restore-operator/deployment.yaml\n```\n\nNow kill all the etcd pods to simulate disaster failure:\n\n```sh\nkubectl delete pod -l app=etcd,etcd_cluster=example-etcd-cluster --force --grace-period=0\n```\n\nCreate EtcdRestore CR:\n\n```yaml\napiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdRestore\"\nmetadata:\n  # The restore CR name must be the same as spec.etcdCluster.name\n  name: example-etcd-cluster\nspec:\n  etcdCluster:\n    # The namespace is the same as this EtcdRestore CR\n    name: example-etcd-cluster\n  backupStorageType: ABS\n  abs:\n    # The format of the path must be: \"<abs-container-name>/<path-to-backup-file>\"\n    path: etcd-backups/etcd.backup\n    absSecret: abs-credentials\n```\n\nCheck the `status` section of the `EtcdRestore` CR:\n\n```sh\n$ kubectl get etcdrestore example-etcd-cluster -o yaml\napiVersion: etcd.database.coreos.com/v1beta2\nkind: EtcdRestore\n...\nspec:\n  abs:\n    absSecret: abs-credentials\n    path: etcd-backups/etcd.backup\n  backupStorageType: ABS\n  etcdCluster:\n    name: example-etcd-cluster\nstatus:\n  succeeded: true\n```\n\nVerify the `EtcdCluster` CR and restored pods for the restored cluster:\n\n```sh\n$ kubectl get etcdcluster\nNAME                   AGE\nexample-etcd-cluster   1m\n\n$ kubectl get pods -l app=etcd,etcd_cluster=example-etcd-cluster\nNAME                                     READY     STATUS    RESTARTS   AGE\nexample-etcd-cluster-795649v9kq          1/1       Running   1          3m\nexample-etcd-cluster-jtp447ggnq          1/1       Running   1          4m\nexample-etcd-cluster-psw7sf2hhr          1/1       Running   1          4m\n```\n"
  },
  {
    "path": "third_party/etcd-operator/doc/user/backup_cronjob/README.md",
    "content": "# Periodic etcd Backup using CronJob\n\nThis doc talks about how to use Kubernetes [CronJob][k8s_cronjob] to make periodic etcd backups.\n\nPrerequisites:\n\n- Kubernetes cluster and kubectl ready\n- etcd-operator, etcd-backup-operator deployed\n- `example-etcd-cluster` EtcdCluster CR is created and the cluster is running\n\nAll commands assume the current working directory to be the root directory of etcd-operator repo.\nWe are also following the example configurations in [backup-operator walkthrough][backup-operator-walkthrough].\n\n\n## Backup ConfigMap\n\nFirst we create a [ConfigMap](./configmap.yaml) containing the Backup CR template for the CronJob container to mount and reuse it.\n\n```\nkubectl create -f ./doc/user/backup_cronjob/configmap.yaml\n```\n\n## Backup CronJob\n\nThen we create a [CronJob](./cronjob.yaml) which every 30 minutes would make a backup with name suffixed with the current timestamp.\n\n```\nkubectl create -f ./doc/user/backup_cronjob/cronjob.yaml\n```\n\nThis example has the following limitations:\n\n- **Backups and EtcdBackup CRs will keep being created**. Clean up/GC old resources properly.\n- The CronJob pods use \"default\" namespace service account.\n  In production case, replace it with a dedicated service account and restrict the permissions via RBAC.\n\n\n[k8s_cronjob]:https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/\n[backup-operator-walkthrough]:../walkthrough/backup-operator.md"
  },
  {
    "path": "third_party/etcd-operator/doc/user/backup_cronjob/configmap.yaml",
    "content": "apiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: backup-config\ndata:\n  backup_cr.yaml: |\n    apiVersion: \"etcd.database.coreos.com/v1beta2\"\n    kind: \"EtcdBackup\"\n    metadata:\n      generateName: example-etcd-backup-\n    spec:\n      etcdEndpoints: [\"http://example-etcd-cluster-client:2379\"]\n      storageType: S3\n      s3:\n        path: mybucket/etcd.backup.<NOW>\n        awsSecret: aws\n"
  },
  {
    "path": "third_party/etcd-operator/doc/user/backup_cronjob/cronjob.yaml",
    "content": "apiVersion: batch/v1beta1\nkind: CronJob\nmetadata:\n  name: etcd-backup\nspec:\n  schedule: \"*/30 * * * *\"\n  jobTemplate:\n    spec:\n      template:\n        spec:\n          containers:\n          - name: etcd-backup\n            image: lachlanevenson/k8s-kubectl\n            command:\n            - /bin/sh\n            - \"-ec\"\n            - |\n              sed -e \"s|<NOW>|$(date '+%Y-%m-%d_%H:%M:%S')|g\" /var/etcd_backup/backup_cr.yaml | kubectl create -f -\n            volumeMounts:\n            - name: backup-config\n              mountPath: /var/etcd_backup\n          restartPolicy: OnFailure\n          volumes:\n          - name: backup-config\n            configMap:\n              name: backup-config\n"
  },
  {
    "path": "third_party/etcd-operator/doc/user/client_service.md",
    "content": "# etcd client service\n\nFor every etcd cluster created, the etcd operator will create an etcd client service in the same namespace with the name `<cluster-name>-client`.\n\n```\n$ kubectl create -f example/example-etcd-cluster.yaml\n$ kubectl get services\nNAME                          CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE\nexample-etcd-cluster          None           <none>        2380/TCP   1m\nexample-etcd-cluster-client   10.0.222.115   <none>        2379/TCP   1m\n```\n\nThe client service is of type `ClusterIP` and accessible only from within the Kubernetes overlay network.\n\nFor example, access the service from a pod in the cluster:\n\n```\n$ kubectl run --rm -i --tty fun --image quay.io/coreos/etcd --restart=Never -- /bin/sh\n/ # ETCDCTL_API=3 etcdctl --endpoints http://example-etcd-cluster-client:2379 put foo bar\nOK\n(ctrl-D to exit)\n```\n\nIf accessing this service from a different namespace than that of the etcd cluster, use the fully qualified domain name (FQDN) `http://<cluster-name>-client.<cluster-namespace>.svc.cluster.local:2379`.\n\n## Accessing the service from outside the cluster\n\nTo access the client API of the etcd cluster from outside the Kubernetes cluster, expose a new client service of type `LoadBalancer`. If using a cloud provider like GKE/GCE or AWS, setting the type to `LoadBalancer` will automatically create the load balancer with a publicly accessible IP.\n\nThe spec for this service will use the label selector `etcd_cluster: <cluster-name>` to load balance the client requests over the etcd pods in the cluster.\n\nFor example, create a service for the cluster described above:\n\n```\n$ cat example-etcd-client-service-lb.yaml\napiVersion: v1\nkind: Service\nmetadata:\n  name: example-etcd-client-service-lb\n  namespace: default\nspec:\n  ports:\n  - name: client\n    port: 2379\n    protocol: TCP\n    targetPort: 2379\n  selector:\n    etcd_cluster: example-etcd-cluster\n  type: LoadBalancer\n\n$ kubectl create -f example-etcd-client-service-lb.yaml\n```\n\nWait until the load balancer is created and the service is assigned an `EXTERNAL-IP`:\n\n```\n$ kubectl get services\nNAME                             CLUSTER-IP     EXTERNAL-IP     PORT(S)          AGE\nexample-etcd-cluster             None           <none>          2380/TCP         5m\nexample-etcd-cluster-client      10.0.222.115   <none>          2379/TCP         5m\nexample-etcd-cluster-client-lb   10.0.176.134   35.184.74.127   2379:32478/TCP   1m\n```\n\nThe etcd client API should now be accessible from outside the Kubernetes cluster:\n\n```\n$ ETCDCTL_API=3 etcdctl --endpoints http://35.184.74.127:2379 get foo\nfoo\nbar\n```\n"
  },
  {
    "path": "third_party/etcd-operator/doc/user/cluster_tls.md",
    "content": "# Cluster TLS policy\n\nCluster TLS policy is configured on a per-cluster basis through the CR spec provided to etcd operator.\n\nFor etcd's TLS support and requirements, see the [etcd security model][etcd-security].\nTo learn about generating self-signed TLS certs, see [Generate self-signed certificates][self-signed].\n\n## Static cluster TLS policy\n\nStatic TLS means keys/certs are generated by the user and passed to an operator.\n\nThis section will use the following YAML manifest to describe the spec. The example cluster manifest and certs can be found in the [example/tls/ directory][example-tls].\n\n```yaml\napiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdCluster\"\nmetadata:\n  name: example\n  namespace: default\nspec:\n  ...\n  TLS:\n    static:\n      member:\n        peerSecret: etcd-peer-tls\n        serverSecret: etcd-server-tls\n      operatorSecret: etcd-client-tls\n```\n\n### member.peerSecret\n\n`member.peerSecret` contains pem-encoded private keys and x509 certificates for etcd peer communication.\n\nThe peer TLS assets should have the following:\n- **peer.crt**: peer communication cert.\n  The certificate should allow wildcard domain `*.${clusterName}.${namespace}.svc` and `*.${clusterName}.${namespace}.svc.${cluster_domain}`.\n  The example shown above uses `*.example.default.svc` and `*.example.default.svc.cluster.local`.\n- **peer.key**: peer communication key.\n- **peer-ca.crt**: CA cert for this peer key-cert pair.\n\nCreate a secret using the `peer.key`, `peer.crt`, and `peer-ca.crt`:\n\n```\n$ kubectl create secret generic etcd-peer-tls --from-file=peer-ca.crt --from-file=peer.crt --from-file=peer.key\n```\n\nOnce passed, etcd operator will mount this secret at `/etc/etcdtls/member/peer-tls/` for each etcd member pod in the cluster.\n\n### member.serverSecret\n\n`member.serverSecret` contains pem-encoded private keys and x509 certificates for etcd client communication on server side.\n\nThe client TLS assets should have the following:\n- **server.crt**: etcd server's client communication cert.\n  The certificate should allow wildcard domain `*.${clusterName}.${namespace}.svc`,\n  `${clusterName}-client.${namespace}.svc`, and `localhost`.\n  The example shown above uses `*.example.default.svc`, `example-client.default.svc`, and `localhost`.\n  To use more DNS name or IP to access etcd server, please add it here.\n- **server.key**: etcd server's client communication key.\n- **server-ca.crt**: CA cert for validating the certs of etcd clients.\n\nCreate a secret using `server.key`, `server.crt`, and `server-ca.crt`:\n\n```\n$ kubectl create secret generic etcd-server-tls --from-file=server-ca.crt --from-file=server.crt --from-file=server.key\n```\n\netcd operator will mount this secret at `/etc/etcdtls/member/server-tls/` for each etcd member pod in the cluster.\n\n### operatorSecret\n\nThe operator must send client requests (such as snapshot, healthy check, add/remove member) to maintain this cluster.\n\n`operatorSecret` contains pem-encoded private keys and x509 certificates for communicating with etcd server via client URL.\n\nThe operator's etcd TLS assets should have the following:\n- **etcd-client.crt**: operator's etcd x509 client cert.\n- **etcd-client.key**: operator's etcd x509 client key.\n- **etcd-client-ca.crt**: CA cert for validating the certs of etcd members.\nThey correspond to the `--cert`,`--key`, and `--cacert` arguments of `etcdctl`.\n\nCreate a secret containing the `etcd-client.crt`, `etcd-client.key`, and `etcd-client-ca.crt`:\n\n```\n$ kubectl create secret generic etcd-client-tls --from-file=etcd-client-ca.crt --from-file=etcd-client.crt --from-file=etcd-client.key\n```\n\nPass `etcd-client-tls` to the `operatorSecret` field.\n\n### Access a secure etcd cluster\n\nAssume a secure etcd cluster `example` is up and running.\n\nTo access the cluster, use the service `example-client.default.svc`, which matches the SAN of its certificates.\n\nAssume the following certs are used:\n\n```\netcd-client.crt\netcd-client.key\netcd-client-ca.crt\n```\n\n`etcd-client.crt` and `etcd-client.key` should be trusted by the etcd server's client CA `server-ca.crt`.\n\n`server.crt` and `server.key` should be trusted by the etcd client CA `etcd-client-ca.crt`.\n\nThe following  example `etcdctl` command will list members from the secure etcd cluster. Run this command from within a Kubernetes Pod to access the service name:\n\n```\n$ ETCDCTL_API=3 etcdctl --endpoints=https://example-client.default.svc:2379 \\\n    --cert=etcd-client.crt --key=etcd-client.key --cacert=etcd-client-ca.crt \\\n    member list -w table\n```\n\n\n[etcd-security]: https://coreos.com/etcd/docs/latest/op-guide/security.html\n[self-signed]: https://coreos.com/os/docs/latest/generate-self-signed-certificates.html\n[example-tls]: ../../example/tls/\n"
  },
  {
    "path": "third_party/etcd-operator/doc/user/clusterwide.md",
    "content": "# Manage clusters in all namespaces\n\nDefault etcd operator behavior is to only manage etcd clusters created in the same namespace.\nIt is possible to deploy an etcd operator with special option to manage clusterwide etcd clusters.\n\n## Install etcd operator\n\netcd operator have to run with `-cluster-wide` arg option.\n\nMore information in [install guide](install_guide.md).\n\nSee the example in [example/example-etcd-cluster.yaml](../../example/example-etcd-cluster.yaml)\n"
  },
  {
    "path": "third_party/etcd-operator/doc/user/conditions_and_events.md",
    "content": "# Status Events and Conditions\n\nTo make it easier for users to understand and debug the etcd-operator, the actions of the operator and the state of the cluster are communicated to the user in the standard Kubernetes convention.\n\nUse `kubectl describe` to view information about an object, including [Events][k8s-events] and [Conditions][k8s-conditions] associated with the resource.\n\nThe etcd-operator exposes the Events and Conditions for each EtcdCluster Custom Resource.\n\n## Events\n\nThe following types of Events and their specific instances are common in the lifecycle of an EtcdCluster:\n\n- A new member is added\n- A member is removed\n- A member is upgraded\n- A dead member is replaced\n\n## Conditions\n\nThe etcd cluster Condition and its statuses are defined as:\n\n- Available\n  - True: Majority members up\n  - False: Reason for not being available (majority down only)\n- Recovering\n  - True: Reason for recovery (all members down, or majority down)\n  - False: Reason for recovery failure (for example: no backup found)\n  - Not present\n- Scaling\n  - True: Scaling from current members size X to spec.size Y\n  - False: Reason for failure (for example: no more nodes to place member due to anti-affinity)\n  - Not present\n- Upgrading\n  - True: Upgrading from version X to Y\n  - False: Reason for failure\n  - Not present\n\n\n[k8s-events]: https://kubernetes.io/docs/api-reference/v1.7/#event-v1-core\n[k8s-conditions]: https://kubernetes.io/docs/api-reference/v1.7/#podcondition-v1-core\n"
  },
  {
    "path": "third_party/etcd-operator/doc/user/gcs_backup.md",
    "content": "# Backups using Google Cloud Storage (GCS)\n\nEtcd backup operator backs up the data of an etcd cluster running on Kubernetes to a remote storage such as Google Cloud Storage (GCS). If it is not deployed yet, please follow [here](walkthrough/backup-operator.md#deploy-etcd-backup-operator) to deploy it, e.g. by running\n\n```sh\nkubectl apply -f example/etcd-backup-operator/deployment.yaml\n```\n\n## Setup Google Cloud Platform (GCP) backup account, GCS bucket, and Secret\n\n  ```bash\n  # create account\n  BACKUP_ACCOUNT='backup-creator'\n  BACKUP_ACCOUNT_EMAIL=\"${BACKUP_ACCOUNT}@$(gcloud config get-value project).iam.gserviceaccount.com\"\n  gcloud iam service-accounts create \"$BACKUP_ACCOUNT\" --display-name='Backup creator service account'\n\n  # create bucket and set permissions\n  BACKUP_BUCKET='mygcsbackupsbucket'\n  gsutil mb \"$BACKUP_BUCKET\"\n  gsutil iam ch \"serviceAccount:${BACKUP_ACCOUNT_EMAIL}:objectCreator\" \"$BACKUP_BUCKET\"\n\n  # create secret\n  kubectl create secret generic gcp-credentials \\\n      --from-literal=\"credentials.json=$(gcloud iam service-accounts keys create - --iam-account=\"$BACKUP_ACCOUNT_EMAIL\")\"\n  ```\n\n## Create EtcdBackup CR\n\nCreate an `EtcdBackup` CR file `etcdbackup.yaml` which uses secret `gcp-credentials` from the previous section:\n\n```yaml\napiVersion: etcd.database.coreos.com/v1beta2\nkind: EtcdBackup\nmetadata:\n  name: example-etcd-cluster-backup\nspec:\n  etcdEndpoints: [\"http://example-etcd-cluster-client:2379\"]\n  storageType: GCS\n  gcs:\n    # The format of the path must be: \"<gcs-bucket-name>/<path-to-backup-object>\"\n    path: my-etcd-backups-bucket/my-etcd-backup-object\n    gcpSecret: gcp-credentials\n```\n\nApply it to kubernetes cluster:\n\n```sh\nkubectl apply -f etcdbackup.yaml\n```\n\nCheck the `status` section of the `EtcdBackup` CR:\n\n```sh\n$ kubectl get EtcdBackup example-etcd-cluster-backup -o yaml\napiVersion: etcd.database.coreos.com/v1beta2\nkind: EtcdBackup\n...\nspec:\n  gcs:\n    gcpSecret: gcp-credentials\n    path: my-etcd-backups-bucket/my-etcd-backup-object\n  etcdEndpoints:\n  - http://example-etcd-cluster-client:2379\n  storageType: GCS\nstatus:\n  etcdRevision: 1\n  etcdVersion: 3.2.13\n  succeeded: true\n\n```\n\nWe should see the backup files after running the following command:\n\n```bash\n$ gsutil ls gs://my-etcd-backups-bucket/my-etcd-backup-object\ngs://my-etcd-backups-bucket/my-etcd-backup-object\n```\n\nAlternatively, you can also login into the Google Cloud Platform Console to view these backups.\n\n## Create EtcdRestore CR\n\nEtcd restore operator is in charge of restoring etcd cluster from backup. If it is not deployed, please deploy by following command:\n\n```yaml\nkubectl apply -f example/etcd-restore-operator/deployment.yaml\n```\n\nNow kill all the etcd pods to simulate a cluster failure:\n\n```sh\nkubectl delete pod -l app=etcd,etcd_cluster=example-etcd-cluster --force --grace-period=0\n```\n\nCreate EtcdRestore CR:\n\n```yaml\napiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdRestore\"\nmetadata:\n  # The restore CR name must be the same as spec.etcdCluster.name\n  name: example-etcd-cluster\nspec:\n  etcdCluster:\n    # The namespace is the same as this EtcdRestore CR\n    name: example-etcd-cluster\n  backupStorageType: GCS\n  gcs:\n    # The format of the path must be: \"<gcs-bucket-name>/<path-to-backup-file>\"\n    path: my-etcd-backups-bucket/my-etcd-backup-object\n    gcpSecret: gcp-credentials\n```\n\nCheck the `status` section of the `EtcdRestore` CR:\n\n```sh\n$ kubectl get etcdrestore example-etcd-cluster -o yaml\napiVersion: etcd.database.coreos.com/v1beta2\nkind: EtcdRestore\n...\nspec:\n  gcs:\n    gcpSecret: gcp-credentials\n    path: my-etcd-backups-bucket/my-etcd-backup-object\n  backupStorageType: GCS\n  etcdCluster:\n    name: example-etcd-cluster\nstatus:\n  succeeded: true\n```\n\nVerify the `EtcdCluster` CR and restored pods for the restored cluster:\n\n```sh\n$ kubectl get etcdcluster\nNAME                   AGE\nexample-etcd-cluster   1m\n\n$ kubectl get pods -l app=etcd,etcd_cluster=example-etcd-cluster\nNAME                                     READY     STATUS    RESTARTS   AGE\nexample-etcd-cluster-795649v9kq          1/1       Running   1          3m\nexample-etcd-cluster-jtp447ggnq          1/1       Running   1          4m\nexample-etcd-cluster-psw7sf2hhr          1/1       Running   1          4m\n```\n"
  },
  {
    "path": "third_party/etcd-operator/doc/user/install_guide.md",
    "content": "# Installation guide\n\n## Set up RBAC\n\nSet up basic [RBAC rules][rbac-rules] for etcd operator:\n\n```bash\n$ example/rbac/create_role.sh\n```\n\n## Install etcd operator\n\nCreate a deployment for etcd operator:\n\n```bash\n$ kubectl create -f example/deployment.yaml\n```\n\netcd operator will automatically create a Kubernetes Custom Resource Definition (CRD):\n\n```bash\n$ kubectl get customresourcedefinitions\nNAME                                    KIND\netcdclusters.etcd.database.coreos.com   CustomResourceDefinition.v1beta1.apiextensions.k8s.io\n```\n\n## Uninstall etcd operator\n\nNote that the etcd clusters managed by etcd operator will **NOT** be deleted even if the operator is uninstalled.\n\nThis is an intentional design to prevent accidental operator failure from killing all the etcd clusters.\n\nTo delete all clusters, delete all cluster CR objects before uninstalling the operator.\n\nClean up etcd operator:\n\n```bash\nkubectl delete -f example/deployment.yaml\nkubectl delete endpoints etcd-operator\nkubectl delete crd etcdclusters.etcd.database.coreos.com\nkubectl delete clusterrole etcd-operator\nkubectl delete clusterrolebinding etcd-operator\n```\n\n## Installation using Helm\n\netcd operator is available as a [Helm chart][etcd-helm]. Follow the instructions on the chart to install etcd operator on clusters.\n[Alejandro Escobar][alejandroEsc] is the active maintainer.\n\n\n[rbac-rules]: rbac.md\n[etcd-helm]: https://github.com/kubernetes/charts/tree/master/stable/etcd-operator/\n[alejandroEsc]:https://github.com/alejandroEsc"
  },
  {
    "path": "third_party/etcd-operator/doc/user/oss_backup.md",
    "content": "# Backups using Alibaba Cloud Object Storage Service (OSS)\n\nEtcd backup operator backs up the data of an etcd cluster running on Kubernetes to a remote storage such as Alibaba Cloud Object Storage Service (OSS). If it is not deployed yet, please follow the [instructions](walkthrough/backup-operator.md#deploy-etcd-backup-operator) to deploy it, e.g. by running\n\n```sh\nkubectl apply -f example/etcd-backup-operator/deployment.yaml\n```\n\n## Setup Alibaba Cloud backup account, OSS bucket, and Secret\n\n1. Login [Alibaba Cloud Console](https://www.alibabacloud.com) (or [Aliyun Console](https://www.aliyun.com/) if you are in China) and create your own [AccessKey](https://www.alibabacloud.com/help/doc-detail/29009.htm) which gives you the AccessKeyID (AKID) and AccessKeySecret (AKS). You can optionally create an Object Storage Service ([OSS](https://www.alibabacloud.com/help/doc-detail/31947.htm)) bucket for backups.\n2. Create a secret storing your AKID and AKS in Kubernetes.  \n\n ```yaml  \napiVersion: v1\n  kind: Secret\n  metadata:\n    name: my-oss-credentials\n  type: Opaque\n  data:\n    accessKeyID: <my-access-key-id>\n    accessKeySecret: <my-access-key-secret>\n ```  \n\n3. Create an `EtcdBackup` CR file `etcdbackup.yaml` which uses secret `my-oss-credentials` from the previous step.  \n```yaml\napiVersion: etcd.database.coreos.com/v1beta2\nkind: EtcdBackup\nmetadata:\n  name: etcd-cluster-with-oss-backup\nspec:\n  backupPolicy:\n    ...\n  etcdEndpoints:\n    - \"http://example-etcd-cluster-client:2379\"\n  storageType: OSS\n  oss:\n    endpoint: http://oss-cn-hangzhou.aliyuncs.com\n    ossSecret: my-oss-credentials\n    path: my-etcd-backups-bucket/etcd.backup\n```   \n\n4. Apply yaml file to kubernetes cluster.  \n```sh\nkubectl apply -f etcdbackup.yaml\n```\n5. Check the `status` section of the `EtcdBackup` CR.\n```console\n$ kubectl get EtcdBackup etcd-cluster-with-oss-backup -o yaml\napiVersion: etcd.database.coreos.com/v1beta2\nkind: EtcdBackup\n...\nspec:\n  oss:\n    ossSecret: my-oss-credentials\n    path: my-etcd-backups-bucket/etcd.backup\n    endpoint: http://oss-cn-hangzhou.aliyuncs.com\n  etcdEndpoints:\n  - http://example-etcd-cluster-client:2379\n  storageType: OSS\nstatus:\n  etcdRevision: 1\n  etcdVersion: 3.2.13\n  succeeded: true\n```\n\n6. We should see the backup files from Alibaba Cloud OSS Console.\n\n\n## Restore etcd based on data from OSS.\n\nEtcd restore operator is in charge of restoring etcd cluster from backup. If it is not deployed, please deploy by following command:\n\n```sh\nkubectl apply -f example/etcd-restore-operator/deployment.yaml\n```\n\nNow kill all the etcd pods to simulate a cluster failure:\n\n```sh\nkubectl delete pod -l app=etcd,etcd_cluster=example-etcd-cluster --force --grace-period=0\n```\n\n1. Create an EtcdRestore CR.\n```yaml\napiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdRestore\"\nmetadata:\n  # The restore CR name must be the same as spec.etcdCluster.name\n  name: example-etcd-cluster\nspec:\n  etcdCluster:\n    # The namespace is the same as this EtcdRestore CR\n    name: example-etcd-cluster\n  backupStorageType: OSS\n  oss:\n    # The format of the path must be: \"<oss-bucket-name>/<path-to-backup-file>\"\n    path: my-etcd-backups-bucket/etcd.backup\n    ossSecret: my-oss-credentials\n    endpoint: http://oss-cn-hangzhou.aliyuncs.com\n```\n\n2. Check the `status` section of the `EtcdRestore` CR.     \n```sh\n$ kubectl get etcdrestore example-etcd-cluster -o yaml\napiVersion: etcd.database.coreos.com/v1beta2\nkind: EtcdRestore\n...\nspec:\n  oss:\n    ossSecret: my-oss-credentials\n    path: my-etcd-backups-bucket/etcd.backup\n    endpoint: http://oss-cn-hangzhou.aliyuncs.com\n  backupStorageType: OSS\n  etcdCluster:\n    name: example-etcd-cluster\nstatus:\n  succeeded: true\n```\n\n3. Verify the `EtcdCluster` CR and restored pods for the restored cluster.    \n```sh  \n$ kubectl get etcdcluster\n$ kubectl get pods -l app=etcd,etcd_cluster=example-etcd-cluster\n```\n"
  },
  {
    "path": "third_party/etcd-operator/doc/user/rbac.md",
    "content": "# Setting up RBAC for etcd operator\n\nIf RBAC is in place, users must create RBAC rules for etcd operator. This doc serves a tutorial for it.\n\n## Production setup\n\nIn production, allow access only to the resources etcd operator needs, and create a specific role for the operator.\n\nThe following example binds a role to the `default` service account in the namespace in which the etcd operator is running. To bind to a different service account, modify the `subjects.name` field in the [rolebinding templates][rbac-templates] as needed.\n\n### Role vs ClusterRole\n\nThe permission model required for the etcd operator depends on the value of its `--create-crd` flag:\n- `--create-crd=true`: Creates a CRD if one does not yet exist. This the default behavior.\n  - In this mode the operator requires a ClusterRole with the permission to create a CRD.\n- `--create-crd=false` Creates a CR without first creating a CRD.\n  - In this mode the operator can be run with just a Role without the permission to create a CRD.\n\n## Set up RBAC\n\nSet up RBAC rules using either a ClusterRole or Role, according to the `--create-crd` flag requirements listed above.\n\nModify and export the following environment variables. These will be used to fill out the [RBAC templates][rbac-templates]:\n\n```\nexport ROLE_NAME=<role-name>\nexport ROLE_BINDING_NAME=<role-binding-name>\nexport NAMESPACE=<namespace>\n```\n\n### RBAC with ClusterRole (create-crd=true)\n\n1. Create a ClusterRole:\n\n    ```sh\n    sed -e \"s/<ROLE_NAME>/${ROLE_NAME}/g\" example/rbac/cluster-role-template.yaml \\\n      | kubectl create -f -\n    ```\n\n2. Create a ClusterRoleBinding which binds the default service account in the namespace to the ClusterRole:\n\n    ```sh\n    sed -e \"s/<ROLE_NAME>/${ROLE_NAME}/g\" \\\n      -e \"s/<ROLE_BINDING_NAME>/${ROLE_BINDING_NAME}/g\" \\\n      -e \"s/<NAMESPACE>/${NAMESPACE}/g\" \\\n      example/rbac/cluster-role-binding-template.yaml \\\n      | kubectl create -f -\n    ```\n\n### RBAC with Role (create-crd=false)\n\n1. Create a Role:\n\n    ```sh\n    sed -e \"s/<ROLE_NAME>/${ROLE_NAME}/g\" \\\n      -e \"s/<NAMESPACE>/${NAMESPACE}/g\" \\\n      example/rbac/role-template.yaml \\\n      | kubectl create -f -\n    ```\n\n2. Create a RoleBinding which binds the default service account in the namespace to the Role:\n\n    ```sh\n    sed -e \"s/<ROLE_NAME>/${ROLE_NAME}/g\" \\\n      -e \"s/<ROLE_BINDING_NAME>/${ROLE_BINDING_NAME}/g\" \\\n      -e \"s/<NAMESPACE>/${NAMESPACE}/g\" \\\n      example/rbac/role-binding-template.yaml \\\n      | kubectl create -f -\n    ```\n\n[rbac-templates]: ../../example/rbac/\n"
  },
  {
    "path": "third_party/etcd-operator/doc/user/resource_labels.md",
    "content": "# Resource Labels\n\nThe etcd operator creates the following Kubernetes resources for each etcd cluster:\n- Pods for the etcd nodes\n- Services for the etcd client and peer\n\nwhere each resource has the following labels:\n- `app=etcd`\n- `etcd_cluster=<cluster-name>`\n"
  },
  {
    "path": "third_party/etcd-operator/doc/user/spec_examples.md",
    "content": "# Cluster Spec Examples\n\n## Three member cluster\n\n```yaml\nspec:\n  size: 3\n```\n\nThis will use the default version chosen by the etcd-operator.\n\n## Three member cluster with version specified\n\n```yaml\nspec:\n  size: 3\n  version: \"3.2.13\"\n```\n\n## Three member cluster with node selector and anti-affinity across nodes\n\n> Note: change $cluster_name to the EtcdCluster's name.\n\n```yaml\nspec:\n  size: 3\n  pod:\n    nodeSelector:\n      diskType: ssd\n    affinity:\n      podAntiAffinity:\n        requiredDuringSchedulingIgnoredDuringExecution:\n        - labelSelector:\n            matchExpressions:\n            - key: etcd_cluster\n              operator: In\n              values: [\"$cluster_name\"]\n          topologyKey: kubernetes.io/hostname\n```\n\nFor other topology keys, see https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ .\n\n## Three member cluster with preferred anti-affinity between pods and nodes (place pods in different nodes if possible)\n\n> Note: change $cluster_name to the EtcdCluster's name.\n\n```yaml\nspec:\n  size: 3\n  pod:\n    affinity:\n      podAntiAffinity:\n        preferredDuringSchedulingIgnoredDuringExecution:\n        - weight: 100\n          podAffinityTerm:\n            labelSelector:\n              matchExpressions:\n              - key: etcd_cluster\n                operator: In\n                values:\n                - $cluster_name\n            topologyKey: kubernetes.io/hostname\n```\n\n## Three member cluster with resource requirement\n\n```yaml\nspec:\n  size: 3\n  pod:\n    resources:\n      limits:\n        cpu: 300m\n        memory: 200Mi\n      requests:\n        cpu: 200m\n        memory: 100Mi\n```\n\n## Custom etcd configuration\n\netcd members could be configured via env: https://coreos.com/etcd/docs/latest/op-guide/configuration.html\n\n```yaml\nspec:\n  size: 3\n  pod:\n    etcdEnv:\n    - name: ETCD_AUTO_COMPACTION_RETENTION\n      value: \"1\"\n```\n\n## TLS\n\nFor more information on working with TLS, see [Cluster TLS policy][cluster-tls].\n\n## Custom pod annotations\n\n```yaml\nspec:\n  size: 3\n  pod:\n    annotations:\n      prometheus.io/scrape: \"true\"\n      prometheus.io/port: \"2379\"\n```\n\n## Custom pod security context\n\nFor more information on pod security context see the Kubernetes [docs][pod-security-context].\n\n```yaml\nspec:\n  size: 3\n  pod:\n    securityContext:\n      runAsNonRoot: true\n      runAsUser: 9000\n      # The FSGroup is needed to let the etcd container access mounted volumes\n      fsGroup: 9000\n```\n\n## Custom PersistentVolumeClaim definition\n\n> Note: Change $STORAGECLASS for your preferred StorageClass or remove the line to use the default one. \n\n```yaml\nspec:\n  size: 3\n  pod:\n    persistentVolumeClaimSpec:\n      storageClassName: $STORAGECLASS\n      accessModes:\n      - ReadWriteOnce\n      resources:\n        requests:\n          storage: 1Gi\n```\n\n[cluster-tls]: cluster_tls.md\n[pod-security-context]: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod\n"
  },
  {
    "path": "third_party/etcd-operator/doc/user/upgrade/migrate_cr_070.md",
    "content": "# Custom Resource Migration Guide for 0.7.0 relase\n\nIn 0.7.0 release, BackupPolicy and RestorePolicy are removed from EtcdCluster spec.\nThis doc provides the migration guide for the change.\n\n## Migrate EtcdCluster\n\nThis has to be done **before upgrading operator**.\n\nUpdate any EtcdCluster Custom Resource to remove BackupPolicy and RestorePolicy:\n\n```\nkubectl get etcdcluster <cluster-name> -o json | \\\n\tjq 'del(.spec.backup)' | jq 'del(.spec.restore)' | \\\n\tkubectl replace -f -\n```\n\n## Migrate BackupPolicy to EtcdBackup CR\n\nRead [etcd backup operator doc](../walkthrough/backup-operator.md) for how to save backup for etcd cluster.\nIt currently only supports S3 backup for non-TLS etcd cluster.\n\nFor previous backup policy, for example:\n\n```yaml\napiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdCluster\"\nmetadata:\n  name: \"example-etcd-cluster\"\nspec:\n  ...\n  backup:\n    storageType: \"S3\"\n    s3:\n      s3Bucket: <s3-bucket-name>\n      awsSecret: <aws-secret-name>\n```\n\nThe equivalent EtcdBackup CR is:\n\n```yaml\napiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdBackup\"\nmetadata:\n  name: example-etcd-cluster-backup\nspec:\n  clusterName: example-etcd-cluster\n  storageType: \"S3\"\n  s3:\n    s3Bucket: <s3-bucket-name>\n    awsSecret: <aws-secret-name>\n```\n\nCreate the above CR will make **one-time** backup attempt to target etcd cluster.\nAfter backup is saved, it is safe to delete the CR and doing that won’t delete the S3 backup.\n\n\n## Migrate RestoreSpec to EtcdRestore CR\n\nRead [etcd restore operator doc](../walkthrough/restore-operator.md) for how to restore etcd cluster from backup.\nIt currently only supports S3 backup and non-TLS etcd cluster.\n\nFor previous restore policy for example:\n```yaml\napiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdCluster\"\nmetadata:\n  name: \"restored-etcd-cluster\"\nspec:\n  ...\n  restore:\n    storageType: \"S3\"\n    backupClustername: “example-etcd-cluster”\n```\n\nThe equivalent EtcdRestore CR is:\n\n```yaml\napiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdRestore\"\nmetadata:\n  # an EtcdCluster with the same name will be created\n  name: \"restored-etcd-cluster\"\nspec:\n  clusterSpec:\n    size: 3\n    version: \"3.1.8\"\n  s3:\n    # e.g: \"etcd-snapshot-bucket/v1/default/example-etcd-cluster/3.1.8_0000000000000001_etcd.backup\"\n    path: <full-s3-path>\n    awsSecret: <aws-secret>\n```\n\nCreate the above CR to trigger restore.\n\n> Note: restore process will create a new EtcdCluster CR.\n\nWait until etcd cluster reaches given size.\nThe it is safe to delete the EtcdRestore CR and doing that won’t delete the EtcdCluster CR.\n"
  },
  {
    "path": "third_party/etcd-operator/doc/user/upgrade/upgrade_guide.md",
    "content": "# Upgrade Guide\n\nThis document shows how to safely upgrade the operator to a desired version while preserving the cluster's state and data whenever possible. \n\n### Backup safety precaution:\n**Note:** Only applies to when upgrading from an etcd operator with version < v0.7.0.\n\nFirst create a backup of your current cluster before starting the upgrade process. See the [backup service guide](https://github.com/coreos/etcd-operator/blob/v0.6.1/doc/user/backup_service.md) on how to create a backup.\n\nIn the case of an upgrade failure you can restore your cluster to the previous state from the previous backup. See the [spec examples](https://github.com/coreos/etcd-operator/blob/v0.6.1/doc/user/spec_examples.md) on how to do that.\n\n## v0.6.1 -> v0.7.0\n**Note:** if your cluster specifies either the backup policy or restore policy, then follow the  [migrate CR](./migrate_cr_070.md) guide to update the cluster spec before upgrading the etcd-operator deployment.\n\nUpdate the etcd-operator deployment:\n- Edit the existing etcd-operator deployment: `kubectl edit deployment/<your-operator>`.\n- Modify `image` to `quay.io/coreos/etcd-operator:v0.7.0`.\n- If `command` field doesn't exist, add a new `command` field to run `etcd-operator`:\n\n  ```\n  command:\n  - etcd-operator\n  ```\n- If `command` field exists and `pv-provisioner` flag is used, you must remove `pv-provisioner` flag.\n- Save.\n\n## v0.6.0 -> v0.6.1\n\nIn `v0.6.1+` the operator will no longer create a storage class specified by `--pv-provisioner` by default. This behavior is set by the new flag `--create-storage-class` which by default is `false`.\n\n**Note:** If your cluster does not have the following backup policy then you can simply upgrade the operator to the `v0.6.1` image.\n\nBackup policy that has `StorageType=PersistentVolume` but `pv.storageClass` is unset. For example:\n```yaml\nspec:\n    backup:\n      backupIntervalInSecond: 30\n      maxBackups: 5\n      pv:\n        storageClass: \"\"\n        volumeSizeInMB: 512\n      storageType: PersistentVolume\n```\n\nSo if your cluster has the above backup policy then do the following steps before upgrading the operator image to `v0.6.1`.\n\n\n- Confirm the name of the storage class for a given cluster:\n\n  ```sh\n  kubectl -n <namespace> get pvc -l=etcd_cluster=<cluster-name> -o yaml | grep storage-class\n  ```\n\n- Edit your etcd cluster spec by changing the `spec.backup.pv.storageClass` field to the name of the existing storage class from the previous step.\n- Wait for the the backup sidecar to be updated.\n\n## v0.5.x -> v0.6.0\n\n### Breaking Change\n\nThe v0.6.0 release removes [operator S3 flag](https://github.com/coreos/etcd-operator/blob/v0.5.1/doc/user/backup_config.md#operator-level-configuration).\n\n**Note:** if your cluster is not using operator S3 flag, then you just need recreate etcd-operator deployment with the `v0.6.0` image.\n\nIf your cluster is using operator S3 flag for backup and want to use S3 backup in v0.6.0, then you need to migrate your cluster to use [cluster level backup](../backup_config.md#S3-on-aws).\n\nSteps for migration:\n\n- Create a backup of you current data using the [backup service guide](../backup_service.md#http-api-v1).\n\n- Create a new AWS secret `<aws-secret>` for [cluster level backup](../backup_config.md#s3-on-aws):\n\n  `$ kubectl -n <namespace> create secret generic <aws-secret> --from-file=$AWS_DIR/credentials --from-file=$AWS_DIR/config`\n\n- Change the backup field in your existing cluster backup spec to enable [cluster level backup](../backup_config.md#s3-on-aws):\n\n  From\n\n  ```yaml\n  backup:\n    backupIntervalInSecond: 30\n    maxBackups: 5\n    storageType: \"S3\"\n  ```\n\n  to\n\n  ```yaml\n  backup:\n    backupIntervalInSecond: 30\n    maxBackups: 5\n    storageType: \"S3\"\n    s3:\n      s3Bucket: <your-s3-bucket>\n      awsSecret: <aws-secret> \n  ```\n\n- Apply the cluster backup spec:\n  `$ kubectl -n <namespace> apply -f <your-cluster-deployment>.yaml`\n\n- Update deployment spec to use `etcd-operator:v0.6.0` and remove the dependency on operator level S3 backup flags:\n\n  From\n\n  ```yaml\n  spec:\n    containers:\n    - name: etcd-operator\n      image: quay.io/coreos/etcd-operator:v0.5.2\n      command: \n        - /usr/local/bin/etcd-operator\n        - --backup-aws-secret=aws\n        - --backup-aws-config=aws\n        - --backup-s3-bucket=<your-s3-bucket>\n  ```\n\n  to \n\n  ```yaml\n  spec:\n    containers:\n    - name: etcd-operator\n      image: quay.io/coreos/etcd-operator:v0.6.0\n      command: \n        - /usr/local/bin/etcd-operator\n  ```\n\n- Apply the updated deployment spec:\n  `$ kubectl -n <namespace> apply -f <your-etcd-operator-deployment>.yaml`\n\n## v0.4.x -> v0.5.x\nFor any `0.4.x` versions, please update to `0.5.0` first.\n\nThe `0.5.0` release introduces a breaking change in moving from [TPR](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-third-party-resource/) to [CRD](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions/). To preserve the cluster state across the upgrade, the cluster must be recreated from backup after the upgrade.\n### Prerequisite:\nKubernetes cluster version must be 1.7+.\n\n### Steps to upgrade:\n- Create a backup of your current cluster data. See the following guides on how to enable and create backups:\n    - [backup config guide](https://github.com/coreos/etcd-operator/blob/master/doc/user/backup_config.md) to enable backups fro your cluster\n    - [backup service guide](https://github.com/coreos/etcd-operator/blob/master/doc/user/backup_service.md) to create a backup\n- Delete the cluster TPR object. The etcd-operator will delete all resources(pods, services, deployments) associated with the cluster:\n    - `kubectl -n <namespace> delete cluster <cluster-name>`\n- Delete the etcd-operator deployment\n- Delete the TPR\n    - `kubectl delete thirdpartyresource cluster.etcd.coreos.com`\n- Replace the existing RBAC rules for the etcd-operator by editing or recreating the `ClusterRole` with the [new rules for CRD](https://github.com/coreos/etcd-operator/blob/master/doc/user/rbac.md#create-clusterrole).\n- Recreate the etcd-operator deployment with the `0.5.0` image.\n- Create a new cluster that restores from the backup of the previous cluster. The new cluster CR spec should look as follows:\n```\napiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdCluster\"\nmetadata:\n  name: <cluster-name>\nspec:\n  size: <cluster-size>\n  version: \"3.1.8\"\n  backup:\n    # The same backup spec used to save the backup of the previous cluster\n    . . .\n    . . .\n  restore:\n    backupClusterName: <previous-cluster-name>\n    storageType: <storage-type-of-backup-spec>\n```\nThe two points of interest in the above CR spec are:\n  1. The `apiVersion` and `kind` fields have been changed as mentioned in the `0.5.0` release notes\n  2. The `spec.restore` field needs to be specified according your backup configuration. See [spec examples guide](https://github.com/coreos/etcd-operator/blob/master/doc/user/spec_examples.md#three-members-cluster-that-restores-from-previous-pv-backup) on how to specify the `spec.restore` field for your particular backup configuration.\n\n## v0.3.x -> v0.4.x\nUpgrade to `v0.4.0` first.\nSee the release notes of `v0.4.0` for noticeable changes: https://github.com/coreos/etcd-operator/releases/tag/v0.4.0\n\n## v0.2.x -> v0.3.x\n### Prerequisite:\nTo upgrade to `v0.3.x` the current operator version **must** first be upgraded to `v0.2.6+`, since versions < `v0.2.6` are not compatible with `v0.3.x` .\n\n### Noticeable changes:\n- `Spec.Backup.MaxBackups` update:\n  - If you have `Spec.Backup.MaxBackups < 0`, previously it had no effect.\n    Now it will get rejected. Please remove it.\n  - If you have `Spec.Backup.MaxBackups == 0`, previously it had no effect.\n    Now it will create backup sidecar that allows unlimited backups.\n    If you don't want backup sidecar, just don't set any backup policy.\n"
  },
  {
    "path": "third_party/etcd-operator/doc/user/walkthrough/backup-operator.md",
    "content": "# etcd backup operator\n\n## Overview\n\netcd backup operator backs up the data of a etcd cluster running on [Kubernetes][Kube] to a remote storage such as AWS [S3][s3].\n\n## Getting Started\n\nTry out etcd backup operator by running it on Kubernetes and then create a `EtcdBackup` Custom Resource which contains the targeting etcd cluster and S3 backup config; the etcd backup operator automatically picks up the `EtcdBackup` Custom Resource, retrieves etcd snapshot, and then saves it to S3.\n>Note: The demo uses the `default` namespace.\n\nPrerequisites: \n* Setup RBAC and deploy an etcd operator. See [Install Guide][install_guide]\n* A running etcd cluster named `example-etcd-cluster`. See [instructions][etcd_cluster_deploy] to deploy it.\n\n### Deploy etcd backup operator\n\nCreate a deployment of etcd backup operator:\n> Note: etcd backup operator creates EtcdBackup CRD automatically\n\n```sh\n$ kubectl create -f example/etcd-backup-operator/deployment.yaml\n$ kubectl get pod\nNAME                                    READY     STATUS    RESTARTS   AGE\netcd-backup-operator-1102130733-hhgt7   1/1       Running   0          3s\n```\n\nVerify that the etcd-backup-operator creates EtcdBackup CRD:\n\n```sh\n$ kubectl get crd\nNAME                                    KIND\netcdbackups.etcd.database.coreos.com    CustomResourceDefinition.v1beta1.apiextensions.k8s.io\n```\n\n### Setup AWS Secret\n\nCreate a Kubernetes secret that contains aws config/credential;\nthe secret will be used later to save etcd backup into S3.\n\n1. Verify that the local aws config and credentials files exist:\n\n    ```sh\n    $ cat $AWS_DIR/credentials\n    [default]\n    aws_access_key_id = XXX\n    aws_secret_access_key = XXX\n\n    $ cat $AWS_DIR/config\n    [default]\n    region = <region>\n    ```\n\n2. Create secret `aws`:\n\n    ```\n    kubectl create secret generic aws --from-file=$AWS_DIR/credentials --from-file=$AWS_DIR/config\n    ```\n\n### Create EtcdBackup CR\n\nCreate EtcdBackup CR:\n>Note: this example uses S3 Bucket \"mybucket\" and k8s secret \"aws\"\n\n```sh\nsed -e 's|<full-s3-path>|mybucket/etcd.backup|g' \\\n    -e 's|<aws-secret>|aws|g' \\\n    -e 's|<etcd-cluster-endpoints>|\"http://example-etcd-cluster-client:2379\"|g' \\\n    example/etcd-backup-operator/backup_cr.yaml \\\n    | kubectl create -f -\n```\n\n### Verify status\n\nCheck the `status` section of the `EtcdBackup` CR:\n\n```\n$ kubectl get EtcdBackup example-etcd-cluster-backup -o yaml\napiVersion: etcd.database.coreos.com/v1beta2\nkind: EtcdBackup\n...\nstatus:\n  etcdRevision: 1\n  etcdVersion: 3.2.13\n  succeeded: true\n```\n\nThis demonstrates etcd backup operator's basic one time backup functionality.\n\n### Cleanup\n\nDelete the etcd-backup-operator deployment and the `EtcdBackup` CR.\n> Note: Deleting the `EtcdBackup` CR won't delete the backup in S3.\n\n```sh\nkubectl delete etcdbackup example-etcd-cluster-backup\nkubectl delete -f example/etcd-backup-operator/deployment.yaml\n```\n\n[Kube]:https://github.com/kubernetes/kubernetes\n[s3]:https://aws.amazon.com/s3/\n[etcd_cluster_deploy]:https://github.com/coreos/etcd-operator#create-and-destroy-an-etcd-cluster\n[minikube]:https://github.com/kubernetes/minikube\n[install_guide]:../install_guide.md\n"
  },
  {
    "path": "third_party/etcd-operator/doc/user/walkthrough/restore-operator.md",
    "content": "# etcd restore operator\n\n## Overview\n\nThe etcd-restore-operator can restore an etcd cluster on Kubernetes from backup.\n\nThe overall workflow is:\n- Create the etcd-restore-operator\n- Create an `EtcdRestore` Custom Resource which triggers a restore request that specifies:\n  - the etcd cluster spec\n  - how to access the backup\n- The etcd-restore-operator will restore a new cluster from the backup\n- The etcd-operator takes over the management of the restored cluster\n\nNote that currently the etcd-restore-operator only supports restoring from backups saved on S3.\n\n**Prerequisite**\n- Setup RBAC and deploy an etcd operator. See [Install Guide][install_guide]\n- Have an etcd backup saved on S3. See the [etcd-backup-operator README][backup-operator-README] as one way to save a backup to S3.\n\n>Note: This demo uses the `default` namespace.\n\n\n### Simulate disaster failure\n\n1. Make sure `example-etcd-cluster` EtcdCluster CR exists\n\n    ```sh\n    kubectl get etcdcluster example-etcd-cluster\n    ```\n\n2. Kill etcd pods to simulate disaster failure\n\n    ```sh\n    kubectl delete pod -l app=etcd,etcd_cluster=example-etcd-cluster --force --grace-period=0\n    ```\n\n### Deploy the etcd-restore-operator\n\n1. Create a deployment of the etcd-restore-operator:\n\n    ```sh\n    kubectl create -f example/etcd-restore-operator/deployment.yaml\n    ```\n\n2. Verify the following resources exist:\n\n    ```sh\n    $ kubectl get pods\n    NAME                                     READY     STATUS    RESTARTS   AGE\n    etcd-restore-operator-4203122180-npn3g   1/1       Running   0          7s\n    ```\n\n3. Verify that the etcd-restore-operator creates the `EtcdRestore` CRD:\n\n    ```sh\n    $ kubectl get crd\n    NAME                                       KIND\n    etcdrestores.etcd.database.coreos.com      CustomResourceDefinition.v1beta1.apiextensions.k8s.io\n    ```\n\n### Setup AWS Secret\n\nCreate a Kubernetes secret that contains AWS credentials and config. This is used by the etcd-restore-operator to retrieve the backup from S3.\n\n1. Verify that the local aws config and credentials files exist:\n\n    ```sh\n    $ cat $AWS_DIR/credentials\n    [default]\n    aws_access_key_id = XXX\n    aws_secret_access_key = XXX\n\n    $ cat $AWS_DIR/config\n    [default]\n    region = <region>\n    ```\n\n2. Create the secret `aws`:\n\n    ```sh\n    kubectl create secret generic aws --from-file=$AWS_DIR/credentials --from-file=$AWS_DIR/config\n    ```\n\n### Create EtcdRestore CR\n\nCreate the `EtcdRestore` CR:\n\n>Note: This example uses k8s secret \"aws\" and S3 path \"mybucket/etcd.backup\"\n\n```sh\nsed -e 's|<full-s3-path>|mybucket/etcd.backup|g' \\\n    -e 's|<aws-secret>|aws|g' \\\n    example/etcd-restore-operator/restore_cr.yaml \\\n    | kubectl create -f -\n```\n\n### Verify the CR status and restored cluster\n\n1. Check the `status` section of the `EtcdRestore` CR:\n\n    ```sh\n    $ kubectl get etcdrestore example-etcd-cluster -o yaml\n    apiVersion: etcd.database.coreos.com/v1beta2\n    kind: EtcdRestore\n    ...\n    status:\n      succeeded: true\n    ```\n\n2. Verify the `EtcdCluster` CR for the restored cluster:\n\n    ```\n    $ kubectl get etcdcluster\n    NAME                    KIND\n    example-etcd-cluster   EtcdCluster.v1beta2.etcd.database.coreos.com\n    ```\n\n3. Verify that the etcd-operator scales the cluster to the desired size:\n\n    ```sh\n    $ kubectl get pods\n    NAME                                     READY     STATUS    RESTARTS   AGE\n    etcd-operator-2486363115-ltc17           1/1       Running   0          1h\n    etcd-restore-operator-4203122180-npn3g   1/1       Running   0          30m\n    example-etcd-cluster-795649v9kq          1/1       Running   1          3m\n    example-etcd-cluster-jtp447ggnq          1/1       Running   1          4m\n    example-etcd-cluster-psw7sf2hhr          1/1       Running   1          4m\n    ```\n\n### Cleanup\n\nDelete the etcd-restore-operator deployment and service, and the `EtcdRestore` CR. \n>Note: Deleting the `EtcdRestore` CR won't delete the `EtcdCluster` CR.\n\n```sh\nkubectl delete etcdrestore example-etcd-cluster\nkubectl delete -f example/etcd-restore-operator/deployment.yaml\n```\n\n\n[backup-operator-README]:./backup-operator.md\n[install_guide]:../install_guide.md\n"
  },
  {
    "path": "third_party/etcd-operator/example/deployment.yaml",
    "content": "apiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: etcd-operator\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        name: etcd-operator\n    spec:\n      containers:\n      - name: etcd-operator\n        image: quay.io/coreos/etcd-operator:v0.9.4\n        command:\n        - etcd-operator\n        # Uncomment to act for resources in all namespaces. More information in doc/user/clusterwide.md\n        #- -cluster-wide\n        env:\n        - name: MY_POD_NAMESPACE\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.namespace\n        - name: MY_POD_NAME\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.name\n"
  },
  {
    "path": "third_party/etcd-operator/example/deployment_psp.yaml",
    "content": "apiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: etcd-operator\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        name: etcd-operator\n    spec:\n      securityContext:\n        runAsUser: 1000\n        fsGroup: 1000\n      containers:\n      - name: etcd-operator\n        image: quay.io/coreos/etcd-operator:v0.9.4\n        command:\n        - etcd-operator\n        # Uncomment to act for resources in all namespaces. More information in doc/user/clusterwide.md\n        #- -cluster-wide\n        env:\n        - name: MY_POD_NAMESPACE\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.namespace\n        - name: MY_POD_NAME\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.name\n"
  },
  {
    "path": "third_party/etcd-operator/example/etcd-backup-operator/backu_cr_qcloud.yaml",
    "content": "apiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdBackup\"\nmetadata:\n  name: etcd-backup-TIMESTAMP\nspec:\n  etcdEndpoints: [\"http://localhost:2379\"]\n  storageType: COS\n  cos:\n    # The format of \"path\" must be: \"<s3-bucket-name>/<path-to-backup-file>\"\n    # e.g: \"mybucket/etcd.backup\"\n    path: bucket-test.cos.ap-shanghai.myqcloud.com/cos-test/TIMESTAMP\n    cosSecret: cos-secret\n"
  },
  {
    "path": "third_party/etcd-operator/example/etcd-backup-operator/backup.sh",
    "content": "#!/bin/bash\n\ntimestamp=`date +%s`\necho $timestamp\ncat ./backup_cr_qcloud.yaml | sed \"s/TIMESTAMP/$timestamp/\" | kubectl create -f -\n"
  },
  {
    "path": "third_party/etcd-operator/example/etcd-backup-operator/backup_cr.yaml",
    "content": "apiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdBackup\"\nmetadata:\n  name: example-etcd-cluster-backup\nspec:\n  etcdEndpoints: [<etcd-cluster-endpoints>]\n  storageType: S3\n  s3:\n    # The format of \"path\" must be: \"<s3-bucket-name>/<path-to-backup-file>\"\n    # e.g: \"mybucket/etcd.backup\"\n    path: <full-s3-path>\n    awsSecret: <aws-secret>\n"
  },
  {
    "path": "third_party/etcd-operator/example/etcd-backup-operator/deployment.yaml",
    "content": "apiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: etcd-backup-operator\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        name: etcd-backup-operator\n    spec:\n      containers:\n      - name: etcd-backup-operator\n        image: quay.io/coreos/etcd-operator:v0.9.4\n        command:\n        - etcd-backup-operator\n        env:\n        - name: MY_POD_NAMESPACE\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.namespace\n        - name: MY_POD_NAME\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.name\n"
  },
  {
    "path": "third_party/etcd-operator/example/etcd-backup-operator/deployment_qcloud.yaml",
    "content": "apiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: etcd-backup-operator\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        name: etcd-backup-operator\n    spec:\n      containers:\n      - name: etcd-backup-operator\n        image: ccr.ccs.tencentyun.com/etcd-dev/etcd-operator:latest\n        imagePullPolicy: Always\n        command:\n        - etcd-backup-operator\n        env:\n        - name: MY_POD_NAMESPACE\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.namespace\n        - name: MY_POD_NAME\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.name\n"
  },
  {
    "path": "third_party/etcd-operator/example/etcd-backup-operator/periodic_backup_cr.yaml",
    "content": "apiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdBackup\"\nmetadata:\n  name: example-etcd-cluster-periodic-backup\nspec:\n  etcdEndpoints: [<etcd-cluster-endpoints>]\n  storageType: S3\n  backupPolicy:\n    # 0 > enable periodic backup\n    backupIntervalInSecond: 125\n    maxBackups: 4\n  s3:\n    # The format of \"path\" must be: \"<s3-bucket-name>/<path-to-backup-file>\"\n    # e.g: \"mybucket/etcd.backup\"\n    path: <full-s3-path>\n    awsSecret: <aws-secret>\n"
  },
  {
    "path": "third_party/etcd-operator/example/etcd-backup-operator/secrets.yaml",
    "content": "apiVersion: v1\ndata:\n  secret-id: xxx\n  secret-key: xxx\nkind: Secret\nmetadata:\n  name: cos-secret\n  namespace: default\n"
  },
  {
    "path": "third_party/etcd-operator/example/etcd-restore-operator/deployment.yaml",
    "content": "apiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: etcd-restore-operator\n  labels:\n    name: etcd-restore-operator\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        name: etcd-restore-operator\n    spec:\n      containers:\n      - name: etcd-restore-operator\n        image: quay.io/coreos/etcd-operator:v0.9.4\n        command:\n        - etcd-restore-operator\n        env:\n        - name: MY_POD_NAMESPACE\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.namespace\n        - name: MY_POD_NAME\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.name\n"
  },
  {
    "path": "third_party/etcd-operator/example/etcd-restore-operator/deployment_qcloud.yaml",
    "content": "apiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: etcd-restore-operator\n  labels:\n    name: etcd-restore-operator\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        name: etcd-restore-operator\n    spec:\n      containers:\n      - name: etcd-restore-operator\n        image: ccr.ccs.tencentyun.com/etcd-dev/etcd-operator:latest\n        imagePullPolicy: Always\n        command:\n        - etcd-restore-operator\n        env:\n        - name: MY_POD_NAMESPACE\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.namespace\n        - name: MY_POD_NAME\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.name\n"
  },
  {
    "path": "third_party/etcd-operator/example/etcd-restore-operator/restore_cr.yaml",
    "content": "apiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdRestore\"\nmetadata:\n  # The restore CR name must be the same as spec.etcdCluster.name\n  name: example-etcd-cluster\nspec:\n  etcdCluster:\n    # The namespace is the same as this EtcdRestore CR\n    name: example-etcd-cluster\n  backupStorageType: S3\n  s3:\n    # The format of \"path\" must be: \"<s3-bucket-name>/<path-to-backup-file>\"\n    # e.g: \"mybucket/etcd.backup\"\n    path: <full-s3-path>\n    awsSecret: <aws-secret>\n"
  },
  {
    "path": "third_party/etcd-operator/example/etcd-restore-operator/restore_cr_qcloud.yaml",
    "content": "apiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdRestore\"\nmetadata:\n  # The restore CR name must be the same as spec.etcdCluster.name\n  name: cos-test\nspec:\n  etcdCluster:\n    # The namespace is the same as this EtcdRestore CR\n    name: cos-test\n  backupStorageType: COS\n  cos:\n    # The format of \"path\" must be: \"<s3-bucket-name>/<path-to-backup-file>\"\n    # e.g: \"mybucket/etcd.backup\"\n    path: bucket-test.cos.ap-shanghai.myqcloud.com/cos-test/xxx\n    cosSecret: cos-secret\n"
  },
  {
    "path": "third_party/etcd-operator/example/example-etcd-cluster-nodeport-service.json",
    "content": "{\n    \"kind\": \"Service\",\n    \"apiVersion\": \"v1\",\n    \"metadata\": {\n        \"name\": \"example-etcd-cluster-client-service\"\n    },\n    \"spec\": {\n        \"selector\": {\n            \"etcd_cluster\": \"example-etcd-cluster\",\n            \"app\": \"etcd\"\n        },\n        \"ports\": [\n            {\n                \"protocol\": \"TCP\",\n                \"port\": 2379,\n                \"targetPort\": 2379,\n                \"nodePort\": 32379\n            }\n        ],\n        \"type\": \"NodePort\"\n    }\n}\n"
  },
  {
    "path": "third_party/etcd-operator/example/example-etcd-cluster.yaml",
    "content": "apiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdCluster\"\nmetadata:\n  name: \"example-etcd-cluster\"\n  ## Adding this annotation make this cluster managed by clusterwide operators\n  ## namespaced operators ignore it\n  # annotations:\n  #   etcd.database.coreos.com/scope: clusterwide\nspec:\n  size: 3\n  version: \"3.2.13\"\n"
  },
  {
    "path": "third_party/etcd-operator/example/rbac/cluster-role-binding-template.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRoleBinding\nmetadata:\n  name: <ROLE_BINDING_NAME>\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: <ROLE_NAME>\nsubjects:\n- kind: ServiceAccount\n  name: default\n  namespace: <NAMESPACE>\n"
  },
  {
    "path": "third_party/etcd-operator/example/rbac/cluster-role-template.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRole\nmetadata:\n  name: <ROLE_NAME>\nrules:\n- apiGroups:\n  - etcd.database.coreos.com\n  resources:\n  - etcdclusters\n  - etcdbackups\n  - etcdrestores\n  verbs:\n  - \"*\"\n- apiGroups:\n  - apiextensions.k8s.io\n  resources:\n  - customresourcedefinitions\n  verbs:\n  - \"*\"\n- apiGroups:\n  - \"\"\n  resources:\n  - pods\n  - services\n  - endpoints\n  - persistentvolumeclaims\n  - events\n  verbs:\n  - \"*\"\n- apiGroups:\n  - apps\n  resources:\n  - deployments\n  verbs:\n  - \"*\"\n# The following permissions can be removed if not using S3 backup and TLS\n- apiGroups:\n  - \"\"\n  resources:\n  - secrets\n  verbs:\n  - get\n"
  },
  {
    "path": "third_party/etcd-operator/example/rbac/create_role.sh",
    "content": "#!/usr/bin/env bash\nset -o errexit\nset -o nounset\nset -o pipefail\n\nETCD_OPERATOR_ROOT=$(dirname \"${BASH_SOURCE}\")/../..\n\nprint_usage() {\n  echo \"$(basename \"$0\") - Create Kubernetes RBAC role and role bindings for etcd-operator\nUsage: $(basename \"$0\") [options...]\nOptions:\n  --role-name=STRING         Name of ClusterRole to create\n                               (default=\\\"etcd-operator\\\", environment variable: ROLE_NAME)\n  --role-binding-name=STRING Name of ClusterRoleBinding to create\n                               (default=\\\"etcd-operator\\\", environment variable: ROLE_BINDING_NAME)\n  --namespace=STRING         namespace to create role and role binding in. Must already exist.\n                               (default=\\\"default\\\", environment variable: NAMESPACE)\n\" >&2\n}\n\nROLE_NAME=\"${ROLE_NAME:-etcd-operator}\"\nROLE_BINDING_NAME=\"${ROLE_BINDING_NAME:-etcd-operator}\"\nNAMESPACE=\"${NAMESPACE:-default}\"\n\nfor i in \"$@\"\ndo\ncase $i in\n    --role-name=*)\n    ROLE_NAME=\"${i#*=}\"\n    ;;\n    --role-binding-name=*)\n    ROLE_BINDING_NAME=\"${i#*=}\"\n    ;;\n    --namespace=*)\n    NAMESPACE=\"${i#*=}\"\n    ;;\n    -h|--help)\n      print_usage\n      exit 0\n    ;;\n    *)\n      print_usage\n      exit 1\n    ;;\nesac\ndone\n\necho \"Creating role with ROLE_NAME=${ROLE_NAME}, NAMESPACE=${NAMESPACE}\"\nsed -e \"s/<ROLE_NAME>/${ROLE_NAME}/g\" \\\n  -e \"s/<NAMESPACE>/${NAMESPACE}/g\" \\\n  \"${ETCD_OPERATOR_ROOT}/example/rbac/cluster-role-template.yaml\" | \\\n  kubectl create -f -\n\necho \"Creating role binding with ROLE_NAME=${ROLE_NAME}, ROLE_BINDING_NAME=${ROLE_BINDING_NAME}, NAMESPACE=${NAMESPACE}\"\nsed -e \"s/<ROLE_NAME>/${ROLE_NAME}/g\" \\\n  -e \"s/<ROLE_BINDING_NAME>/${ROLE_BINDING_NAME}/g\" \\\n  -e \"s/<NAMESPACE>/${NAMESPACE}/g\" \\\n  \"${ETCD_OPERATOR_ROOT}/example/rbac/cluster-role-binding-template.yaml\" | \\\n  kubectl create -f -\n"
  },
  {
    "path": "third_party/etcd-operator/example/rbac/role-binding-template.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1beta1\nkind: RoleBinding\nmetadata:\n  name: <ROLE_BINDING_NAME>\n  namespace: <NAMESPACE>\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: Role\n  name: <ROLE_NAME>\nsubjects:\n- kind: ServiceAccount\n  name: default\n  namespace: <NAMESPACE>\n"
  },
  {
    "path": "third_party/etcd-operator/example/rbac/role-template.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1beta1\nkind: Role\nmetadata:\n  name: <ROLE_NAME>\n  namespace: <NAMESPACE>\nrules:\n- apiGroups:\n  - etcd.database.coreos.com\n  resources:\n  - etcdclusters\n  - etcdbackups\n  - etcdrestores\n  verbs:\n  - \"*\"\n- apiGroups:\n  - \"\"\n  resources:\n  - pods\n  - services\n  - endpoints\n  - persistentvolumeclaims\n  - events\n  verbs:\n  - \"*\"\n- apiGroups:\n  - apps\n  resources:\n  - deployments\n  verbs:\n  - \"*\"\n# The following permissions can be removed if not using S3 backup and TLS\n- apiGroups:\n  - \"\"\n  resources: \n  - secrets\n  verbs:\n  - get\n"
  },
  {
    "path": "third_party/etcd-operator/example/tls/certs/ca-config.json",
    "content": "{\n    \"signing\": {\n        \"default\": {\n            \"expiry\": \"43800h\"\n        },\n        \"profiles\": {\n            \"server\": {\n                \"expiry\": \"43800h\",\n                \"usages\": [\n                    \"signing\",\n                    \"key encipherment\",\n                    \"server auth\"\n                ]\n            },\n            \"client\": {\n                \"expiry\": \"43800h\",\n                \"usages\": [\n                    \"signing\",\n                    \"key encipherment\",\n                    \"client auth\"\n                ]\n            },\n            \"peer\": {\n                \"expiry\": \"43800h\",\n                \"usages\": [\n                    \"signing\",\n                    \"key encipherment\",\n                    \"server auth\",\n                    \"client auth\"\n                ]\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "third_party/etcd-operator/example/tls/certs/ca-csr.json",
    "content": "{\n    \"CN\": \"My own CA\",\n    \"key\": {\n        \"algo\": \"rsa\",\n        \"size\": 2048\n    },\n    \"names\": [\n        {\n            \"C\": \"US\",\n            \"L\": \"CA\",\n            \"O\": \"My Company Name\",\n            \"ST\": \"San Francisco\",\n            \"OU\": \"Org Unit 1\"\n        }\n    ]\n}\n"
  },
  {
    "path": "third_party/etcd-operator/example/tls/certs/etcd-client-ca.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIID3jCCAsagAwIBAgIUKXbvWUAgVnL7iVUcet3e4x1qH70wDQYJKoZIhvcNAQEL\nBQAwdTELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDVNhbiBGcmFuY2lzY28xCzAJBgNV\nBAcTAkNBMRgwFgYDVQQKEw9NeSBDb21wYW55IE5hbWUxEzARBgNVBAsTCk9yZyBV\nbml0IDExEjAQBgNVBAMTCU15IG93biBDQTAeFw0xNzEwMzEyMjUzMDBaFw0yMjEw\nMzAyMjUzMDBaMHUxCzAJBgNVBAYTAlVTMRYwFAYDVQQIEw1TYW4gRnJhbmNpc2Nv\nMQswCQYDVQQHEwJDQTEYMBYGA1UEChMPTXkgQ29tcGFueSBOYW1lMRMwEQYDVQQL\nEwpPcmcgVW5pdCAxMRIwEAYDVQQDEwlNeSBvd24gQ0EwggEiMA0GCSqGSIb3DQEB\nAQUAA4IBDwAwggEKAoIBAQDgwydE2HYdqTiz//bMSL/C4w2y4DDMjGZgNdo50VIl\nQniiNDrPRB8Xt1fY4MO3VAyLWU934YKssrsqSDn1PE/Fcc5yURKaMc+rsSlGr8Qn\nE/W551OuEIAKujPKhIIBk6X4mBVQWEQnjVskAD0aEjYtoo4I/+9F67Rklub5fXwE\nESsB5yf812zWSzC51Ls0s1Uc80h5buh4p7HtFDOY0oCNxNx2Ou21xn5qqpG/1flY\nReHHKmuvRWwnxQdQu+qrill8j/H48Ly6ZGSV47Qqiw7Hb2JK2vnsf95Pp8nEProU\n53M5V5y5WHW8VH0sVgzjgc0rC0w0TCCQVkGUSttqFpdJAgMBAAGjZjBkMA4GA1Ud\nDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgECMB0GA1UdDgQWBBSgWCYJFFoa\n6O22U4MaelWJt3khUDAfBgNVHSMEGDAWgBSgWCYJFFoa6O22U4MaelWJt3khUDAN\nBgkqhkiG9w0BAQsFAAOCAQEA1ELpWokOl1kwD5fbuROUZ9YedhXVRBWUKKluqQCr\neUUU7x/txKZ4xRYr3s1ltuUjxOMs5XbJSJq1z3tifDQ1srDjyU2CkKtZfjX5xmaS\nQHCEJv/WgC6SBHGVYAgZ1hONPN2WpWxDYOLf6seonLszCHLkHMmjub8uFi/TSP8x\n5OQ2SYLpHQDQcb3xlwk6+09ZuihAzWAgNAOvW+cNrunlD7N+BBTWMZmugKzqk0BT\navTn+p4dimFk528Iz+bk2uCfmF9WlnHm9DmlwCwM4PioGND7ag1VXAsgkqRWGa3k\nuCP+NP3PpnGJLfxV5u20YlNLJk8bVFMB6FoFMafREVMQBA==\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "third_party/etcd-operator/example/tls/certs/etcd-client.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDzzCCAregAwIBAgIUFr+6DAbtFSnfqm4Aup/yPagMWB8wDQYJKoZIhvcNAQEL\nBQAwdTELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDVNhbiBGcmFuY2lzY28xCzAJBgNV\nBAcTAkNBMRgwFgYDVQQKEw9NeSBDb21wYW55IE5hbWUxEzARBgNVBAsTCk9yZyBV\nbml0IDExEjAQBgNVBAMTCU15IG93biBDQTAeFw0xNzEwMzEyMjUzMDBaFw0yMjEw\nMzAyMjUzMDBaMEgxCzAJBgNVBAYTAlVTMRYwFAYDVQQIEw1TYW4gRnJhbmNpc2Nv\nMQswCQYDVQQHEwJDQTEUMBIGA1UEAxMLZXRjZCBjbGllbnQwggEiMA0GCSqGSIb3\nDQEBAQUAA4IBDwAwggEKAoIBAQDBA3WhHLwWPFeaqsDIvwkqnszPIiCpyDdLkpTx\nXcjM6PTiA/hA2y3WRlcQrBsPAcGyj3V+fGxOCGTIktoKLvFk4GjGR6zw+hfIGwSe\nhbuPAQnkaoCsctrgeRjyv7TUb9N4KzXOYfP/RHAtZxh+91gmo/oF/kgzJz+MFR/y\nOodBzzdXp7ZAumt0HUB5kqDxQDNXftnquK0WWvjU9geoYwFuHZ4J25p18RmMkL7p\nhAWK+MB8+DgTMDP3SGh7SwdVS41UJhJTxK6C/ebj5fMjMNmsinAtCt39pvgwcP7y\np3k/IPoXxWBqRaC3NZW8Mq/dFVMVdcDZ9kzXWiRuvVnCpwzzAgMBAAGjgYMwgYAw\nDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMCMAwGA1UdEwEB/wQC\nMAAwHQYDVR0OBBYEFNJTsiGVvKItIERnVbqCz9kpQoDyMB8GA1UdIwQYMBaAFKBY\nJgkUWhro7bZTgxp6VYm3eSFQMAsGA1UdEQQEMAKCADANBgkqhkiG9w0BAQsFAAOC\nAQEAjleSdnxhceY4/muz9HsC1Fk9Yh/KqkMZWMbKCSGyDGR27hS69RJ5VSpfHV6O\n2BzXrhH7ygbnqGIl9BreBVOuYsNK/Z2l/h1vwRmehpjlht1LWQAYgSsS24RxgFSL\nw2QREI+3hYtnOW7ESnnZTD5xlNJenR1iQx7+R+1Y4R2viqN6s8WF30p7q28EzBVR\n+jlqezpwDhmIRTv91IQhrhmkn/xFtg0ZiIS/AGbjKpPKmVw19mweh2TRscV1V8Gk\n0nCV8xvREELZyFLNyXdlkhVMyE2f0Dp4uYcPwuPlGTFcQOmELirzi0Gw94WaoIPO\n58JdskKHXTJdzbV15WYM/KD8Kw==\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "third_party/etcd-operator/example/tls/certs/etcd-client.json",
    "content": "{\n    \"CN\": \"etcd client\",\n    \"hosts\": [\"\"],\n    \"key\": {\n        \"algo\": \"rsa\",\n        \"size\": 2048\n    },\n    \"names\": [\n        {\n            \"C\": \"US\",\n            \"L\": \"CA\",\n            \"ST\": \"San Francisco\"\n        }\n    ]\n}\n\n"
  },
  {
    "path": "third_party/etcd-operator/example/tls/certs/etcd-client.key",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAwQN1oRy8FjxXmqrAyL8JKp7MzyIgqcg3S5KU8V3IzOj04gP4\nQNst1kZXEKwbDwHBso91fnxsTghkyJLaCi7xZOBoxkes8PoXyBsEnoW7jwEJ5GqA\nrHLa4HkY8r+01G/TeCs1zmHz/0RwLWcYfvdYJqP6Bf5IMyc/jBUf8jqHQc83V6e2\nQLprdB1AeZKg8UAzV37Z6ritFlr41PYHqGMBbh2eCduadfEZjJC+6YQFivjAfPg4\nEzAz90hoe0sHVUuNVCYSU8Sugv3m4+XzIzDZrIpwLQrd/ab4MHD+8qd5PyD6F8Vg\nakWgtzWVvDKv3RVTFXXA2fZM11okbr1ZwqcM8wIDAQABAoIBAQCF26tZl/8NgL3U\nwzU+Q9bMmyM5R9bVSMiofbkUB9G54pnqoYwrFpacc13wbxu49aPq/TkkBpBqMcIL\npGTZCSNarZOcZ5sV6KxTmAFFG0Qvci31HrOsZV9MrE9UEwYLCp7jSTxgrGg2kbUm\nl8hSTaHx8mj0fRx/dWnJ8eCc8mBZj3LO6A9w1bSa53LGh5LggyxDFwRfECXcUEAI\nRWFkP8QWVweSzbScHomVEQ3Wn0isBgMF3s5hcdvu6txkS+p12/M7ZXk1cgXZTNtM\n6WUhX/uP/NrcA4b5NIRiW5hQ0qgGsCcVD7Tq3fBHZbt6dfRsPE+XIkQF79lmIRIu\nDYeamONxAoGBANktHJ25DJ9lB99kIF8wTm1F0Xv1rfkz2YrW38MVhOErDfDurgTk\n4VTcIfV8gNTmI/LLIOvk9B2nzm2wWJWFO2XRdEuTbWjQQn/po8G5mEKieYiHFHY1\n0vx2HrwzZAtuxz0ceHC6aEoYg76w4a7ILiSw4eoMsIBjci7Q8kO3HUPJAoGBAOOE\nj812IJylsdPiYAFlnqmm4+XPqXnXA8juUzlZr69GTgtwb0o6ZmnvmNPwErBXPwaB\nDzWauENu5Tg1PxBjxBCxCjDlJcizhbGNaGLn8TphVpzg3roIWEqn6LR8es7WGao1\nH9TyUSKGCSqCnszVhdBw+DyFxnKCKi8VXbHfFZDbAoGBAI6POlWef1aybzSI+WcC\nwrigOB7y6rzG+GpXGpNosM1OAdzCEKFNzUxzJCeNDtSyLa7XAElZBZXh7XO7aqrb\nxl3T3E8v+4XuD3j/2Wr1daloFfc1FI10T4dB0nMgGPAYS9klsznsY0EgTnsCiWK+\nLOwQ4HtO0R22KeHpbt5ceW1hAoGBAJ3TWUX3ycugjWkkQeD2M0gQg0rp8PCaHQAH\ngyfndR2rMXxx9GGTfXPDR0rN4Mj+3LOQV5Khz2zHwq5pEWQ3MM07YoxkiP9euUFf\njKf/qbEL0N9mhlqaa1TugViieTZ+ArO1wm0f4vSF8lnQ3oPNItRjaW/ihLTuYoDi\n22oGDJm9AoGAS7rQk9SkMvg0miOGJJSKPwhLjvPRLxYWE/X9DkSpJPLdlay7LXj2\no9kytsNQ305U+aB55h1MkpI22TxClFIJ0YiPHOoYuvvEJ6YCpphZiNdRQVT/8Unv\nsCV40oCU+RDsJNC4FAuVnXAovdT1VHkhZum7i25oto+C0hdZGpSlloM=\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "third_party/etcd-operator/example/tls/certs/gen-cert.sh",
    "content": "#!/usr/bin/env bash\n\necho \"generating CA certs ===\"\ncfssl gencert -initca ca-csr.json | cfssljson -bare ca -\n\necho \"generating etcd peer certs ===\"\ncfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=peer peer.json | cfssljson -bare peer\n\necho \"generating etcd server certs ===\"\ncfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server server.json | cfssljson -bare server\n\necho \"generating etcd client certs ===\"\ncfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client etcd-client.json | cfssljson -bare etcd-client\n\nmv etcd-client.pem etcd-client.crt\nmv etcd-client-key.pem etcd-client.key\ncp ca.pem etcd-client-ca.crt\n\nmv server.pem server.crt\nmv server-key.pem server.key\ncp ca.pem server-ca.crt\n\nmv peer.pem peer.crt\nmv peer-key.pem peer.key\nmv ca.pem peer-ca.crt\n\nrm *.csr ca-key.pem\n"
  },
  {
    "path": "third_party/etcd-operator/example/tls/certs/peer-ca.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIID3jCCAsagAwIBAgIUKXbvWUAgVnL7iVUcet3e4x1qH70wDQYJKoZIhvcNAQEL\nBQAwdTELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDVNhbiBGcmFuY2lzY28xCzAJBgNV\nBAcTAkNBMRgwFgYDVQQKEw9NeSBDb21wYW55IE5hbWUxEzARBgNVBAsTCk9yZyBV\nbml0IDExEjAQBgNVBAMTCU15IG93biBDQTAeFw0xNzEwMzEyMjUzMDBaFw0yMjEw\nMzAyMjUzMDBaMHUxCzAJBgNVBAYTAlVTMRYwFAYDVQQIEw1TYW4gRnJhbmNpc2Nv\nMQswCQYDVQQHEwJDQTEYMBYGA1UEChMPTXkgQ29tcGFueSBOYW1lMRMwEQYDVQQL\nEwpPcmcgVW5pdCAxMRIwEAYDVQQDEwlNeSBvd24gQ0EwggEiMA0GCSqGSIb3DQEB\nAQUAA4IBDwAwggEKAoIBAQDgwydE2HYdqTiz//bMSL/C4w2y4DDMjGZgNdo50VIl\nQniiNDrPRB8Xt1fY4MO3VAyLWU934YKssrsqSDn1PE/Fcc5yURKaMc+rsSlGr8Qn\nE/W551OuEIAKujPKhIIBk6X4mBVQWEQnjVskAD0aEjYtoo4I/+9F67Rklub5fXwE\nESsB5yf812zWSzC51Ls0s1Uc80h5buh4p7HtFDOY0oCNxNx2Ou21xn5qqpG/1flY\nReHHKmuvRWwnxQdQu+qrill8j/H48Ly6ZGSV47Qqiw7Hb2JK2vnsf95Pp8nEProU\n53M5V5y5WHW8VH0sVgzjgc0rC0w0TCCQVkGUSttqFpdJAgMBAAGjZjBkMA4GA1Ud\nDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgECMB0GA1UdDgQWBBSgWCYJFFoa\n6O22U4MaelWJt3khUDAfBgNVHSMEGDAWgBSgWCYJFFoa6O22U4MaelWJt3khUDAN\nBgkqhkiG9w0BAQsFAAOCAQEA1ELpWokOl1kwD5fbuROUZ9YedhXVRBWUKKluqQCr\neUUU7x/txKZ4xRYr3s1ltuUjxOMs5XbJSJq1z3tifDQ1srDjyU2CkKtZfjX5xmaS\nQHCEJv/WgC6SBHGVYAgZ1hONPN2WpWxDYOLf6seonLszCHLkHMmjub8uFi/TSP8x\n5OQ2SYLpHQDQcb3xlwk6+09ZuihAzWAgNAOvW+cNrunlD7N+BBTWMZmugKzqk0BT\navTn+p4dimFk528Iz+bk2uCfmF9WlnHm9DmlwCwM4PioGND7ag1VXAsgkqRWGa3k\nuCP+NP3PpnGJLfxV5u20YlNLJk8bVFMB6FoFMafREVMQBA==\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "third_party/etcd-operator/example/tls/certs/peer.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIIEETCCAvmgAwIBAgIUY5HWQmhEKqvuoS4dGe74MUpfp+swDQYJKoZIhvcNAQEL\nBQAwdTELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDVNhbiBGcmFuY2lzY28xCzAJBgNV\nBAcTAkNBMRgwFgYDVQQKEw9NeSBDb21wYW55IE5hbWUxEzARBgNVBAsTCk9yZyBV\nbml0IDExEjAQBgNVBAMTCU15IG93biBDQTAeFw0xNzEwMzEyMjUzMDBaFw0yMjEw\nMzAyMjUzMDBaMEYxCzAJBgNVBAYTAlVTMRYwFAYDVQQIEw1TYW4gRnJhbmNpc2Nv\nMQswCQYDVQQHEwJDQTESMBAGA1UEAxMJZXRjZCBwZWVyMIIBIjANBgkqhkiG9w0B\nAQEFAAOCAQ8AMIIBCgKCAQEAzvv3cmbiO5Q68T6VF+UJq0hlI5zs+AUhnhEF9Oth\nL52oOckQGSt9RiuywBKmBsESFLm+gfP6waQFvVl4QazckTCIZx2qze0sfxQzWWNI\nxySePfx7E/aZvWVfeJROMLRVZ530K2K0zPdCc1vxyGTkpFSg6qO5pY6g2appfKIZ\nzF+HE1exDgagCvFpnQ3zheSY6F4S47r4UMnH6aeSGsyE1RZVL91K9+MURRjjpr/1\nySB+It4wfk458g6RiNuKtm4NtQRDkaf4zki4paiRVAz8418k0tL9pWzdbxk9LWJx\nJy4tHmy/m9h4lT8wS0Fav4J5SlWJwxqTWlco3fUgrSgOfQIDAQABo4HHMIHEMA4G\nA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYD\nVR0TAQH/BAIwADAdBgNVHQ4EFgQUXHY98bMHb7Jq5VmVOk+cvqJT2tAwHwYDVR0j\nBBgwFoAUoFgmCRRaGujttlODGnpVibd5IVAwRQYDVR0RBD4wPIIVKi5leGFtcGxl\nLmRlZmF1bHQuc3ZjgiMqLmV4YW1wbGUuZGVmYXVsdC5zdmMuY2x1c3Rlci5sb2Nh\nbDANBgkqhkiG9w0BAQsFAAOCAQEAqnJ4DgqC5JZYYjrQdGHP9NQ8fUyy2AVT9KOj\ns6Ik/bTtwSJ7vTEG+yFDJSlyAWLPYl09rXm+aQ73FFKZihN5ptqpQjyjfqh3jfoC\nDjzFNSxOoGJMwNufLZezD1P3JE26EZPnt9rBd6EGKgDfSMSKCSTjYYpSP93OM816\n3dUkbdiPzAtGN/Q9NFdYY42UyjXAj2c+hmPUr41pZSTW2lzNvLpXrB7nMZH6hjIX\n7BemrTR0X+nG/wiJPKMAjizrhiXfMBA8eqo3fota98cDKDWdIKhgIFOZ26wJpoit\nHm1WUJCvgR6+Ujg3tIWTJdmMn3wnqlXKfM/uoihlV1DmHYw7pg==\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "third_party/etcd-operator/example/tls/certs/peer.json",
    "content": "{\n    \"CN\": \"etcd peer\",\n    \"hosts\": [\n        \"*.example.default.svc\",\n        \"*.example.default.svc.cluster.local\"\n    ],\n    \"key\": {\n        \"algo\": \"rsa\",\n        \"size\": 2048\n    },\n    \"names\": [\n        {\n            \"C\": \"US\",\n            \"L\": \"CA\",\n            \"ST\": \"San Francisco\"\n        }\n    ]\n}\n\n"
  },
  {
    "path": "third_party/etcd-operator/example/tls/certs/peer.key",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAzvv3cmbiO5Q68T6VF+UJq0hlI5zs+AUhnhEF9OthL52oOckQ\nGSt9RiuywBKmBsESFLm+gfP6waQFvVl4QazckTCIZx2qze0sfxQzWWNIxySePfx7\nE/aZvWVfeJROMLRVZ530K2K0zPdCc1vxyGTkpFSg6qO5pY6g2appfKIZzF+HE1ex\nDgagCvFpnQ3zheSY6F4S47r4UMnH6aeSGsyE1RZVL91K9+MURRjjpr/1ySB+It4w\nfk458g6RiNuKtm4NtQRDkaf4zki4paiRVAz8418k0tL9pWzdbxk9LWJxJy4tHmy/\nm9h4lT8wS0Fav4J5SlWJwxqTWlco3fUgrSgOfQIDAQABAoIBAAOuu/JPHktNEddk\n86YfLxLbEOGXUyf+f2CekOqQnYQJXArbJuwrt+jdsip0qnuIR9gSje8l9hon3upF\ngzw35Ry4LlUXVAih5Z7FLzyx5YOVhTM5IL90LbwO56nviYyYSMS1LLjw4qKa65W9\n1wlnsiGyV8KU8yKc7QOyYnoTMD5QlJTMrIyQz0JJYXpnKJ7nUVkVVF2EaJANloYU\nbh6hyWBayup6EcHNrvpaGejbp1Zd+ByTTy0O1vSc6c+nMozJWeZo8XgXuAtZAgth\n3Yll7esUvBkwG/AFxO+ernD7oOFjEVNYXopph+jsQlBHxkxFhLTincicabyU81wv\nUJ4Gv0kCgYEA2k0len5xQVXiRm2EeLvhs3gGwe+ymehgXorhznrlfZLcrB9dzGsj\nnNKy59vwG45/oY+y2lA45WBY0wBvrRIY9yhAomukzXyKnDgcDnUDzwCO0bZ+0FIi\neGykyB8VRiOgDWuID2FXDLyBdcNwGj5nzHt1mL3rKTXcGzDC9Nmhfi8CgYEA8rqA\n9NyRdNxwO2JVcK0LLx71E7s3xmAJHst2PecO/D/+GhNa/zyDk4rAYeTQsBHxjWp1\nmbjWiPF229QqZOQGVkXh9FoBYflAOHH1sgR6Lhpv5qr+Tcpabl1vLK0+RLLFS4Ta\nnSzgoxMa/LepKontO237BPMje30HlKwraJFcHxMCgYEAqCZ+dPFKaaou5lLblGgc\nPTJ5+g6ZQwYEnS5bKsHtXaGvSwHKLXhlcRm25vO56nAEDb1zZcgfW0ewg681Vlm3\nU0H1L2a9Be8lkZmCuvwVV/C1EgKBghOSK7J75w5SQ7mTQmMO5dHzzIKzMbO9+OkS\n6SY7+dBogFDVXzhbI2EzjM8CgYEA56tYn9zRu/8V46gEMmoHDa93bKC5KE7LBahe\nL9ET/XC6f3rP1GKWlsDMw+KXyCUoLrhYjCLeKJCGyGQlHmyBG+DRO96YCUHTqMwk\nHAen8c7r1PaJiAfF7iahkLu9feY+5shju7Z0pVD75g8Jl/9S/PEIr/28dQWtsZnu\nSHzMtx8CgYEAiSJ30r6jnp1fQbsYIaTaeHUwh8QDBlA5K71L0oBADTucPV3i5unV\nBMFFZ97uH0NEhOGL4l2ZgzLX85Lk9abLrMP04TuxRxt6nPctPB8/RY0RdrwTtbmo\n35YK9y08MtHOn7H5CRarrgOJAZPyk4VPdscP+xXNuIP4uS0Z0qLtdRI=\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "third_party/etcd-operator/example/tls/certs/server-ca.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIID3jCCAsagAwIBAgIUKXbvWUAgVnL7iVUcet3e4x1qH70wDQYJKoZIhvcNAQEL\nBQAwdTELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDVNhbiBGcmFuY2lzY28xCzAJBgNV\nBAcTAkNBMRgwFgYDVQQKEw9NeSBDb21wYW55IE5hbWUxEzARBgNVBAsTCk9yZyBV\nbml0IDExEjAQBgNVBAMTCU15IG93biBDQTAeFw0xNzEwMzEyMjUzMDBaFw0yMjEw\nMzAyMjUzMDBaMHUxCzAJBgNVBAYTAlVTMRYwFAYDVQQIEw1TYW4gRnJhbmNpc2Nv\nMQswCQYDVQQHEwJDQTEYMBYGA1UEChMPTXkgQ29tcGFueSBOYW1lMRMwEQYDVQQL\nEwpPcmcgVW5pdCAxMRIwEAYDVQQDEwlNeSBvd24gQ0EwggEiMA0GCSqGSIb3DQEB\nAQUAA4IBDwAwggEKAoIBAQDgwydE2HYdqTiz//bMSL/C4w2y4DDMjGZgNdo50VIl\nQniiNDrPRB8Xt1fY4MO3VAyLWU934YKssrsqSDn1PE/Fcc5yURKaMc+rsSlGr8Qn\nE/W551OuEIAKujPKhIIBk6X4mBVQWEQnjVskAD0aEjYtoo4I/+9F67Rklub5fXwE\nESsB5yf812zWSzC51Ls0s1Uc80h5buh4p7HtFDOY0oCNxNx2Ou21xn5qqpG/1flY\nReHHKmuvRWwnxQdQu+qrill8j/H48Ly6ZGSV47Qqiw7Hb2JK2vnsf95Pp8nEProU\n53M5V5y5WHW8VH0sVgzjgc0rC0w0TCCQVkGUSttqFpdJAgMBAAGjZjBkMA4GA1Ud\nDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgECMB0GA1UdDgQWBBSgWCYJFFoa\n6O22U4MaelWJt3khUDAfBgNVHSMEGDAWgBSgWCYJFFoa6O22U4MaelWJt3khUDAN\nBgkqhkiG9w0BAQsFAAOCAQEA1ELpWokOl1kwD5fbuROUZ9YedhXVRBWUKKluqQCr\neUUU7x/txKZ4xRYr3s1ltuUjxOMs5XbJSJq1z3tifDQ1srDjyU2CkKtZfjX5xmaS\nQHCEJv/WgC6SBHGVYAgZ1hONPN2WpWxDYOLf6seonLszCHLkHMmjub8uFi/TSP8x\n5OQ2SYLpHQDQcb3xlwk6+09ZuihAzWAgNAOvW+cNrunlD7N+BBTWMZmugKzqk0BT\navTn+p4dimFk528Iz+bk2uCfmF9WlnHm9DmlwCwM4PioGND7ag1VXAsgkqRWGa3k\nuCP+NP3PpnGJLfxV5u20YlNLJk8bVFMB6FoFMafREVMQBA==\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "third_party/etcd-operator/example/tls/certs/server.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIIECzCCAvOgAwIBAgIUJ9A0ORmRWaag95KE7Mw7ZEeAsqwwDQYJKoZIhvcNAQEL\nBQAwdTELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDVNhbiBGcmFuY2lzY28xCzAJBgNV\nBAcTAkNBMRgwFgYDVQQKEw9NeSBDb21wYW55IE5hbWUxEzARBgNVBAsTCk9yZyBV\nbml0IDExEjAQBgNVBAMTCU15IG93biBDQTAeFw0xNzEwMzEyMjUzMDBaFw0yMjEw\nMzAyMjUzMDBaMEgxCzAJBgNVBAYTAlVTMRYwFAYDVQQIEw1TYW4gRnJhbmNpc2Nv\nMQswCQYDVQQHEwJDQTEUMBIGA1UEAxMLZXRjZCBzZXJ2ZXIwggEiMA0GCSqGSIb3\nDQEBAQUAA4IBDwAwggEKAoIBAQDHQ27rtTF+U5X67gpWf4tmAnG9P/p2PzVltqWi\njn2niHcAm3rA2ZyKa97REIg43j3K9+mfcah36fY6h567OfxuOU3MY5Nf7A/EchxZ\nqqiGCyghwXBWs7kspucxr3KIrlZD8ZFshLDKwKJuHonxBqZgU90gCGrex+RnYRO3\nfUBWXTua/d+k5kKXSrpSYQhevZX3QxPwhBYc1a6tEgNcTi4hQWjNoVNVq0vySps3\n5eOzh/vD7Y6iFimp6EkRDfqfEUG9Vt1ngfILqP/P3chHVFkBPGLWYqGrD7jELmry\nDtHfbFUuzZJcz4I5FxE6V0LdkOEbI7VGqLcCFokwzi3gCkF9AgMBAAGjgb8wgbww\nDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQC\nMAAwHQYDVR0OBBYEFAt3OUO1pMZ4rQSzKbebIWE/PbYEMB8GA1UdIwQYMBaAFKBY\nJgkUWhro7bZTgxp6VYm3eSFQMEcGA1UdEQRAMD6CFSouZXhhbXBsZS5kZWZhdWx0\nLnN2Y4IaZXhhbXBsZS1jbGllbnQuZGVmYXVsdC5zdmOCCWxvY2FsaG9zdDANBgkq\nhkiG9w0BAQsFAAOCAQEAjdkgFCI0ySHIf3QyfckcoCpPVTU+S3g4gRp+RWGbQ2yp\npgAJBBG6tFZRu9VGhj2uDtqDxyp1igKs4aOA95Amm92/k9y8Xw1LMPNIdmst/1ol\nUbLrFfhxwYbZTpn0FDESHrRNX8j5UlRFsoqcW6CXdem8DL2MB5eshnpKZMLABoqM\nEzNRvfnJ4tkH9T949nJkjXcih/0UWg/S/P9MsXMxbXpuDxivynMcBUQxPfdkMzTV\nBwogyJn/f508ahlmlwb0JM5D7RLhHndBP1hbs00KE8g927PkpL8QNBW/DL2bjS0y\nUI/MmAWRZiP6LAj+3H12QbbCmG5LvY+Ujbz28qSuXg==\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "third_party/etcd-operator/example/tls/certs/server.json",
    "content": "{\n    \"CN\": \"etcd server\",\n    \"hosts\": [\n        \"*.example.default.svc\",\n        \"example-client.default.svc\",\n        \"localhost\"\n    ],\n    \"key\": {\n        \"algo\": \"rsa\",\n        \"size\": 2048\n    },\n    \"names\": [\n        {\n            \"C\": \"US\",\n            \"L\": \"CA\",\n            \"ST\": \"San Francisco\"\n        }\n    ]\n}\n\n"
  },
  {
    "path": "third_party/etcd-operator/example/tls/certs/server.key",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAx0Nu67UxflOV+u4KVn+LZgJxvT/6dj81Zbaloo59p4h3AJt6\nwNmcimve0RCION49yvfpn3God+n2Ooeeuzn8bjlNzGOTX+wPxHIcWaqohgsoIcFw\nVrO5LKbnMa9yiK5WQ/GRbISwysCibh6J8QamYFPdIAhq3sfkZ2ETt31AVl07mv3f\npOZCl0q6UmEIXr2V90MT8IQWHNWurRIDXE4uIUFozaFTVatL8kqbN+Xjs4f7w+2O\nohYpqehJEQ36nxFBvVbdZ4HyC6j/z93IR1RZATxi1mKhqw+4xC5q8g7R32xVLs2S\nXM+CORcROldC3ZDhGyO1Rqi3AhaJMM4t4ApBfQIDAQABAoIBADYtnIwUAPgDDAVl\nEYSBO0qqIXi+W4ApIYCdT53KNloF3a1ZmN+0iz6Lo9KeNxuXOZ/lFi1W/uJTx7IU\nS9FGK99gT0niTSDIk2TrTdAHebiwceHzsXKxfQip/LRiqraFCEmC9fJWhacrBz7/\nqKvTDguk4bui7kPSf8Sn/W9na8XPKssoPEzYR/sPUh3D8TcdrWZrS2R+6xaLr2Pm\nHi5ZtF9eW4n2biRxXvIFGI76BrFE8UlHcdau7YdTrHQhbLz+go43T02iV4eKdSzp\nA3OJDyKbut4fTPWx4rlk1ysaianpdXDaFxXzZd7vXvLq5VfxO17D3Ti9uhjBQE9J\nYzUbFPUCgYEA6s9aWhmmMtzoEBt2FngjfDrRxI2Yp0yASvh2bDCO+b5/P8F0uLKU\nHcOmJG1949212nPQ9SDnRSSM9joRA3HKP/gRx8KGKoFsQadMnW7tOnEwKJvDWe6V\nDypW36zI4YicJJOX+UbLHStom24Y7O7q59wp726p8piy3Sa/MHz2ZAcCgYEA2T7f\noBP76IuTDKOzk3QO0ow7fsVQCM28h2JLMYFnGQQksDvFgdeM4Y8dONrVVahXVH+N\n7CAnZ5H3wFEXpXetyuwplEmhfzDnyERvi0udxmYrug0xOu+DCEJP3w7T4pHCDEho\nEa3sbwTmZC4ckfkR/gQKR8RxX2R/6n93rDj29VsCgYEAt3teA+flCfu6ztNWnEo2\nmF2yCuAGeDx8R5kNmI79OkRUVPKLjcPln7iBfBee9s8JynETyGh0r3/XMpS/NKzX\nONNUuX7UriRB/q+HW8IRV8iYtDK7HOwkyBvylIgE1M+WC7LVX3GlR97iuAn5KjOr\nlZBhqHoWDL6rjco4PeB3/EMCgYEAvOCIJrIZOzZWdA/DqjimRnI7q90611ygRAi2\nnWUHUN2kVECzWE8iolz+KBdCkYWZ39JCfv/5ondrMp6Oc4NY62tmPxHBQkcvzZOK\nc04b74mXDNw5aCcjAkQ9Ew7eM0dMsccmC/Dt9hwJfyIEHvmwpeu3UGw/sZM8D5Ih\nZu/j7q8CgYAv76kxhx/jxdX77FNflAhM7HK+hpcpJPzy/e/Jle+jbMki6d5lytCp\nDjRPVsgVUV6FGOSLRcDzbOyfwVRJduToLox2UUGVJaPRid8D/Y5+HGs2yyKG7ubz\nSzH3mMv+TDPFmVsKlECMUgr1aEKJRQf2KcLFioXZlLAIRuzDufnCnw==\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "third_party/etcd-operator/example/tls/example-tls-cluster.yaml",
    "content": "apiVersion: \"etcd.database.coreos.com/v1beta2\"\nkind: \"EtcdCluster\"\nmetadata:\n  name: \"example\"\nspec:\n  size: 3\n  TLS:\n    static:\n      member:\n        peerSecret: etcd-peer-tls\n        serverSecret: etcd-server-tls\n      operatorSecret: etcd-client-tls\n\n"
  },
  {
    "path": "third_party/etcd-operator/go.mod",
    "content": "module github.com/coreos/etcd-operator\n\ngo 1.12\n\nrequire (\n\tcloud.google.com/go v0.38.0\n\tgit.apache.org/thrift.git v0.0.0-20181218151757-9b75e4fe745a // indirect\n\tgithub.com/Azure/azure-sdk-for-go v11.3.0-beta+incompatible\n\tgithub.com/Azure/go-autorest v11.1.1+incompatible\n\tgithub.com/PuerkitoBio/purell v1.1.1\n\tgithub.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578\n\tgithub.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190125095113-2b29687e15f2\n\tgithub.com/aws/aws-sdk-go v1.13.8\n\tgithub.com/beorn7/perks v1.0.0\n\tgithub.com/coreos/etcd v3.3.10+incompatible\n\tgithub.com/davecgh/go-spew v1.1.1\n\tgithub.com/dgrijalva/jwt-go v3.2.0+incompatible\n\tgithub.com/emicklei/go-restful v2.9.5+incompatible\n\tgithub.com/ghodss/yaml v1.0.0\n\tgithub.com/go-ini/ini v1.42.0\n\tgithub.com/go-openapi/jsonpointer v0.19.3\n\tgithub.com/go-openapi/jsonreference v0.19.3\n\tgithub.com/go-openapi/spec v0.19.3\n\tgithub.com/go-openapi/swag v0.19.5\n\tgithub.com/gogo/protobuf v1.3.1\n\tgithub.com/golang/glog v0.0.0-20160126235308-23def4e6c14b\n\tgithub.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef\n\tgithub.com/golang/protobuf v1.3.2\n\tgithub.com/google/btree v1.0.0\n\tgithub.com/google/go-querystring v1.0.0\n\tgithub.com/google/gofuzz v1.1.0\n\tgithub.com/googleapis/gax-go v0.0.0-20181219185031-c8a15bac9b9f\n\tgithub.com/googleapis/gnostic v0.2.0\n\tgithub.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc\n\tgithub.com/hashicorp/golang-lru v0.5.1\n\tgithub.com/imdario/mergo v0.3.7\n\tgithub.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8\n\tgithub.com/json-iterator/go v1.1.8\n\tgithub.com/mailru/easyjson v0.7.0\n\tgithub.com/matttproud/golang_protobuf_extensions v1.0.1\n\tgithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd\n\tgithub.com/modern-go/reflect2 v1.0.1\n\tgithub.com/mozillazg/go-httpheader v0.2.1\n\tgithub.com/openzipkin/zipkin-go v0.1.3 // indirect\n\tgithub.com/pborman/uuid v1.2.0\n\tgithub.com/petar/GoLLRB v0.0.0-20130427215148-53be0d36a84c\n\tgithub.com/peterbourgon/diskv v2.0.1+incompatible\n\tgithub.com/pkg/errors v0.8.1\n\tgithub.com/prometheus/client_golang v1.0.0\n\tgithub.com/prometheus/client_model v0.2.0\n\tgithub.com/prometheus/common v0.4.1\n\tgithub.com/prometheus/procfs v0.0.2\n\tgithub.com/satori/uuid v1.2.0\n\tgithub.com/sirupsen/logrus v1.4.2\n\tgithub.com/spf13/pflag v1.0.5\n\tgithub.com/tencentyun/cos-go-sdk-v5 v0.7.31\n\tgo.opencensus.io v0.21.0\n\tgolang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45\n\tgoogle.golang.org/api v0.4.0\n\tgopkg.in/inf.v0 v0.9.1\n\tgopkg.in/yaml.v2 v2.2.8\n\tk8s.io/api v0.18.3\n\tk8s.io/apiextensions-apiserver v0.18.3\n\tk8s.io/apimachinery v0.18.3\n\tk8s.io/client-go v11.0.0+incompatible\n)\n"
  },
  {
    "path": "third_party/etcd-operator/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 h1:ROfEUZz+Gh5pa62DJWXSaonyu3StP6EA6lPEXPI6mCo=\ncloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=\ngit.apache.org/thrift.git v0.0.0-20181218151757-9b75e4fe745a/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=\ngithub.com/Azure/azure-sdk-for-go v11.3.0-beta+incompatible h1:F+Xs1GMaEJnaBa8gY+ogJSCeK34w4PXPYspY0huefbM=\ngithub.com/Azure/azure-sdk-for-go v11.3.0-beta+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=\ngithub.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=\ngithub.com/Azure/go-autorest v11.1.1+incompatible h1:kqw9PTHZBZKk6kSv/S7L/qxKKcz6hBDnmjWJU5RnHTw=\ngithub.com/Azure/go-autorest v11.1.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=\ngithub.com/Azure/go-autorest/autorest v0.9.0 h1:MRvx8gncNaXJqOoLmhNjUAKh33JJF8LyxPhomEtOsjs=\ngithub.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=\ngithub.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=\ngithub.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=\ngithub.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=\ngithub.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=\ngithub.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=\ngithub.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=\ngithub.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=\ngithub.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=\ngithub.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=\ngithub.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=\ngithub.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=\ngithub.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=\ngithub.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=\ngithub.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=\ngithub.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=\ngithub.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=\ngithub.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=\ngithub.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190125095113-2b29687e15f2 h1:7oDAZnIvzxoPhyBFLgiBXEqOpNnqS9CJVeazaQpEzmA=\ngithub.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190125095113-2b29687e15f2/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=\ngithub.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=\ngithub.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=\ngithub.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=\ngithub.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=\ngithub.com/aws/aws-sdk-go v1.13.8 h1:2GXJr7VVErT37gjlGzkRI7Pb0alhJ2Y3XoCRcXRhavQ=\ngithub.com/aws/aws-sdk-go v1.13.8/go.mod h1:ZRmQr0FajVIyZ4ZzBYKG5P3ZqPz9IHG41ZoMu1ADI3k=\ngithub.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=\ngithub.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=\ngithub.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=\ngithub.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=\ngithub.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=\ngithub.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=\ngithub.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=\ngithub.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=\ngithub.com/coreos/etcd v3.3.10+incompatible h1:jFneRYjIvLMLhDLCzuTuU4rSJUjRplcJQ7pD7MnhC04=\ngithub.com/coreos/etcd v3.3.10+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.1.0+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-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=\ngithub.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=\ngithub.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=\ngithub.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=\ngithub.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=\ngithub.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=\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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=\ngithub.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=\ngithub.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=\ngithub.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=\ngithub.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=\ngithub.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=\ngithub.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=\ngithub.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=\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/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=\ngithub.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=\ngithub.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=\ngithub.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=\ngithub.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=\ngithub.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=\ngithub.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=\ngithub.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=\ngithub.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=\ngithub.com/go-ini/ini v1.42.0 h1:TWr1wGj35+UiWHlBA8er89seFXxzwFn11spilrrj+38=\ngithub.com/go-ini/ini v1.42.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=\ngithub.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=\ngithub.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=\ngithub.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=\ngithub.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=\ngithub.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=\ngithub.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=\ngithub.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk=\ngithub.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU=\ngithub.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=\ngithub.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=\ngithub.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=\ngithub.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=\ngithub.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=\ngithub.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=\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/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=\ngithub.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=\ngithub.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=\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/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=\ngithub.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=\ngithub.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=\ngithub.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs=\ngithub.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk=\ngithub.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA=\ngithub.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64=\ngithub.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4=\ngithub.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=\ngithub.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=\ngithub.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=\ngithub.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=\ngithub.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=\ngithub.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=\ngithub.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=\ngithub.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY=\ngithub.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=\ngithub.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=\ngithub.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=\ngithub.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=\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/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=\ngithub.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=\ngithub.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=\ngithub.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=\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.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=\ngithub.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=\ngithub.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=\ngithub.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk=\ngithub.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=\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/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\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 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=\ngithub.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\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/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=\ngithub.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=\ngithub.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=\ngithub.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=\ngithub.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=\ngithub.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=\ngithub.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=\ngithub.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=\ngithub.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=\ngithub.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/googleapis/gax-go v0.0.0-20181219185031-c8a15bac9b9f h1:UagDZv2cTLFNxuFiG5WvbbxtKTwbLWec8QUnFNqS6Ho=\ngithub.com/googleapis/gax-go v0.0.0-20181219185031-c8a15bac9b9f/go.mod h1:5VvnLYVimBt+hOVlFtJDkYQHVmk4K27qHHioZjPbYAI=\ngithub.com/googleapis/gax-go/v2 v2.0.2/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=\ngithub.com/googleapis/gax-go/v2 v2.0.4 h1:hU4mGcQI4DaAYW+IbTun+2qEZVFxK0ySjQLTbS0VQKc=\ngithub.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=\ngithub.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=\ngithub.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=\ngithub.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g=\ngithub.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=\ngithub.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=\ngithub.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=\ngithub.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=\ngithub.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=\ngithub.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=\ngithub.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/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.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=\ngithub.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=\ngithub.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=\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/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=\ngithub.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=\ngithub.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=\ngithub.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=\ngithub.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 h1:12VvqtR6Aowv3l/EQUlocDHW2Cp4G9WJVH7uyH8QFJE=\ngithub.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=\ngithub.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=\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.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok=\ngithub.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=\ngithub.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=\ngithub.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=\ngithub.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=\ngithub.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=\ngithub.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=\ngithub.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=\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/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/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=\ngithub.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=\ngithub.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=\ngithub.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=\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/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=\ngithub.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=\ngithub.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=\ngithub.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=\ngithub.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=\ngithub.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=\ngithub.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=\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 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=\ngithub.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=\ngithub.com/mozillazg/go-httpheader v0.2.1 h1:geV7TrjbL8KXSyvghnFm+NyTux/hxwueTSrwhe88TQQ=\ngithub.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60=\ngithub.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=\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/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=\ngithub.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=\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/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/openzipkin/zipkin-go v0.1.3/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=\ngithub.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=\ngithub.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=\ngithub.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=\ngithub.com/petar/GoLLRB v0.0.0-20130427215148-53be0d36a84c/go.mod h1:HUpKUBZnpzkdx0kD/+Yfuft+uD3zHGtXF/XJB14TUr4=\ngithub.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=\ngithub.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=\ngithub.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=\ngithub.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=\ngithub.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM=\ngithub.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=\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.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw=\ngithub.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=\ngithub.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=\ngithub.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs=\ngithub.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=\ngithub.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=\ngithub.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=\ngithub.com/satori/uuid v1.2.0 h1:6TFY4nxn5XwBx0gDfzbEMCNT6k4N/4FNIuN8RACZ0KI=\ngithub.com/satori/uuid v1.2.0/go.mod h1:B8HLsPLik/YNn6KKWVMDJ8nzCL8RP5WyfsnmvnAEwIU=\ngithub.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=\ngithub.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=\ngithub.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=\ngithub.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=\ngithub.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=\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/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=\ngithub.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=\ngithub.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=\ngithub.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=\ngithub.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=\ngithub.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=\ngithub.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=\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/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/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/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.194/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=\ngithub.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.194/go.mod h1:yrBKWhChnDqNz1xuXdSbWXG56XawEq0G5j1lg4VwBD4=\ngithub.com/tencentyun/cos-go-sdk-v5 v0.0.0-20190717101923-c5c1f9751e7f h1:TzE7Cs9HhTyfot4WIoMnbD1rWfD4Jkwy2M3Zs66CaRE=\ngithub.com/tencentyun/cos-go-sdk-v5 v0.0.0-20190717101923-c5c1f9751e7f/go.mod h1:/4BhymH1yO6ljUGQgcKsd7L3W+pdKRxoRiOuoZPLnGg=\ngithub.com/tencentyun/cos-go-sdk-v5 v0.7.31/go.mod h1:4E4+bQ2gBVJcgEC9Cufwylio4mXOct2iu05WjgEBx1o=\ngithub.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=\ngithub.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=\ngithub.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=\ngithub.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=\ngithub.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=\ngithub.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=\ngithub.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=\ngo.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=\ngo.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=\ngo.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=\ngo.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=\ngo.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=\ngo.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg=\ngo.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=\ngo.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=\ngo.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=\ngo.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=\ngolang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=\ngolang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=\ngolang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/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-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo=\ngolang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=\ngolang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=\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/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\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-20181005035420-146acd28ed58/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-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-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\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-20190813141303-74dc4d7220e7/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-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=\ngolang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\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 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=\ngolang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=\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/sys v0.0.0-20170830134202-bb24a47a89ea/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-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-20190209173611-3b5209105503/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-20190321052220-f7bb7a8bee54/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-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7 h1:HmbHVPwrPEKPGLAcHSrMe6+hqSUlvZU0rab6x5EXfGU=\ngolang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/text v0.0.0-20160726164857-2910a502d2bf/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 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=\ngolang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=\ngolang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=\ngolang.org/x/time v0.0.0-20190308202827-9d24e82272b4/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-20180828015842-6cd1fcedba52/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-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/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-20190125232054-d66bd3c5d5a6/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-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=\ngolang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=\ngolang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngoogle.golang.org/api v0.4.0 h1:KKgc1aqhV8wDPbDzlDtpvyjZFY3vjz85FP7p4wcQUyI=\ngoogle.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=\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/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-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=\ngoogle.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=\ngoogle.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=\ngoogle.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=\ngoogle.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=\ngoogle.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=\ngoogle.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg=\ngoogle.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=\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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=\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/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=\ngopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=\ngopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=\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.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=\ngopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=\nhonnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\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-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nk8s.io/api v0.18.3 h1:2AJaUQdgUZLoDZHrun21PW2Nx9+ll6cUzvn3IKhSIn0=\nk8s.io/api v0.18.3/go.mod h1:UOaMwERbqJMfeeeHc8XJKawj4P9TgDRnViIqqBeH2QA=\nk8s.io/apiextensions-apiserver v0.18.3 h1:h6oZO+iAgg0HjxmuNnguNdKNB9+wv3O1EBDdDWJViQ0=\nk8s.io/apiextensions-apiserver v0.18.3/go.mod h1:TMsNGs7DYpMXd+8MOCX8KzPOCx8fnZMoIGB24m03+JE=\nk8s.io/apimachinery v0.18.3 h1:pOGcbVAhxADgUYnjS08EFXs9QMl8qaH5U4fr5LGUrSk=\nk8s.io/apimachinery v0.18.3/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=\nk8s.io/apiserver v0.18.3/go.mod h1:tHQRmthRPLUtwqsOnJJMoI8SW3lnoReZeE861lH8vUw=\nk8s.io/client-go v0.18.3/go.mod h1:4a/dpQEvzAhT1BbuWW09qvIaGw6Gbu1gZYiQZIi1DMw=\nk8s.io/client-go v11.0.0+incompatible h1:LBbX2+lOwY9flffWlJM7f1Ct8V2SRNiMRDFeiwnJo9o=\nk8s.io/client-go v11.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=\nk8s.io/code-generator v0.18.3/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=\nk8s.io/component-base v0.18.3/go.mod h1:bp5GzGR0aGkYEfTj+eTY0AN/vXTgkJdQXjNTTVUaa3k=\nk8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=\nk8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=\nk8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=\nk8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=\nk8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=\nk8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=\nk8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6 h1:Oh3Mzx5pJ+yIumsAD0MOECPVeXsVot0UkiaCGVyfGQY=\nk8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=\nk8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89 h1:d4vVOjXm687F1iLSP2q3lyPPuyvTUt3aVoBpi2DqRsU=\nk8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=\nsigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0=\nsigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=\nsigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E=\nsigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=\nsigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=\nsigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=\nsigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=\n"
  },
  {
    "path": "third_party/etcd-operator/hack/build/Dockerfile",
    "content": "FROM alpine:3.6\n\nRUN apk add --no-cache ca-certificates\n\nADD _output/bin/etcd-backup-operator /usr/local/bin/etcd-backup-operator\nADD _output/bin/etcd-restore-operator /usr/local/bin/etcd-restore-operator\nADD _output/bin/etcd-operator /usr/local/bin/etcd-operator\n\nRUN adduser -D etcd-operator\nUSER etcd-operator\n"
  },
  {
    "path": "third_party/etcd-operator/hack/build/backup-operator/build",
    "content": "#!/usr/bin/env bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nsource hack/lib/build.sh\n\nif ! which go > /dev/null; then\n\techo \"golang needs to be installed\"\n\texit 1\nfi\n\nGIT_SHA=`git rev-parse --short HEAD || echo \"GitNotFound\"`\n\ngitHash=\"github.com/coreos/etcd-operator/version.GitSHA=${GIT_SHA}\"\n\ngo_ldflags=\"-X ${gitHash}\"\n\nbin_dir=\"$(pwd)/_output/bin\"\nmkdir -p ${bin_dir} || true\n\nGO_BUILD_FLAGS=\"$@\" go_build backup-operator\n"
  },
  {
    "path": "third_party/etcd-operator/hack/build/build",
    "content": "#!/usr/bin/env bash\n\n# This script builds the operators' binaries\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nmkdir -p _output\n\nDOCKER_REPO_ROOT=\"/go/src/github.com/coreos/etcd-operator\"\n\ndocker run --rm \\\n\t-v \"$PWD\":\"$DOCKER_REPO_ROOT\" \\\n\t-w \"$DOCKER_REPO_ROOT\" \\\n\tgcr.io/coreos-k8s-scale-testing/etcd-operator-builder:0.4.1-2 \\\n\t/bin/bash -c \"hack/build/operator/build && \\\n\t\thack/build/backup-operator/build && \\\n\t\thack/build/restore-operator/build\"\n"
  },
  {
    "path": "third_party/etcd-operator/hack/build/docker_push",
    "content": "#!/usr/bin/env bash\n\nif ! which docker > /dev/null; then\n\techo \"docker needs to be installed\"\n\texit 1\nfi\n\nIMAGE=ccr.ccs.tencentyun.com/etcd-dev/etcd-operator\necho $IMAGE\n\n: ${IMAGE:?\"Need to set IMAGE, e.g. gcr.io/coreos-k8s-scale-testing/etcd-operator\"}\n\necho \"login:\"\ndocker login ccr.ccs.tencentyun.com -u 100000493114 -p codis123 \necho \"building container...\"\ndocker build --tag \"${IMAGE}\" -f hack/build/Dockerfile . 1>/dev/null\n\n# For gcr users, do \"gcloud docker -a\" to have access.\n\necho \"pushing container...\"\ndocker push \"${IMAGE}\" 1>/dev/null\n"
  },
  {
    "path": "third_party/etcd-operator/hack/build/e2e/builder/Dockerfile",
    "content": "FROM golang:1.11.5\n\nRUN curl -L https://github.com/golang/dep/releases/download/v0.5.0/dep-linux-amd64 -o /usr/local/bin/dep \\\n    && chmod +x /usr/local/bin/dep \\\n    && go get honnef.co/go/tools/cmd/gosimple \\\n    && go get honnef.co/go/tools/cmd/unused\n"
  },
  {
    "path": "third_party/etcd-operator/hack/build/e2e/builder/build",
    "content": "#!/usr/bin/env bash\n\n# This script builds and pushes the builder image\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nif ! which docker > /dev/null; then\n\techo \"docker needs to be installed\"\n\texit 1\nfi\n\n: ${IMAGE:?\"Need to set IMAGE, e.g. gcr.io/coreos-k8s-scale-testing/etcd-operator-builder\"}\n\necho \"building container...\"\ndocker build --tag \"${IMAGE}\" -f hack/build/e2e/builder/Dockerfile . 1>/dev/null\n\n# For gcr users, do \"gcloud docker -a\" to have access.\necho \"pushing container...\"\ndocker push \"${IMAGE}\"\n"
  },
  {
    "path": "third_party/etcd-operator/hack/build/e2e/docker_push",
    "content": "#!/usr/bin/env bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\n: ${TEST_IMAGE:?\"Need to set TEST_IMAGE\"}\n\nif ! which docker > /dev/null; then\n\techo \"docker needs to be installed\"\n\texit 1\nfi\n\n# Push test pod image\nTEST_IMAGE=${TEST_IMAGE} test/pod/docker_push\n"
  },
  {
    "path": "third_party/etcd-operator/hack/build/logcollector/Dockerfile",
    "content": "# Build step: docker build --tag gcr.io/coreos-k8s-scale-testing/logcollector -f hack/build/logcollector/Dockerfile .\n\nFROM golang:1.11.5\n\nADD ./ /go/src/github.com/coreos/etcd-operator\n\nWORKDIR /go/src/github.com/coreos/etcd-operator\n\nRUN rm -rf _output _test .git .gitignore\n\nRUN go build -o /usr/local/bin/logcollector test/logcollector/main.go\n"
  },
  {
    "path": "third_party/etcd-operator/hack/build/operator/build",
    "content": "#!/usr/bin/env bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nsource hack/lib/build.sh\n\nif ! which go > /dev/null; then\n\techo \"golang needs to be installed\"\n\texit 1\nfi\n\nGIT_SHA=`git rev-parse --short HEAD || echo \"GitNotFound\"`\n\nbin_dir=\"$(pwd)/_output/bin\"\nmkdir -p ${bin_dir} || true\n\n\ngitHash=\"github.com/coreos/etcd-operator/version.GitSHA=${GIT_SHA}\"\n\ngo_ldflags=\"-X ${gitHash}\"\n\nGO_BUILD_FLAGS=\"$@\" go_build operator\n"
  },
  {
    "path": "third_party/etcd-operator/hack/build/restore-operator/build",
    "content": "#!/usr/bin/env bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nsource hack/lib/build.sh\n\nif ! which go > /dev/null; then\n\techo \"golang needs to be installed\"\n\texit 1\nfi\n\nGIT_SHA=`git rev-parse --short HEAD || echo \"GitNotFound\"`\n\ngitHash=\"github.com/coreos/etcd-operator/version.GitSHA=${GIT_SHA}\"\n\ngo_ldflags=\"-X ${gitHash}\"\n\nbin_dir=\"$(pwd)/_output/bin\"\nmkdir -p ${bin_dir} || true\n\nGO_BUILD_FLAGS=\"$@\" go_build restore-operator\n"
  },
  {
    "path": "third_party/etcd-operator/hack/ci/get_dep",
    "content": "#!/usr/bin/env bash\n\nset -o errexit\n\nDOCKER_REPO_ROOT=\"/go/src/github.com/coreos/etcd-operator\"\n\ndocker run --rm \\\n\t-v \"$PWD\":\"$DOCKER_REPO_ROOT\" \\\n\t-w \"$DOCKER_REPO_ROOT\" \\\n\tgcr.io/coreos-k8s-scale-testing/etcd-operator-builder:0.4.1-2 \\\n\thack/update_vendor.sh\n"
  },
  {
    "path": "third_party/etcd-operator/hack/ci/get_kube.sh",
    "content": "#!/usr/bin/env bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\n: ${DOWNLOAD_DIR:?\"Need to set DOWNLOAD_DIR\"}\n: ${KUBE_VERSION:?\"Need to set KUBE_VERSION\"}\n: ${KUBE_RELEASE_URL:?\"Need to set KUBE_RELEASE_URL\"}\n\ngsutil cp \"gs://${KUBE_RELEASE_URL}/${KUBE_VERSION}/kubernetes.tar.gz\" \"${DOWNLOAD_DIR}/\"\n\ncd $DOWNLOAD_DIR\ntar zxvf kubernetes.tar.gz 1>/dev/null\n\ngsutil cp \"gs://${KUBE_RELEASE_URL}/${KUBE_VERSION}/kubernetes-server-linux-amd64.tar.gz\" \"kubernetes/server/\"\n"
  },
  {
    "path": "third_party/etcd-operator/hack/ci/rbac_utils.sh",
    "content": "#!/usr/bin/env bash\n\n: ${TEST_NAMESPACE:?\"Need to set TEST_NAMESPACE\"}\nROLE_NAME=etcd-operator-${TEST_NAMESPACE}\nROLE_BINDING_NAME=etcd-operator-${TEST_NAMESPACE}\n\nfunction rbac_cleanup {\n    kubectl delete clusterrolebinding ${ROLE_BINDING_NAME}\n    kubectl delete clusterrole ${ROLE_NAME}\n}\n\nfunction rbac_setup() {\n    # Create ClusterRole\n    sed -e \"s/<ROLE_NAME>/${ROLE_NAME}/g\" example/rbac/cluster-role-template.yaml | kubectl create -f -\n\n    # Create ClusterRoleBinding\n    sed -e \"s/<ROLE_NAME>/${ROLE_NAME}/g\" \\\n      -e \"s/<ROLE_BINDING_NAME>/${ROLE_BINDING_NAME}/g\" \\\n      -e \"s/<NAMESPACE>/${TEST_NAMESPACE}/g\" \\\n      example/rbac/cluster-role-binding-template.yaml \\\n      | kubectl create -f -\n}\n"
  },
  {
    "path": "third_party/etcd-operator/hack/ci/run_e2e",
    "content": "#!/usr/bin/env bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nkubectl version\n\n: ${TEST_NAMESPACE:?\"Need to set TEST_NAMESPACE\"}\n: ${TEST_S3_BUCKET:?\"Need to set TEST_S3_BUCKET\"}\n: ${TEST_AWS_SECRET:?\"Need to set TEST_AWS_SECRET\"}\n\n# Default values for e2e and upgrade test envs\nGIT_VERSION=$(git rev-parse HEAD)\nOPERATOR_IMAGE=${OPERATOR_IMAGE:-\"gcr.io/coreos-k8s-scale-testing/etcd-operator:${GIT_VERSION}\"}\nE2E_TEST_SELECTOR=${E2E_TEST_SELECTOR:-\"\"}\n\nUPGRADE_TEST_SELECTOR=${UPGRADE_TEST_SELECTOR:-\"\"}\nUPGRADE_FROM=${UPGRADE_FROM:-\"quay.io/coreos/etcd-operator:latest\"}\nUPGRADE_TO=${UPGRADE_TO:-\"quay.io/coreos/etcd-operator:dev\"}\n\nfunction finish {\n  sudo chown -R \"$(whoami)\" ./\n}\ntrap finish EXIT\n\nhack/ci/get_dep\n\nBUILD_IMAGE=${BUILD_IMAGE:-true}\nif [[ ${BUILD_IMAGE} == \"true\" ]]; then\n  gcloud docker -a\n  hack/build/build\n  IMAGE=${OPERATOR_IMAGE} hack/build/docker_push\nfi\n\nBUILD_E2E=${BUILD_E2E:-true}\nif [[ ${BUILD_E2E} == \"true\" ]]; then\n  TEST_IMAGE=${TEST_IMAGE:-\"gcr.io/coreos-k8s-scale-testing/etcd-operator-e2e:${GIT_VERSION}\"}\n  gcloud docker -a\n  TEST_IMAGE=${TEST_IMAGE} hack/build/e2e/docker_push\nfi\n\necho \"TEST_NAMESPACE: ${TEST_NAMESPACE}\"\necho \"OPERATOR_IMAGE: ${OPERATOR_IMAGE}\"\necho \"TEST_IMAGE: ${TEST_IMAGE}\"\n\nif [ -z \"${PASSES-}\" ]; then\n  echo \"No PASSES specified. Skipping tests\"\n  exit 0\nfi\n\n# Generate test-pod spec\nexport TEST_POD_SPEC=${PWD}/test/pod/test-pod-spec.yaml\nexport POD_NAME=${POD_NAME:-\"e2e-testing\"}\n\nsed -e \"s|<POD_NAME>|${POD_NAME}|g\" \\\n    -e \"s|<TEST_IMAGE>|${TEST_IMAGE}|g\" \\\n    -e \"s|<PASSES>|${PASSES}|g\" \\\n    -e \"s|<OPERATOR_IMAGE>|${OPERATOR_IMAGE}|g\" \\\n    -e \"s|<E2E_TEST_SELECTOR>|${E2E_TEST_SELECTOR}|g\" \\\n    -e \"s|<TEST_S3_BUCKET>|${TEST_S3_BUCKET}|g\" \\\n    -e \"s|<TEST_AWS_SECRET>|${TEST_AWS_SECRET}|g\" \\\n    -e \"s|<UPGRADE_TEST_SELECTOR>|${UPGRADE_TEST_SELECTOR}|g\" \\\n    -e \"s|<UPGRADE_FROM>|${UPGRADE_FROM}|g\" \\\n    -e \"s|<UPGRADE_TO>|${UPGRADE_TO}|g\" \\\n    test/pod/test-pod-templ.yaml > ${TEST_POD_SPEC}\n\n# Run test-pod\ntest/pod/run-test-pod\n"
  },
  {
    "path": "third_party/etcd-operator/hack/ci/run_unit",
    "content": "#!/usr/bin/env bash\n#\n# This script is used for fmt_pass and unit_pass\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nexport CODECOV_TOKEN=$(cat $CODECOV_TOKEN_FILE)\n\nfunction finish {\n  sudo chown -R \"$(whoami)\" ./\n}\ntrap finish EXIT\n\nhack/ci/get_dep\nhack/test\n"
  },
  {
    "path": "third_party/etcd-operator/hack/fmt_pass",
    "content": "#!/usr/bin/env bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nsource \"hack/lib/test_lib.sh\"\n\nallfiles=$(listFiles)\n\necho \"Checking gofmt...\"\nfor file in $allfiles; do\n  checkRes=$(gofmt -l -s -d $file)\n  if [ -n \"${checkRes}\" ]; then\n    echo -e \"gofmt checking failed:\\n${checkRes}\"\n    exit 255\n  fi\ndone\n\nif which gosimple >/dev/null; then\n  echo \"Checking gosimple...\"\n  # Generated deepcopy code failed checking... Ignore it at the moment\n  checkRes=$(gosimple `listPkgs | grep -v apis/etcd/v1beta2`) || true\n  if [ -n \"${checkRes}\" ]; then\n    echo -e \"gosimple checking failed:\\n${checkRes}\"\n    exit 255\n  fi\nelse\n  echo \"Skipping gosimple: failed to install\"\nfi\n\nif which unused >/dev/null; then\n  echo \"Checking unused...\"\n  checkRes=$(unused `listPkgs`) || true\n  if [ -n \"${checkRes}\" ]; then\n      echo -e \"unused checking failed:\\n${checkRes}\"\n      exit 255\n  fi\nelse\n  echo \"Skipping unused: failed to install\"\nfi\n\necho \"Checking for license header...\"\nlicRes=\"\"\nfor file in $allfiles; do\n  if ! head -n3 \"${file}\" | grep -Eq \"(Copyright|generated|GENERATED)\" ; then\n    licRes=\"${licRes}\"$(echo -e \"  ${file}\")\n  fi\ndone\nif [ -n \"${licRes}\" ]; then\n  echo -e \"license header checking failed:\\n${licRes}\"\n  exit 255\nfi\n"
  },
  {
    "path": "third_party/etcd-operator/hack/k8s/codegen/README.md",
    "content": "## How to use codegen\n\n```sh\n./hack/k8s/codegen/update-generated.sh\n```\n\nIt should print:\n\n```\nGenerating deepcopy funcs\nGenerating clientset for etcd:v1beta2 at github.com/coreos/etcd-operator/pkg/generated/clientset\nGenerating listers for etcd:v1beta2 at github.com/coreos/etcd-operator/pkg/generated/listers\nGenerating informers for etcd:v1beta2 at github.com/coreos/etcd-operator/pkg/generated/informers\n```\n"
  },
  {
    "path": "third_party/etcd-operator/hack/k8s/codegen/boilerplate.go.txt",
    "content": "/*\nCopyright YEAR The etcd-operator Authors\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"
  },
  {
    "path": "third_party/etcd-operator/hack/k8s/codegen/update-generated.sh",
    "content": "#!/usr/bin/env bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nvendor/k8s.io/code-generator/generate-groups.sh \\\n  \"all\" \\\n  \"github.com/coreos/etcd-operator/pkg/generated\" \\\n  \"github.com/coreos/etcd-operator/pkg/apis\" \\\n  \"etcd:v1beta2\" \\\n  --go-header-file \"./hack/k8s/codegen/boilerplate.go.txt\" \\\n  $@\n"
  },
  {
    "path": "third_party/etcd-operator/hack/k8s/codegen/verify-generated.sh",
    "content": "#!/usr/bin/env bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\n\nif ! output=$(./hack/k8s/codegen/update-generated.sh --verify-only 2>&1); then\n  echo \"FAILURE: verification of codegen failed:\"\n  echo \"${output}\"\n  exit 1\nfi\n\necho \"Verified generated code ===\"\n"
  },
  {
    "path": "third_party/etcd-operator/hack/lib/build.sh",
    "content": "function go_build {\n\techo \"building \"${1}\"...\"\n\t# We’re disabling cgo which gives us a static binary.\n\t# This is needed for building minimal container based on alpine image.\n\tGOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build $GO_BUILD_FLAGS -o ${bin_dir}/etcd-${1} -installsuffix cgo -ldflags \"$go_ldflags\" ./cmd/${1}/\n}\n"
  },
  {
    "path": "third_party/etcd-operator/hack/lib/test_lib.sh",
    "content": "function listPkgs() {\n\tgo list ./cmd/... ./pkg/... ./test/... | grep -v generated\n}\n\nfunction listFiles() {\n\t# pipeline is much faster than for loop\n\tlistPkgs | xargs -I {} find \"${GOPATH}/src/{}\" -name '*.go' | grep -v generated\n}\n"
  },
  {
    "path": "third_party/etcd-operator/hack/release/bump_version.sh",
    "content": "#!/usr/bin/env bash\n\n# Usage:\n#   ./hack/release/bump_version.sh 0.8.0 0.8.1\n\noldv=$1\nnewv=$2\n\necho \"old version: ${oldv}, new version: ${newv}\"\n\nsed -i.bak -e \"s/${oldv}+git/${newv}/g\" version/version.go\nsed -i.bak -e \"s/${oldv}/${newv}/g\" example/deployment.yaml\nsed -i.bak -e \"s/${oldv}/${newv}/g\" example/etcd-backup-operator/deployment.yaml\nsed -i.bak -e \"s/${oldv}/${newv}/g\" example/etcd-restore-operator/deployment.yaml\n\nrm version/version.go.bak\nrm example/deployment.yaml.bak\nrm example/etcd-backup-operator/deployment.yaml.bak\nrm example/etcd-restore-operator/deployment.yaml.bak\n"
  },
  {
    "path": "third_party/etcd-operator/hack/test",
    "content": "#!/usr/bin/env bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nsource \"hack/lib/test_lib.sh\"\n\n# KUBECONFIG can be an empty string and so needs to be explicitly declared to avoid an unbound variable error\nKUBECONFIG=${KUBECONFIG:-\"\"}\n\nif [ -z \"${PASSES-}\" ]; then\n\tPASSES=\"fmt e2e e2eslow unit\"\nfi\n\nfunction fmt_pass {\n\tif ! \"./hack/k8s/codegen/verify-generated.sh\"; then\n\t\texit 1\n\tfi\n\t\n\tDOCKER_REPO_ROOT=\"/go/src/github.com/coreos/etcd-operator\"\n\tdocker run --rm \\\n\t\t-v \"${PWD}\":\"${DOCKER_REPO_ROOT}\" \\\n\t\t-w \"${DOCKER_REPO_ROOT}\" \\\n\t\tgcr.io/coreos-k8s-scale-testing/etcd-operator-builder:0.4.1-2 \\\n\t\t\"./hack/fmt_pass\"\n}\n\nfunction e2e_pass {\n\t: ${TEST_S3_BUCKET:?\"Need to set TEST_S3_BUCKET\"}\n\t: ${TEST_AWS_SECRET:?\"Need to set TEST_AWS_SECRET\"}\n\n\t# Run all the tests by default\n\tE2E_TEST_SELECTOR=${E2E_TEST_SELECTOR:-.*}\n\n\tbuild_flags=(\"-i\") # cache package compilation data for faster repeated builds\n\tfor i in {1..2}; do\n\t\tgo test -failfast -parallel=4 \"./test/e2e/\" ${build_flags[@]} -run \"$E2E_TEST_SELECTOR\" -timeout 30m --race \\\n\t\t\t--kubeconfig=$KUBECONFIG --operator-image=$OPERATOR_IMAGE --namespace=${TEST_NAMESPACE}\n\t\tbuild_flags=(\"\")\n\tdone\n}\n\nfunction e2eslow_pass {\n\tE2E_TEST_SELECTOR=${E2E_TEST_SELECTOR:-.*}\n\tbuild_flags=(\"-i\") # cache package compilation data for faster repeated builds\n\tfor i in {1..2}; do\n\t\tgo test -failfast \"./test/e2e/e2eslow\" ${build_flags[@]} -run \"$E2E_TEST_SELECTOR\" -timeout 30m --race \\\n\t\t\t--kubeconfig=$KUBECONFIG --operator-image=$OPERATOR_IMAGE --namespace=${TEST_NAMESPACE}\n\t\tbuild_flags=(\"\")\n\tdone\n}\n\nfunction upgrade_pass {\n\t# Run all the tests by default\n\tUPGRADE_TEST_SELECTOR=${UPGRADE_TEST_SELECTOR:-.*}\n\tgo test -failfast ./test/e2e/upgradetest/ -run \"$UPGRADE_TEST_SELECTOR\" --race -timeout 30m \\\n\t\t--kubeconfig=$KUBECONFIG --kube-ns=$TEST_NAMESPACE \\\n\t\t--old-image=$UPGRADE_FROM \\\n\t\t--new-image=$UPGRADE_TO\n}\n\nfunction unit_pass {\n\tDOCKER_REPO_ROOT=\"/go/src/github.com/coreos/etcd-operator\"\n\tdocker run --rm \\\n\t\t-v \"${PWD}\":\"${DOCKER_REPO_ROOT}\" \\\n\t\t-w \"${DOCKER_REPO_ROOT}\" \\\n\t\t-e \"CODECOV_TOKEN\" \\\n\t\tgolang:1.11.5 \\\n\t\t\"./hack/unit_test\"\n}\n\nfor p in $PASSES\ndo\n\t${p}_pass\ndone\n\necho \"test success ===\"\n"
  },
  {
    "path": "third_party/etcd-operator/hack/unit_test",
    "content": "#!/usr/bin/env bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nsource \"hack/lib/test_lib.sh\"\n\n# coverage.txt is the combined coverage report consumed by codecov\necho \"mode: atomic\" > coverage.txt\n\nTEST_PKGS=$(listPkgs | grep -v e2e)\nfor pkg in $TEST_PKGS\ndo\n  build_flags=(\"-i\") # cache package compilation data for faster repeated builds\n  for i in {1..2}; do\n    go test -failfast ${build_flags[@]} -race -covermode=atomic -coverprofile=profile.out $pkg\n    # Expand empty array would cause \"unbound variable\".\n    # Expand one empty string array is equal to nothing.\n    build_flags=(\"\")\n  done\n  if [ -f profile.out ]; then\n    tail -n +2 profile.out >> coverage.txt\n    rm profile.out\n  fi\ndone\n\n# Send reports to codecov, CODECOV_TOKEN env must be present in Jenkins\n(curl -s https://codecov.io/bash | bash) || true\n"
  },
  {
    "path": "third_party/etcd-operator/hack/update_vendor.sh",
    "content": "#!/usr/bin/env bash\n\ndep ensure -v\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/apis/etcd/v1beta2/backup_types.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage v1beta2\n\nimport (\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\nconst (\n\t// AWS S3 related consts\n\tBackupStorageTypeS3          BackupStorageType = \"S3\"\n\tAWSSecretCredentialsFileName                   = \"credentials\"\n\tAWSSecretConfigFileName                        = \"config\"\n\n\t// Azure ABS related consts\n\tBackupStorageTypeABS      BackupStorageType = \"ABS\"\n\tAzureSecretStorageAccount                   = \"storage-account\"\n\tAzureSecretStorageKey                       = \"storage-key\"\n\tAzureCloudKey                               = \"cloud\"\n\n\t// Google GCS related consts\n\tBackupStorageTypeGCS BackupStorageType = \"GCS\"\n\tGCPAccessToken                         = \"access-token\"\n\tGCPCredentialsJson                     = \"credentials.json\"\n\n\t// Tencent COS related consts\n\tBackupStorageTypeCOS BackupStorageType = \"COS\"\n\tCOSSecretKey                           = \"secret-key\"\n\tCOSSecretId                            = \"secret-id\"\n\n\t// Alibaba Cloud OSS related consts\n\tBackupStorageTypeOSS                         BackupStorageType = \"OSS\"\n\tAlibabaCloudSecretCredentialsAccessKeyID                       = \"accessKeyID\"\n\tAlibabaCloudSecretCredentialsAccessKeySecret                   = \"accessKeySecret\"\n\n\t// Hostpath related consts\n\tBackupStorageTypeHostPath BackupStorageType = \"HostPath\"\n)\n\ntype BackupStorageType string\n\n// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n\n// EtcdBackupList is a list of EtcdBackup.\ntype EtcdBackupList struct {\n\tmetav1.TypeMeta `json:\",inline\"`\n\tmetav1.ListMeta `json:\"metadata\"`\n\tItems           []EtcdBackup `json:\"items\"`\n}\n\n// +genclient\n// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n\n// EtcdBackup represents a Kubernetes EtcdBackup Custom Resource.\ntype EtcdBackup struct {\n\tmetav1.TypeMeta   `json:\",inline\"`\n\tmetav1.ObjectMeta `json:\"metadata\"`\n\tSpec              BackupSpec   `json:\"spec\"`\n\tStatus            BackupStatus `json:\"status,omitempty\"`\n}\n\n// BackupSpec contains a backup specification for an etcd cluster.\ntype BackupSpec struct {\n\t// EtcdEndpoints specifies the endpoints of an etcd cluster.\n\t// When multiple endpoints are given, the backup operator retrieves\n\t// the backup from the endpoint that has the most up-to-date state.\n\t// The given endpoints must belong to the same etcd cluster.\n\tEtcdEndpoints []string `json:\"etcdEndpoints,omitempty\"`\n\t// StorageType is the etcd backup storage type.\n\t// We need this field because CRD doesn't support validation against invalid fields\n\t// and we cannot verify invalid backup storage source.\n\tStorageType BackupStorageType `json:\"storageType\"`\n\t// BackupPolicy configures the backup process.\n\tBackupPolicy *BackupPolicy `json:\"backupPolicy,omitempty\"`\n\t// BackupSource is the backup storage source.\n\tBackupSource `json:\",inline\"`\n\t// ClientTLSSecret is the secret containing the etcd TLS client certs and\n\t// must contain the following data items:\n\t// data:\n\t//    \"client.crt\": <pem-encoded-cert>\n\t//    \"client.key\": <pem-encoded-key>\n\t//    \"client-ca.crt\": <pem-encoded-ca-cert>\n\tClientTLSSecret string `json:\"clientTLSSecret,omitempty\"`\n\t// insecure-skip-tsl-verify\n\tInsecureSkipVerify bool `json:\"insecureSkipVerify, omitempty\"`\n\t// BasicAuthSecret is the secret containing the etcd user password\n\t// data:\n\t//    \"username\": xx\n\t//    \"password\": xxxx\n\tBasicAuthSecret string `json:\"basicAuthSecret,omitempty\"`\n}\n\n// BackupSource contains the supported backup sources.\ntype BackupSource struct {\n\t// S3 defines the S3 backup source spec.\n\tS3 *S3BackupSource `json:\"s3,omitempty\"`\n\t// ABS defines the ABS backup source spec.\n\tABS *ABSBackupSource `json:\"abs,omitempty\"`\n\t// GCS defines the GCS backup source spec.\n\tGCS *GCSBackupSource `json:\"gcs,omitempty\"`\n\t// COS defines the COS backup source spec.\n\tCOS *COSBackupSource `json:\"cos,omitempty\"`\n\t// OSS defines the OSS backup source spec.\n\tOSS *OSSBackupSource `json:\"oss,omitempty\"`\n\t// HostPath defines the HostPath backup source spec.\n\tHostPath *HostPathBackupSource `json:\"hostpath,omitempty\"`\n}\n\n// BackupPolicy defines backup policy.\ntype BackupPolicy struct {\n\t// TimeoutInSecond is the maximal allowed time in second of the entire backup process.\n\tTimeoutInSecond int64 `json:\"timeoutInSecond,omitempty\"`\n\t// BackupIntervalInSecond is to specify how often operator take snapshot\n\t// 0 is magic number to indicate one-shot backup\n\tBackupIntervalInSecond int64 `json:\"backupIntervalInSecond,omitempty\"`\n\t// MaxBackups is to specify how many backups we want to keep\n\t// 0 is magic number to indicate un-limited backups\n\tMaxBackups int `json:\"maxBackups,omitempty\"`\n}\n\n// BackupStatus represents the status of the EtcdBackup Custom Resource.\ntype BackupStatus struct {\n\t// Succeeded indicates if the backup has Succeeded.\n\tSucceeded bool `json:\"succeeded\"`\n\t// Reason indicates the reason for any backup related failures.\n\tReason string `json:\"Reason,omitempty\"`\n\t// EtcdVersion is the version of the backup etcd server.\n\tEtcdVersion string `json:\"etcdVersion,omitempty\"`\n\t// EtcdRevision is the revision of etcd's KV store where the backup is performed on.\n\tEtcdRevision int64 `json:\"etcdRevision,omitempty\"`\n\t// LastSuccessDate indicate the time to get snapshot last time\n\tLastSuccessDate metav1.Time `json:\"lastSuccessDate,omitempty\"`\n}\n\n// S3BackupSource provides the spec how to store backups on S3.\ntype S3BackupSource struct {\n\t// Path is the full s3 path where the backup is saved.\n\t// The format of the path must be: \"<s3-bucket-name>/<path-to-backup-file>\"\n\t// e.g: \"mybucket/etcd.backup\"\n\tPath string `json:\"path\"`\n\n\t// The name of the secret object that stores the AWS credential and config files.\n\t// The file name of the credential MUST be 'credentials'.\n\t// The file name of the config MUST be 'config'.\n\t// The profile to use in both files will be 'default'.\n\t//\n\t// AWSSecret overwrites the default etcd operator wide AWS credential and config.\n\tAWSSecret string `json:\"awsSecret\"`\n\n\t// Endpoint if blank points to aws. If specified, can point to s3 compatible object\n\t// stores.\n\tEndpoint string `json:\"endpoint,omitempty\"`\n\n\t// ForcePathStyle forces to use path style over the default subdomain style.\n\t// This is useful when you have an s3 compatible endpoint that doesn't support\n\t// subdomain buckets.\n\tForcePathStyle bool `json:\"forcePathStyle\"`\n}\n\n// ABSBackupSource provides the spec how to store backups on ABS.\ntype ABSBackupSource struct {\n\t// Path is the full abs path where the backup is saved.\n\t// The format of the path must be: \"<abs-container-name>/<path-to-backup-file>\"\n\t// e.g: \"myabscontainer/etcd.backup\"\n\tPath string `json:\"path\"`\n\n\t// The name of the secret object that stores the Azure storage credential\n\tABSSecret string `json:\"absSecret\"`\n}\n\n// GCSBackupSource provides the spec how to store backups on GCS.\ntype GCSBackupSource struct {\n\t// Path is the full GCS path where the backup is saved.\n\t// The format of the path must be: \"<gcs-bucket-name>/<path-to-backup-file>\"\n\t// e.g: \"mygcsbucket/etcd.backup\"\n\tPath string `json:\"path\"`\n\n\t// The name of the secret object that stores the Google storage credential\n\t// containing at most ONE of the following:\n\t// An access token with file name of 'access-token'.\n\t// JSON credentials with file name of 'credentials.json'.\n\t//\n\t// If omitted, client will use the default application credentials.\n\tGCPSecret string `json:\"gcpSecret,omitempty\"`\n}\n\n// COSBackupSource provides the spec how to store backups on COS.\ntype COSBackupSource struct {\n\t// Path is the full COS path where the backup is saved.\n\t// The format of the path must be: \"<cos-bucket-name>/<path-to-backup-file>\"\n\t// e.g: \"mycosbucket/etcd.backup\"\n\tPath string `json:\"path\"`\n\n\t// The name of the secret object that stores the COS storage credential\n\tCOSSecret string `json:\"cosSecret\"`\n}\n\n// OSSBackupSource provides the spec how to store backups on OSS.\ntype OSSBackupSource struct {\n\t// Path is the full abs path where the backup is saved.\n\t// The format of the path must be: \"<oss-bucket-name>/<path-to-backup-file>\"\n\t// e.g: \"mybucket/etcd.backup\"\n\tPath string `json:\"path\"`\n\n\t// The name of the secret object that stores the credential which will be used\n\t// to access Alibaba Cloud OSS.\n\t//\n\t// The secret must contain the following keys/fields:\n\t//     accessKeyID\n\t//     accessKeySecret\n\t//\n\t// The format of secret:\n\t//\n\t//   apiVersion: v1\n\t//   kind: Secret\n\t//   metadata:\n\t//     name: <my-credential-name>\n\t//   type: Opaque\n\t//   data:\n\t//     accessKeyID: <base64 of my-access-key-id>\n\t//     accessKeySecret: <base64 of my-access-key-secret>\n\t//\n\tOSSSecret string `json:\"ossSecret\"`\n\n\t// Endpoint is the OSS service endpoint on alibaba cloud, defaults to\n\t// \"http://oss-cn-hangzhou.aliyuncs.com\".\n\t//\n\t// Details about regions and endpoints, see:\n\t//  https://www.alibabacloud.com/help/doc-detail/31837.htm\n\tEndpoint string `json:\"endpoint,omitempty\"`\n}\n\n// HostPathBackupSource provides the spec how to store backups on HostPath.\ntype HostPathBackupSource struct {\n\t// Path is the full Host path where the backup is saved.\n\t// The format of the path is relative\n\t// e.g: \"etcd.backup\"\n\tPath string `json:\"path\"`\n} \n"
  },
  {
    "path": "third_party/etcd-operator/pkg/apis/etcd/v1beta2/cluster.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage v1beta2\n\nimport (\n\t\"errors\"\n\t\"strings\"\n\n\tv1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\nconst (\n\tdefaultRepository  = \"quay.io/coreos/etcd\"\n\tDefaultEtcdVersion = \"3.2.13\"\n)\n\nvar (\n\t// TODO: move validation code into separate package.\n\tErrBackupUnsetRestoreSet = errors.New(\"spec: backup policy must be set if restore policy is set\")\n)\n\n// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n\n// EtcdClusterList is a list of etcd clusters.\ntype EtcdClusterList struct {\n\tmetav1.TypeMeta `json:\",inline\"`\n\t// Standard list metadata\n\t// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata\n\tmetav1.ListMeta `json:\"metadata,omitempty\"`\n\tItems           []EtcdCluster `json:\"items\"`\n}\n\n// +genclient\n// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n\ntype EtcdCluster struct {\n\tmetav1.TypeMeta   `json:\",inline\"`\n\tmetav1.ObjectMeta `json:\"metadata,omitempty\"`\n\tSpec              ClusterSpec   `json:\"spec\"`\n\tStatus            ClusterStatus `json:\"status\"`\n}\n\nfunc (c *EtcdCluster) AsOwner() metav1.OwnerReference {\n\ttrueVar := true\n\treturn metav1.OwnerReference{\n\t\tAPIVersion: SchemeGroupVersion.String(),\n\t\tKind:       EtcdClusterResourceKind,\n\t\tName:       c.Name,\n\t\tUID:        c.UID,\n\t\tController: &trueVar,\n\t}\n}\n\ntype ClusterSpec struct {\n\t// Size is the expected size of the etcd cluster.\n\t// The etcd-operator will eventually make the size of the running\n\t// cluster equal to the expected size.\n\t// The vaild range of the size is from 1 to 7.\n\tSize int `json:\"size\"`\n\t// Repository is the name of the repository that hosts\n\t// etcd container images. It should be direct clone of the repository in official\n\t// release:\n\t//   https://github.com/coreos/etcd/releases\n\t// That means, it should have exact same tags and the same meaning for the tags.\n\t//\n\t// By default, it is `quay.io/coreos/etcd`.\n\tRepository string `json:\"repository,omitempty\"`\n\n\t// Version is the expected version of the etcd cluster.\n\t// The etcd-operator will eventually make the etcd cluster version\n\t// equal to the expected version.\n\t//\n\t// The version must follow the [semver]( http://semver.org) format, for example \"3.2.13\".\n\t// Only etcd released versions are supported: https://github.com/coreos/etcd/releases\n\t//\n\t// If version is not set, default is \"3.2.13\".\n\tVersion string `json:\"version,omitempty\"`\n\n\t// Paused is to pause the control of the operator for the etcd cluster.\n\tPaused bool `json:\"paused,omitempty\"`\n\n\t// Pod defines the policy to create pod for the etcd pod.\n\t//\n\t// Updating Pod does not take effect on any existing etcd pods.\n\tPod *PodPolicy `json:\"pod,omitempty\"`\n\n\t// etcd cluster TLS configuration\n\tTLS *TLSPolicy `json:\"TLS,omitempty\"`\n}\n\n// PodPolicy defines the policy to create pod for the etcd container.\ntype PodPolicy struct {\n\t// Labels specifies the labels to attach to pods the operator creates for the\n\t// etcd cluster.\n\t// \"app\" and \"etcd_*\" labels are reserved for the internal use of the etcd operator.\n\t// Do not overwrite them.\n\tLabels map[string]string `json:\"labels,omitempty\"`\n\n\t// NodeSelector specifies a map of key-value pairs. For the pod to be eligible\n\t// to run on a node, the node must have each of the indicated key-value pairs as\n\t// labels.\n\tNodeSelector map[string]string `json:\"nodeSelector,omitempty\"`\n\n\t// The scheduling constraints on etcd pods.\n\tAffinity *v1.Affinity `json:\"affinity,omitempty\"`\n\t// **DEPRECATED**. Use Affinity instead.\n\tAntiAffinity bool `json:\"antiAffinity,omitempty\"`\n\n\t// Resources is the resource requirements for the etcd container.\n\t// This field cannot be updated once the cluster is created.\n\tResources v1.ResourceRequirements `json:\"resources,omitempty\"`\n\n\t// Tolerations specifies the pod's tolerations.\n\tTolerations []v1.Toleration `json:\"tolerations,omitempty\"`\n\n\t// List of environment variables to set in the etcd container.\n\t// This is used to configure etcd process. etcd cluster cannot be created, when\n\t// bad environement variables are provided. Do not overwrite any flags used to\n\t// bootstrap the cluster (for example `--initial-cluster` flag).\n\t// This field cannot be updated.\n\tEtcdEnv []v1.EnvVar `json:\"etcdEnv,omitempty\"`\n\n\t// PersistentVolumeClaimSpec is the spec to describe PVC for the etcd container\n\t// This field is optional. If no PVC spec, etcd container will use emptyDir as volume\n\t// Note. This feature is in alpha stage. It is currently only used as non-stable storage,\n\t// not the stable storage. Future work need to make it used as stable storage.\n\tPersistentVolumeClaimSpec *v1.PersistentVolumeClaimSpec `json:\"persistentVolumeClaimSpec,omitempty\"`\n\n\t// Annotations specifies the annotations to attach to pods the operator creates for the\n\t// etcd cluster.\n\t// The \"etcd.version\" annotation is reserved for the internal use of the etcd operator.\n\tAnnotations map[string]string `json:\"annotations,omitempty\"`\n\n\t// busybox init container image. default is busybox:1.28.0-glibc\n\t// busybox:latest uses uclibc which contains a bug that sometimes prevents name resolution\n\t// More info: https://github.com/docker-library/busybox/issues/27\n\tBusyboxImage string `json:\"busyboxImage,omitempty\"`\n\n\t// SecurityContext specifies the security context for the entire pod\n\t// More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context\n\tSecurityContext *v1.PodSecurityContext `json:\"securityContext,omitempty\"`\n\n\t// DNSTimeoutInSecond is the maximum allowed time for the init container of the etcd pod to\n\t// reverse DNS lookup its IP given the hostname.\n\t// The default is to wait indefinitely and has a vaule of 0.\n\tDNSTimeoutInSecond int64 `json:\"DNSTimeoutInSecond,omitempty\"`\n\n\t// ClusterDomain is the cluster domain to use for member URLs E.g.\n\t// '.cluster.local'.\n\t// The default is to not set a cluster domain explicitly.\n\tClusterDomain string `json:\"ClusterDomain\"`\n}\n\n// TODO: move this to initializer\nfunc (c *ClusterSpec) Validate() error {\n\tif c.TLS != nil {\n\t\tif err := c.TLS.Validate(); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif c.Pod != nil {\n\t\tfor k := range c.Pod.Labels {\n\t\t\tif k == \"app\" || strings.HasPrefix(k, \"etcd_\") {\n\t\t\t\treturn errors.New(\"spec: pod labels contains reserved label\")\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// SetDefaults cleans up user passed spec, e.g. defaulting, transforming fields.\n// TODO: move this to initializer\nfunc (e *EtcdCluster) SetDefaults() {\n\tc := &e.Spec\n\tif len(c.Repository) == 0 {\n\t\tc.Repository = defaultRepository\n\t}\n\n\tif len(c.Version) == 0 {\n\t\tc.Version = DefaultEtcdVersion\n\t}\n\n\tc.Version = strings.TrimLeft(c.Version, \"v\")\n\n\t// convert PodPolicy.AntiAffinity to Pod.Affinity.PodAntiAffinity\n\t// TODO: Remove this once PodPolicy.AntiAffinity is removed\n\tif c.Pod != nil && c.Pod.AntiAffinity && c.Pod.Affinity == nil {\n\t\tc.Pod.Affinity = &v1.Affinity{\n\t\t\tPodAntiAffinity: &v1.PodAntiAffinity{\n\t\t\t\tRequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{\n\t\t\t\t\t{\n\t\t\t\t\t\t// set anti-affinity to the etcd pods that belongs to the same cluster\n\t\t\t\t\t\tLabelSelector: &metav1.LabelSelector{MatchLabels: map[string]string{\n\t\t\t\t\t\t\t\"etcd_cluster\": e.Name,\n\t\t\t\t\t\t}},\n\t\t\t\t\t\tTopologyKey: \"kubernetes.io/hostname\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/apis/etcd/v1beta2/cluster_tls.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage v1beta2\n\nimport \"errors\"\n\n// TLSPolicy defines the TLS policy of an etcd cluster\ntype TLSPolicy struct {\n\t// StaticTLS enables user to generate static x509 certificates and keys,\n\t// put them into Kubernetes secrets, and specify them into here.\n\tStatic *StaticTLS `json:\"static,omitempty\"`\n}\n\ntype StaticTLS struct {\n\t// Member contains secrets containing TLS certs used by each etcd member pod.\n\tMember *MemberSecret `json:\"member,omitempty\"`\n\t// OperatorSecret is the secret containing TLS certs used by operator to\n\t// talk securely to this cluster.\n\tOperatorSecret string `json:\"operatorSecret,omitempty\"`\n}\n\ntype MemberSecret struct {\n\t// PeerSecret is the secret containing TLS certs used by each etcd member pod\n\t// for the communication between etcd peers.\n\tPeerSecret string `json:\"peerSecret,omitempty\"`\n\t// ServerSecret is the secret containing TLS certs used by each etcd member pod\n\t// for the communication between etcd server and its clients.\n\tServerSecret string `json:\"serverSecret,omitempty\"`\n}\n\nfunc (tp *TLSPolicy) Validate() error {\n\tif tp.Static == nil {\n\t\treturn nil\n\t}\n\tst := tp.Static\n\n\tif len(st.OperatorSecret) != 0 {\n\t\tif len(st.Member.ServerSecret) == 0 {\n\t\t\treturn errors.New(\"operator secret set but member serverSecret not set\")\n\t\t}\n\t} else if st.Member != nil && len(st.Member.ServerSecret) != 0 {\n\t\treturn errors.New(\"member serverSecret set but operator secret not set\")\n\t}\n\treturn nil\n}\n\nfunc (tp *TLSPolicy) IsSecureClient() bool {\n\tif tp == nil || tp.Static == nil {\n\t\treturn false\n\t}\n\treturn len(tp.Static.OperatorSecret) != 0\n}\n\nfunc (tp *TLSPolicy) IsSecurePeer() bool {\n\tif tp == nil || tp.Static == nil || tp.Static.Member == nil {\n\t\treturn false\n\t}\n\treturn len(tp.Static.Member.PeerSecret) != 0\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/apis/etcd/v1beta2/doc.go",
    "content": "/*\nCopyright 2017 The etcd-operator Authors\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\n// +k8s:deepcopy-gen=package\n// +groupName=etcd.database.coreos.com\npackage v1beta2\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/apis/etcd/v1beta2/register.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage v1beta2\n\nimport (\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n)\n\nconst (\n\tEtcdClusterResourceKind   = \"EtcdCluster\"\n\tEtcdClusterResourcePlural = \"etcdclusters\"\n\tgroupName                 = \"etcd.database.coreos.com\"\n\n\tEtcdBackupResourceKind   = \"EtcdBackup\"\n\tEtcdBackupResourcePlural = \"etcdbackups\"\n\n\tEtcdRestoreResourceKind   = \"EtcdRestore\"\n\tEtcdRestoreResourcePlural = \"etcdrestores\"\n)\n\nvar (\n\tSchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)\n\tAddToScheme   = SchemeBuilder.AddToScheme\n\n\tSchemeGroupVersion = schema.GroupVersion{Group: groupName, Version: \"v1beta2\"}\n\tEtcdClusterCRDName = EtcdClusterResourcePlural + \".\" + groupName\n\tEtcdBackupCRDName  = EtcdBackupResourcePlural + \".\" + groupName\n\tEtcdRestoreCRDName = EtcdRestoreResourcePlural + \".\" + groupName\n)\n\n// Resource gets an EtcdCluster GroupResource for a specified resource\nfunc Resource(resource string) schema.GroupResource {\n\treturn SchemeGroupVersion.WithResource(resource).GroupResource()\n}\n\n// addKnownTypes adds the set of types defined in this package to the supplied scheme.\nfunc addKnownTypes(s *runtime.Scheme) error {\n\ts.AddKnownTypes(SchemeGroupVersion,\n\t\t&EtcdCluster{},\n\t\t&EtcdClusterList{},\n\t\t&EtcdBackup{},\n\t\t&EtcdBackupList{},\n\t\t&EtcdRestore{},\n\t\t&EtcdRestoreList{},\n\t)\n\tmetav1.AddToGroupVersion(s, SchemeGroupVersion)\n\treturn nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/apis/etcd/v1beta2/restore_types.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage v1beta2\n\nimport metav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\n// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n\n// EtcdRestoreList is a list of EtcdRestore.\ntype EtcdRestoreList struct {\n\tmetav1.TypeMeta `json:\",inline\"`\n\tmetav1.ListMeta `json:\"metadata\"`\n\tItems           []EtcdRestore `json:\"items\"`\n}\n\n// +genclient\n// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n\n// EtcdRestore represents a Kubernetes EtcdRestore Custom Resource.\n// The EtcdRestore CR name will be used as the name of the new restored cluster.\ntype EtcdRestore struct {\n\tmetav1.TypeMeta   `json:\",inline\"`\n\tmetav1.ObjectMeta `json:\"metadata\"`\n\tSpec              RestoreSpec   `json:\"spec\"`\n\tStatus            RestoreStatus `json:\"status,omitempty\"`\n}\n\n// RestoreSpec defines how to restore an etcd cluster from existing backup.\ntype RestoreSpec struct {\n\t// BackupStorageType is the type of the backup storage which is used as RestoreSource.\n\tBackupStorageType BackupStorageType `json:\"backupStorageType\"`\n\t// RestoreSource tells the where to get the backup and restore from.\n\tRestoreSource `json:\",inline\"`\n\t// EtcdCluster references an EtcdCluster resource whose metadata and spec\n\t// will be used to create the new restored EtcdCluster CR.\n\t// This reference EtcdCluster CR and all its resources will be deleted before the\n\t// restored EtcdCluster CR is created.\n\tEtcdCluster EtcdClusterRef `json:\"etcdCluster\"`\n}\n\n// EtcdCluster references an EtcdCluster resource whose metadata and spec\n// will be used to create the new restored EtcdCluster CR.\n// This reference EtcdCluster CR and all its resources will be deleted before the\n// restored EtcdCluster CR is created.\ntype EtcdClusterRef struct {\n\t// Name is the EtcdCluster resource name.\n\t// This reference EtcdCluster must be present in the same namespace as the restore-operator\n\tName string `json:\"name\"`\n}\n\ntype RestoreSource struct {\n\t// S3 tells where on S3 the backup is saved and how to fetch the backup.\n\tS3 *S3RestoreSource `json:\"s3,omitempty\"`\n\n\t// ABS tells where on ABS the backup is saved and how to fetch the backup.\n\tABS *ABSRestoreSource `json:\"abs,omitempty\"`\n\n\t// GCS tells where on GCS the backup is saved and how to fetch the backup.\n\tGCS *GCSRestoreSource `json:\"gcs,omitempty\"`\n\n\t// COS tells where on COS the backup is saved and how to fetch the backup.\n\tCOS *COSRestoreSource `json:\"cos,omitempty\"`\n\n\t// OSS tells where on OSS the backup is saved and how to fetch the backup.\n\tOSS *OSSRestoreSource `json:\"oss,omitempty\"`\n\n\t// HostPath tells where on HostPath the backup is saved and how to fetch the backup.\n\tHostPath *HostPathRestoreSource `json:\"hostPath,omitempty\"`\n}\n\ntype S3RestoreSource struct {\n\t// Path is the full s3 path where the backup is saved.\n\t// The format of the path must be: \"<s3-bucket-name>/<path-to-backup-file>\"\n\t// e.g: \"mybucket/etcd.backup\"\n\tPath string `json:\"path\"`\n\n\t// The name of the secret object that stores the AWS credential and config files.\n\t// The file name of the credential MUST be 'credentials'.\n\t// The file name of the config MUST be 'config'.\n\t// The profile to use in both files will be 'default'.\n\t//\n\t// AWSSecret overwrites the default etcd operator wide AWS credential and config.\n\tAWSSecret string `json:\"awsSecret\"`\n\n\t// Endpoint if blank points to aws. If specified, can point to s3 compatible object\n\t// stores.\n\tEndpoint string `json:\"endpoint\"`\n\n\t// ForcePathStyle forces to use path style over the default subdomain style.\n\t// This is useful when you have an s3 compatible endpoint that doesn't support\n\t// subdomain buckets.\n\tForcePathStyle bool `json:\"forcePathStyle\"`\n}\n\ntype ABSRestoreSource struct {\n\t// Path is the full abs path where the backup is saved.\n\t// The format of the path must be: \"<abs-container-name>/<path-to-backup-file>\"\n\t// e.g: \"myabscontainer/etcd.backup\"\n\tPath string `json:\"path\"`\n\n\t// The name of the secret object that stores the Azure Blob Storage credential.\n\tABSSecret string `json:\"absSecret\"`\n}\n\ntype GCSRestoreSource struct {\n\t// Path is the full GCS path where the backup is saved.\n\t// The format of the path must be: \"<gcs-bucket-name>/<path-to-backup-file>\"\n\t// e.g: \"mygcsbucket/etcd.backup\"\n\tPath string `json:\"path\"`\n\n\t// The name of the secret object that stores the Google storage credential\n\t// containing at most ONE of the following:\n\t// An access token with file name of 'access-token'.\n\t// JSON credentials with file name of 'credentials.json'.\n\t//\n\t// If omitted, client will use the default application credentials.\n\tGCPSecret string `json:\"gcpSecret,omitempty\"`\n}\n\ntype COSRestoreSource struct {\n\t// Path is the full cos path where the backup is saved.\n\t// The format of the path must be: \"<cos-container-name>/<path-to-backup-file>\"\n\t// e.g: \"mycoscontainer/etcd.backup\"\n\tPath string `json:\"path\"`\n\n\t// The name of the secret object that stores the QCLOUD COS Storage credential.\n\tCOSSecret string `json:\"cosSecret\"`\n}\ntype OSSRestoreSource struct {\n\t// Path is the full abs path where the backup is saved.\n\t// The format of the path must be: \"<oss-bucket-name>/<path-to-backup-file>\"\n\t// e.g: \"myossbucket/etcd.backup\"\n\tPath string `json:\"path\"`\n\n\t// The name of the secret object that stores the credential which will be used\n\t// to access Alibaba Cloud OSS.\n\t//\n\t// The secret must contain the following keys/fields:\n\t//     accessKeyID\n\t//     accessKeySecret\n\t//\n\t// The format of secret:\n\t//\n\t//   apiVersion: v1\n\t//   kind: Secret\n\t//   metadata:\n\t//     name: <my-credential-name>\n\t//   type: Opaque\n\t//   data:\n\t//     accessKeyID: <base64 of my-access-key-id>\n\t//     accessKeySecret: <base64 of my-access-key-secret>\n\t//\n\tOSSSecret string `json:\"ossSecret\"`\n\n\t// Endpoint is the OSS service endpoint on alibaba cloud, defaults to\n\t// \"http://oss-cn-hangzhou.aliyuncs.com\".\n\t//\n\t// Details about regions and endpoints, see:\n\t//  https://www.alibabacloud.com/help/doc-detail/31837.htm\n\tEndpoint string `json:\"endpoint,omitempty\"`\n}\n\ntype HostPathRestoreSource struct {\n\t// Path is the full cos path where the backup is saved.\n\t// The format of the path must be: \"<cos-container-name>/<path-to-backup-file>\"\n\t// e.g: \"mycoscontainer/etcd.backup\"\n\tPath string `json:\"path\"`\n}\n\n// RestoreStatus reports the status of this restore operation.\ntype RestoreStatus struct {\n\t// Succeeded indicates if the backup has Succeeded.\n\tSucceeded bool `json:\"succeeded\"`\n\t// Reason indicates the reason for any backup related failures.\n\tReason string `json:\"reason,omitempty\"`\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/apis/etcd/v1beta2/status.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage v1beta2\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\n\tv1 \"k8s.io/api/core/v1\"\n)\n\ntype ClusterPhase string\ntype ClusterConditionType string\n\nconst (\n\tClusterPhaseNone     ClusterPhase = \"\"\n\tClusterPhaseCreating              = \"Creating\"\n\tClusterPhaseRunning               = \"Running\"\n\tClusterPhaseFailed                = \"Failed\"\n\n\t// See ./doc/user/conditions_and_events.md\n\tClusterConditionAvailable  ClusterConditionType = \"Available\"\n\tClusterConditionRecovering                      = \"Recovering\"\n\tClusterConditionScaling                         = \"Scaling\"\n\tClusterConditionUpgrading                       = \"Upgrading\"\n)\n\ntype ClusterStatus struct {\n\t// Phase is the cluster running phase\n\tPhase  ClusterPhase `json:\"phase\"`\n\tReason string       `json:\"reason,omitempty\"`\n\n\t// ControlPuased indicates the operator pauses the control of the cluster.\n\tControlPaused bool `json:\"controlPaused,omitempty\"`\n\n\t// Condition keeps track of all cluster conditions, if they exist.\n\tConditions []ClusterCondition `json:\"conditions,omitempty\"`\n\n\t// Size is the current size of the cluster\n\tSize int `json:\"size\"`\n\n\t// ServiceName is the LB service for accessing etcd nodes.\n\tServiceName string `json:\"serviceName,omitempty\"`\n\n\t// ClientPort is the port for etcd client to access.\n\t// It's the same on client LB service and etcd nodes.\n\tClientPort int `json:\"clientPort,omitempty\"`\n\n\t// Members are the etcd members in the cluster\n\tMembers MembersStatus `json:\"members\"`\n\t// CurrentVersion is the current cluster version\n\tCurrentVersion string `json:\"currentVersion\"`\n\t// TargetVersion is the version the cluster upgrading to.\n\t// If the cluster is not upgrading, TargetVersion is empty.\n\tTargetVersion string `json:\"targetVersion\"`\n}\n\n// ClusterCondition represents one current condition of an etcd cluster.\n// A condition might not show up if it is not happening.\n// For example, if a cluster is not upgrading, the Upgrading condition would not show up.\n// If a cluster is upgrading and encountered a problem that prevents the upgrade,\n// the Upgrading condition's status will would be False and communicate the problem back.\ntype ClusterCondition struct {\n\t// Type of cluster condition.\n\tType ClusterConditionType `json:\"type\"`\n\t// Status of the condition, one of True, False, Unknown.\n\tStatus v1.ConditionStatus `json:\"status\"`\n\t// The last time this condition was updated.\n\tLastUpdateTime string `json:\"lastUpdateTime,omitempty\"`\n\t// Last time the condition transitioned from one status to another.\n\tLastTransitionTime string `json:\"lastTransitionTime,omitempty\"`\n\t// The reason for the condition's last transition.\n\tReason string `json:\"reason,omitempty\"`\n\t// A human readable message indicating details about the transition.\n\tMessage string `json:\"message,omitempty\"`\n}\n\ntype MembersStatus struct {\n\t// Ready are the etcd members that are ready to serve requests\n\t// The member names are the same as the etcd pod names\n\tReady []string `json:\"ready,omitempty\"`\n\t// Unready are the etcd members not ready to serve requests\n\tUnready []string `json:\"unready,omitempty\"`\n}\n\nfunc (cs *ClusterStatus) IsFailed() bool {\n\tif cs == nil {\n\t\treturn false\n\t}\n\treturn cs.Phase == ClusterPhaseFailed\n}\n\nfunc (cs *ClusterStatus) SetPhase(p ClusterPhase) {\n\tcs.Phase = p\n}\n\nfunc (cs *ClusterStatus) PauseControl() {\n\tcs.ControlPaused = true\n}\n\nfunc (cs *ClusterStatus) Control() {\n\tcs.ControlPaused = false\n}\n\nfunc (cs *ClusterStatus) UpgradeVersionTo(v string) {\n\tcs.TargetVersion = v\n}\n\nfunc (cs *ClusterStatus) SetVersion(v string) {\n\tcs.TargetVersion = \"\"\n\tcs.CurrentVersion = v\n}\n\nfunc (cs *ClusterStatus) SetReason(r string) {\n\tcs.Reason = r\n}\n\nfunc (cs *ClusterStatus) SetScalingUpCondition(from, to int) {\n\tc := newClusterCondition(ClusterConditionScaling, v1.ConditionTrue, \"Scaling up\", scalingMsg(from, to))\n\tcs.setClusterCondition(*c)\n}\n\nfunc (cs *ClusterStatus) SetScalingDownCondition(from, to int) {\n\tc := newClusterCondition(ClusterConditionScaling, v1.ConditionTrue, \"Scaling down\", scalingMsg(from, to))\n\tcs.setClusterCondition(*c)\n}\n\nfunc (cs *ClusterStatus) SetRecoveringCondition() {\n\tc := newClusterCondition(ClusterConditionRecovering, v1.ConditionTrue,\n\t\t\"Disaster recovery\", \"Majority is down. Recovering from backup\")\n\tcs.setClusterCondition(*c)\n\n\tcs.ClearCondition(ClusterConditionAvailable)\n}\n\nfunc (cs *ClusterStatus) SetUpgradingCondition(to string) {\n\t// TODO: show x/y members has upgraded.\n\tc := newClusterCondition(ClusterConditionUpgrading, v1.ConditionTrue,\n\t\t\"Cluster upgrading\", \"upgrading to \"+to)\n\tcs.setClusterCondition(*c)\n}\n\nfunc (cs *ClusterStatus) SetReadyCondition() {\n\tc := newClusterCondition(ClusterConditionAvailable, v1.ConditionTrue, \"Cluster available\", \"\")\n\tcs.setClusterCondition(*c)\n}\n\nfunc (cs *ClusterStatus) ClearCondition(t ClusterConditionType) {\n\tpos, _ := getClusterCondition(cs, t)\n\tif pos == -1 {\n\t\treturn\n\t}\n\tcs.Conditions = append(cs.Conditions[:pos], cs.Conditions[pos+1:]...)\n}\n\nfunc (cs *ClusterStatus) setClusterCondition(c ClusterCondition) {\n\tpos, cp := getClusterCondition(cs, c.Type)\n\tif cp != nil &&\n\t\tcp.Status == c.Status && cp.Reason == c.Reason && cp.Message == c.Message {\n\t\treturn\n\t}\n\n\tif cp != nil {\n\t\tcs.Conditions[pos] = c\n\t} else {\n\t\tcs.Conditions = append(cs.Conditions, c)\n\t}\n}\n\nfunc getClusterCondition(status *ClusterStatus, t ClusterConditionType) (int, *ClusterCondition) {\n\tfor i, c := range status.Conditions {\n\t\tif t == c.Type {\n\t\t\treturn i, &c\n\t\t}\n\t}\n\treturn -1, nil\n}\n\nfunc newClusterCondition(condType ClusterConditionType, status v1.ConditionStatus, reason, message string) *ClusterCondition {\n\tnow := time.Now().Format(time.RFC3339)\n\treturn &ClusterCondition{\n\t\tType:               condType,\n\t\tStatus:             status,\n\t\tLastUpdateTime:     now,\n\t\tLastTransitionTime: now,\n\t\tReason:             reason,\n\t\tMessage:            message,\n\t}\n}\n\nfunc scalingMsg(from, to int) string {\n\treturn fmt.Sprintf(\"Current cluster size: %d, desired cluster size: %d\", from, to)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/apis/etcd/v1beta2/zz_generated.deepcopy.go",
    "content": "// +build !ignore_autogenerated\n\n/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by deepcopy-gen. DO NOT EDIT.\n\npackage v1beta2\n\nimport (\n\tv1 \"k8s.io/api/core/v1\"\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n)\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *ABSBackupSource) DeepCopyInto(out *ABSBackupSource) {\n\t*out = *in\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ABSBackupSource.\nfunc (in *ABSBackupSource) DeepCopy() *ABSBackupSource {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(ABSBackupSource)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *ABSRestoreSource) DeepCopyInto(out *ABSRestoreSource) {\n\t*out = *in\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ABSRestoreSource.\nfunc (in *ABSRestoreSource) DeepCopy() *ABSRestoreSource {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(ABSRestoreSource)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *BackupPolicy) DeepCopyInto(out *BackupPolicy) {\n\t*out = *in\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupPolicy.\nfunc (in *BackupPolicy) DeepCopy() *BackupPolicy {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(BackupPolicy)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *BackupSource) DeepCopyInto(out *BackupSource) {\n\t*out = *in\n\tif in.S3 != nil {\n\t\tin, out := &in.S3, &out.S3\n\t\t*out = new(S3BackupSource)\n\t\t**out = **in\n\t}\n\tif in.ABS != nil {\n\t\tin, out := &in.ABS, &out.ABS\n\t\t*out = new(ABSBackupSource)\n\t\t**out = **in\n\t}\n\tif in.GCS != nil {\n\t\tin, out := &in.GCS, &out.GCS\n\t\t*out = new(GCSBackupSource)\n\t\t**out = **in\n\t}\n\tif in.COS != nil {\n\t\tin, out := &in.COS, &out.COS\n\t\t*out = new(COSBackupSource)\n\t\t**out = **in\n\t}\n\tif in.OSS != nil {\n\t\tin, out := &in.OSS, &out.OSS\n\t\t*out = new(OSSBackupSource)\n\t\t**out = **in\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupSource.\nfunc (in *BackupSource) DeepCopy() *BackupSource {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(BackupSource)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *BackupSpec) DeepCopyInto(out *BackupSpec) {\n\t*out = *in\n\tif in.EtcdEndpoints != nil {\n\t\tin, out := &in.EtcdEndpoints, &out.EtcdEndpoints\n\t\t*out = make([]string, len(*in))\n\t\tcopy(*out, *in)\n\t}\n\tif in.BackupPolicy != nil {\n\t\tin, out := &in.BackupPolicy, &out.BackupPolicy\n\t\t*out = new(BackupPolicy)\n\t\t**out = **in\n\t}\n\tin.BackupSource.DeepCopyInto(&out.BackupSource)\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupSpec.\nfunc (in *BackupSpec) DeepCopy() *BackupSpec {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(BackupSpec)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *BackupStatus) DeepCopyInto(out *BackupStatus) {\n\t*out = *in\n\tin.LastSuccessDate.DeepCopyInto(&out.LastSuccessDate)\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupStatus.\nfunc (in *BackupStatus) DeepCopy() *BackupStatus {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(BackupStatus)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *COSBackupSource) DeepCopyInto(out *COSBackupSource) {\n\t*out = *in\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new COSBackupSource.\nfunc (in *COSBackupSource) DeepCopy() *COSBackupSource {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(COSBackupSource)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *COSRestoreSource) DeepCopyInto(out *COSRestoreSource) {\n\t*out = *in\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new COSRestoreSource.\nfunc (in *COSRestoreSource) DeepCopy() *COSRestoreSource {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(COSRestoreSource)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *ClusterCondition) DeepCopyInto(out *ClusterCondition) {\n\t*out = *in\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterCondition.\nfunc (in *ClusterCondition) DeepCopy() *ClusterCondition {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(ClusterCondition)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *ClusterSpec) DeepCopyInto(out *ClusterSpec) {\n\t*out = *in\n\tif in.Pod != nil {\n\t\tin, out := &in.Pod, &out.Pod\n\t\t*out = new(PodPolicy)\n\t\t(*in).DeepCopyInto(*out)\n\t}\n\tif in.TLS != nil {\n\t\tin, out := &in.TLS, &out.TLS\n\t\t*out = new(TLSPolicy)\n\t\t(*in).DeepCopyInto(*out)\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterSpec.\nfunc (in *ClusterSpec) DeepCopy() *ClusterSpec {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(ClusterSpec)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *ClusterStatus) DeepCopyInto(out *ClusterStatus) {\n\t*out = *in\n\tif in.Conditions != nil {\n\t\tin, out := &in.Conditions, &out.Conditions\n\t\t*out = make([]ClusterCondition, len(*in))\n\t\tcopy(*out, *in)\n\t}\n\tin.Members.DeepCopyInto(&out.Members)\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterStatus.\nfunc (in *ClusterStatus) DeepCopy() *ClusterStatus {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(ClusterStatus)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdBackup) DeepCopyInto(out *EtcdBackup) {\n\t*out = *in\n\tout.TypeMeta = in.TypeMeta\n\tin.ObjectMeta.DeepCopyInto(&out.ObjectMeta)\n\tin.Spec.DeepCopyInto(&out.Spec)\n\tin.Status.DeepCopyInto(&out.Status)\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdBackup.\nfunc (in *EtcdBackup) DeepCopy() *EtcdBackup {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdBackup)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.\nfunc (in *EtcdBackup) DeepCopyObject() runtime.Object {\n\tif c := in.DeepCopy(); c != nil {\n\t\treturn c\n\t}\n\treturn nil\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdBackupList) DeepCopyInto(out *EtcdBackupList) {\n\t*out = *in\n\tout.TypeMeta = in.TypeMeta\n\tout.ListMeta = in.ListMeta\n\tif in.Items != nil {\n\t\tin, out := &in.Items, &out.Items\n\t\t*out = make([]EtcdBackup, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdBackupList.\nfunc (in *EtcdBackupList) DeepCopy() *EtcdBackupList {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdBackupList)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.\nfunc (in *EtcdBackupList) DeepCopyObject() runtime.Object {\n\tif c := in.DeepCopy(); c != nil {\n\t\treturn c\n\t}\n\treturn nil\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdCluster) DeepCopyInto(out *EtcdCluster) {\n\t*out = *in\n\tout.TypeMeta = in.TypeMeta\n\tin.ObjectMeta.DeepCopyInto(&out.ObjectMeta)\n\tin.Spec.DeepCopyInto(&out.Spec)\n\tin.Status.DeepCopyInto(&out.Status)\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdCluster.\nfunc (in *EtcdCluster) DeepCopy() *EtcdCluster {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdCluster)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.\nfunc (in *EtcdCluster) DeepCopyObject() runtime.Object {\n\tif c := in.DeepCopy(); c != nil {\n\t\treturn c\n\t}\n\treturn nil\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdClusterList) DeepCopyInto(out *EtcdClusterList) {\n\t*out = *in\n\tout.TypeMeta = in.TypeMeta\n\tout.ListMeta = in.ListMeta\n\tif in.Items != nil {\n\t\tin, out := &in.Items, &out.Items\n\t\t*out = make([]EtcdCluster, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdClusterList.\nfunc (in *EtcdClusterList) DeepCopy() *EtcdClusterList {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdClusterList)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.\nfunc (in *EtcdClusterList) DeepCopyObject() runtime.Object {\n\tif c := in.DeepCopy(); c != nil {\n\t\treturn c\n\t}\n\treturn nil\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdClusterRef) DeepCopyInto(out *EtcdClusterRef) {\n\t*out = *in\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdClusterRef.\nfunc (in *EtcdClusterRef) DeepCopy() *EtcdClusterRef {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdClusterRef)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdRestore) DeepCopyInto(out *EtcdRestore) {\n\t*out = *in\n\tout.TypeMeta = in.TypeMeta\n\tin.ObjectMeta.DeepCopyInto(&out.ObjectMeta)\n\tin.Spec.DeepCopyInto(&out.Spec)\n\tout.Status = in.Status\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdRestore.\nfunc (in *EtcdRestore) DeepCopy() *EtcdRestore {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdRestore)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.\nfunc (in *EtcdRestore) DeepCopyObject() runtime.Object {\n\tif c := in.DeepCopy(); c != nil {\n\t\treturn c\n\t}\n\treturn nil\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *EtcdRestoreList) DeepCopyInto(out *EtcdRestoreList) {\n\t*out = *in\n\tout.TypeMeta = in.TypeMeta\n\tout.ListMeta = in.ListMeta\n\tif in.Items != nil {\n\t\tin, out := &in.Items, &out.Items\n\t\t*out = make([]EtcdRestore, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdRestoreList.\nfunc (in *EtcdRestoreList) DeepCopy() *EtcdRestoreList {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(EtcdRestoreList)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.\nfunc (in *EtcdRestoreList) DeepCopyObject() runtime.Object {\n\tif c := in.DeepCopy(); c != nil {\n\t\treturn c\n\t}\n\treturn nil\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *GCSBackupSource) DeepCopyInto(out *GCSBackupSource) {\n\t*out = *in\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GCSBackupSource.\nfunc (in *GCSBackupSource) DeepCopy() *GCSBackupSource {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(GCSBackupSource)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *GCSRestoreSource) DeepCopyInto(out *GCSRestoreSource) {\n\t*out = *in\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GCSRestoreSource.\nfunc (in *GCSRestoreSource) DeepCopy() *GCSRestoreSource {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(GCSRestoreSource)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *MemberSecret) DeepCopyInto(out *MemberSecret) {\n\t*out = *in\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemberSecret.\nfunc (in *MemberSecret) DeepCopy() *MemberSecret {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(MemberSecret)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *MembersStatus) DeepCopyInto(out *MembersStatus) {\n\t*out = *in\n\tif in.Ready != nil {\n\t\tin, out := &in.Ready, &out.Ready\n\t\t*out = make([]string, len(*in))\n\t\tcopy(*out, *in)\n\t}\n\tif in.Unready != nil {\n\t\tin, out := &in.Unready, &out.Unready\n\t\t*out = make([]string, len(*in))\n\t\tcopy(*out, *in)\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MembersStatus.\nfunc (in *MembersStatus) DeepCopy() *MembersStatus {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(MembersStatus)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *OSSBackupSource) DeepCopyInto(out *OSSBackupSource) {\n\t*out = *in\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSSBackupSource.\nfunc (in *OSSBackupSource) DeepCopy() *OSSBackupSource {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(OSSBackupSource)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *OSSRestoreSource) DeepCopyInto(out *OSSRestoreSource) {\n\t*out = *in\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSSRestoreSource.\nfunc (in *OSSRestoreSource) DeepCopy() *OSSRestoreSource {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(OSSRestoreSource)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *PodPolicy) DeepCopyInto(out *PodPolicy) {\n\t*out = *in\n\tif in.Labels != nil {\n\t\tin, out := &in.Labels, &out.Labels\n\t\t*out = make(map[string]string, len(*in))\n\t\tfor key, val := range *in {\n\t\t\t(*out)[key] = val\n\t\t}\n\t}\n\tif in.NodeSelector != nil {\n\t\tin, out := &in.NodeSelector, &out.NodeSelector\n\t\t*out = make(map[string]string, len(*in))\n\t\tfor key, val := range *in {\n\t\t\t(*out)[key] = val\n\t\t}\n\t}\n\tif in.Affinity != nil {\n\t\tin, out := &in.Affinity, &out.Affinity\n\t\t*out = new(v1.Affinity)\n\t\t(*in).DeepCopyInto(*out)\n\t}\n\tin.Resources.DeepCopyInto(&out.Resources)\n\tif in.Tolerations != nil {\n\t\tin, out := &in.Tolerations, &out.Tolerations\n\t\t*out = make([]v1.Toleration, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n\tif in.EtcdEnv != nil {\n\t\tin, out := &in.EtcdEnv, &out.EtcdEnv\n\t\t*out = make([]v1.EnvVar, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n\tif in.PersistentVolumeClaimSpec != nil {\n\t\tin, out := &in.PersistentVolumeClaimSpec, &out.PersistentVolumeClaimSpec\n\t\t*out = new(v1.PersistentVolumeClaimSpec)\n\t\t(*in).DeepCopyInto(*out)\n\t}\n\tif in.Annotations != nil {\n\t\tin, out := &in.Annotations, &out.Annotations\n\t\t*out = make(map[string]string, len(*in))\n\t\tfor key, val := range *in {\n\t\t\t(*out)[key] = val\n\t\t}\n\t}\n\tif in.SecurityContext != nil {\n\t\tin, out := &in.SecurityContext, &out.SecurityContext\n\t\t*out = new(v1.PodSecurityContext)\n\t\t(*in).DeepCopyInto(*out)\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodPolicy.\nfunc (in *PodPolicy) DeepCopy() *PodPolicy {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(PodPolicy)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *RestoreSource) DeepCopyInto(out *RestoreSource) {\n\t*out = *in\n\tif in.S3 != nil {\n\t\tin, out := &in.S3, &out.S3\n\t\t*out = new(S3RestoreSource)\n\t\t**out = **in\n\t}\n\tif in.ABS != nil {\n\t\tin, out := &in.ABS, &out.ABS\n\t\t*out = new(ABSRestoreSource)\n\t\t**out = **in\n\t}\n\tif in.GCS != nil {\n\t\tin, out := &in.GCS, &out.GCS\n\t\t*out = new(GCSRestoreSource)\n\t\t**out = **in\n\t}\n\tif in.COS != nil {\n\t\tin, out := &in.COS, &out.COS\n\t\t*out = new(COSRestoreSource)\n\t\t**out = **in\n\t}\n\tif in.OSS != nil {\n\t\tin, out := &in.OSS, &out.OSS\n\t\t*out = new(OSSRestoreSource)\n\t\t**out = **in\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RestoreSource.\nfunc (in *RestoreSource) DeepCopy() *RestoreSource {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(RestoreSource)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *RestoreSpec) DeepCopyInto(out *RestoreSpec) {\n\t*out = *in\n\tin.RestoreSource.DeepCopyInto(&out.RestoreSource)\n\tout.EtcdCluster = in.EtcdCluster\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RestoreSpec.\nfunc (in *RestoreSpec) DeepCopy() *RestoreSpec {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(RestoreSpec)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *RestoreStatus) DeepCopyInto(out *RestoreStatus) {\n\t*out = *in\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RestoreStatus.\nfunc (in *RestoreStatus) DeepCopy() *RestoreStatus {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(RestoreStatus)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *S3BackupSource) DeepCopyInto(out *S3BackupSource) {\n\t*out = *in\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S3BackupSource.\nfunc (in *S3BackupSource) DeepCopy() *S3BackupSource {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(S3BackupSource)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *S3RestoreSource) DeepCopyInto(out *S3RestoreSource) {\n\t*out = *in\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S3RestoreSource.\nfunc (in *S3RestoreSource) DeepCopy() *S3RestoreSource {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(S3RestoreSource)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *StaticTLS) DeepCopyInto(out *StaticTLS) {\n\t*out = *in\n\tif in.Member != nil {\n\t\tin, out := &in.Member, &out.Member\n\t\t*out = new(MemberSecret)\n\t\t**out = **in\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StaticTLS.\nfunc (in *StaticTLS) DeepCopy() *StaticTLS {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(StaticTLS)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *TLSPolicy) DeepCopyInto(out *TLSPolicy) {\n\t*out = *in\n\tif in.Static != nil {\n\t\tin, out := &in.Static, &out.Static\n\t\t*out = new(StaticTLS)\n\t\t(*in).DeepCopyInto(*out)\n\t}\n\treturn\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSPolicy.\nfunc (in *TLSPolicy) DeepCopy() *TLSPolicy {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(TLSPolicy)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/backup/backup_manager.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage backup\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"fmt\"\n\t\"sort\"\n\t\"time\"\n\n\t\"github.com/coreos/etcd-operator/pkg/backup/writer\"\n\t\"github.com/coreos/etcd-operator/pkg/util/constants\"\n\n\t\"github.com/coreos/etcd/clientv3\"\n\t\"github.com/sirupsen/logrus\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n)\n\n// BackupManager backups an etcd cluster.\ntype BackupManager struct {\n\tkubecli kubernetes.Interface\n\n\tendpoints     []string\n\tnamespace     string\n\tusername      string\n\tpassword      string\n\tetcdTLSConfig *tls.Config\n\n\tbw writer.Writer\n}\n\n// NewBackupManagerFromWriter creates a BackupManager with backup writer.\nfunc NewBackupManagerFromWriter(kubecli kubernetes.Interface, bw writer.Writer, tc *tls.Config, endpoints []string, namespace, username, password string) *BackupManager {\n\treturn &BackupManager{\n\t\tkubecli:       kubecli,\n\t\tendpoints:     endpoints,\n\t\tnamespace:     namespace,\n\t\tusername:      username,\n\t\tpassword:      password,\n\t\tetcdTLSConfig: tc,\n\t\tbw:            bw,\n\t}\n}\n\n// SaveSnap uses backup writer to save etcd snapshot to a specified S3 path\n// and returns backup etcd server's kv store revision and its version.\nfunc (bm *BackupManager) SaveSnap(ctx context.Context, s3Path string, isPeriodic bool) (int64, string, *metav1.Time, error) {\n\tnow := time.Now().Local()\n\tetcdcli, rev, err := bm.etcdClientWithMaxRevision(ctx)\n\tif err != nil {\n\t\treturn 0, \"\", nil, fmt.Errorf(\"create etcd client failed: %v\", err)\n\t}\n\tdefer etcdcli.Close()\n\n\tresp, err := etcdcli.Status(ctx, etcdcli.Endpoints()[0])\n\tif err != nil {\n\t\treturn 0, \"\", nil, fmt.Errorf(\"failed to retrieve etcd version from the status call: %v\", err)\n\t}\n\n\trc, err := etcdcli.Snapshot(ctx)\n\tif err != nil {\n\t\treturn 0, \"\", nil, fmt.Errorf(\"failed to receive snapshot (%v)\", err)\n\t}\n\tdefer rc.Close()\n\tif isPeriodic {\n\t\ts3Path = fmt.Sprintf(s3Path+\"_v%d_%s\", rev, now.Format(\"2006-01-02-15:04:05\"))\n\t}\n\t_, err = bm.bw.Write(ctx, s3Path, rc)\n\tif err != nil {\n\t\treturn 0, \"\", nil, fmt.Errorf(\"failed to write snapshot (%v)\", err)\n\t}\n\treturn rev, resp.Version, &metav1.Time{Time: now}, nil\n}\n\n// EnsureMaxBackup to ensure the number of snapshot is under maxcount\n// if the number of snapshot exceeded than maxcount, delete oldest snapshot\nfunc (bm *BackupManager) EnsureMaxBackup(ctx context.Context, basePath string, maxCount int) error {\n\tsavedSnapShots, err := bm.bw.List(ctx, basePath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get exisiting snapshots: %v\", err)\n\t}\n\tsort.Sort(sort.Reverse(sort.StringSlice(savedSnapShots)))\n\tfor i, snapshotPath := range savedSnapShots {\n\t\tif i < maxCount {\n\t\t\tcontinue\n\t\t}\n\t\terr := bm.bw.Delete(ctx, snapshotPath)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to delete snapshot: %v\", err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// etcdClientWithMaxRevision gets the etcd endpoint with the maximum kv store revision\n// and returns the etcd client of that member.\nfunc (bm *BackupManager) etcdClientWithMaxRevision(ctx context.Context) (*clientv3.Client, int64, error) {\n\tetcdcli, rev, err := getClientWithMaxRev(ctx, bm.endpoints, bm.etcdTLSConfig, bm.username, bm.password)\n\tif err != nil {\n\t\treturn nil, 0, fmt.Errorf(\"failed to get etcd client with maximum kv store revision: %v\", err)\n\t}\n\treturn etcdcli, rev, nil\n}\n\nfunc getClientWithMaxRev(ctx context.Context, endpoints []string, tc *tls.Config, username, password string) (*clientv3.Client, int64, error) {\n\tmapEps := make(map[string]*clientv3.Client)\n\tvar maxClient *clientv3.Client\n\tmaxRev := int64(0)\n\terrors := make([]string, 0)\n\tfor _, endpoint := range endpoints {\n\t\t// TODO: update clientv3 to 3.2.x and then use ctx as in clientv3.Config.\n\t\tcfg := clientv3.Config{\n\t\t\tEndpoints:   []string{endpoint},\n\t\t\tDialTimeout: constants.DefaultDialTimeout,\n\t\t\tTLS:         tc,\n\t\t\tUsername:    username,\n\t\t\tPassword:    password,\n\t\t}\n\t\tetcdcli, err := clientv3.New(cfg)\n\t\tif err != nil {\n\t\t\terrors = append(errors, fmt.Sprintf(\"failed to create etcd client for endpoint (%v): %v\", endpoint, err))\n\t\t\tcontinue\n\t\t}\n\t\tmapEps[endpoint] = etcdcli\n\n\t\tresp, err := etcdcli.Get(ctx, \"/\", clientv3.WithSerializable())\n\t\tif err != nil {\n\t\t\terrors = append(errors, fmt.Sprintf(\"failed to get revision from endpoint (%s):%v\", endpoint, err))\n\t\t\tcontinue\n\t\t}\n\n\t\tlogrus.Infof(\"getMaxRev: endpoint %s revision (%d)\", endpoint, resp.Header.Revision)\n\t\tif resp.Header.Revision > maxRev {\n\t\t\tmaxRev = resp.Header.Revision\n\t\t\tmaxClient = etcdcli\n\t\t}\n\t}\n\n\t// close all open clients that are not maxClient.\n\tfor _, cli := range mapEps {\n\t\tif cli == maxClient {\n\t\t\tcontinue\n\t\t}\n\t\tcli.Close()\n\t}\n\n\tif maxClient == nil {\n\t\terrors = append(errors, fmt.Sprintf(\"could not create an etcd client for the max revision purpose from given endpoints (%v)\", endpoints))\n\t}\n\n\tvar err error\n\tif len(errors) > 0 {\n\t\terrorStr := \"\"\n\t\tfor _, errStr := range errors {\n\t\t\terrorStr += errStr + \"\\n\"\n\t\t}\n\t\terr = fmt.Errorf(errorStr)\n\t}\n\n\tif maxClient == nil {\n\t\treturn nil, 0, err\n\t}\n\n\treturn maxClient, maxRev, err\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/backup/backupapi/http.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage backupapi\n\nimport (\n\t\"net/url\"\n\t\"path\"\n)\n\nconst (\n\tAPIV1 = \"/v1\"\n)\n\n// BackupURLForRestore creates a URL struct for retrieving an existing backup specified by a restore CR\nfunc BackupURLForRestore(scheme, host, restoreName string) *url.URL {\n\treturn &url.URL{\n\t\tScheme: scheme,\n\t\tHost:   host,\n\t\tPath:   path.Join(APIV1, \"backup\", restoreName),\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/backup/reader/abs_reader.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage reader\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/coreos/etcd-operator/pkg/backup/util\"\n\n\t\"github.com/Azure/azure-sdk-for-go/storage\"\n)\n\n// ensure absReader satisfies reader interface.\nvar _ Reader = &absReader{}\n\n// absReader provides Reader implementation for reading a file from ABS\ntype absReader struct {\n\tabs *storage.BlobStorageClient\n}\n\n// NewABSReader return a Reader implementation to read a file from ABS in the form of absReader\nfunc NewABSReader(abs *storage.BlobStorageClient) Reader {\n\treturn &absReader{abs}\n}\n\n// Open opens the file on path where path must be in the format \"<abs-container-name>/<key>\"\nfunc (absr *absReader) Open(path string) (io.ReadCloser, error) {\n\tcontainer, key, err := util.ParseBucketAndKey(path)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse abs container and key: %v\", err)\n\t}\n\n\tcontainerRef := absr.abs.GetContainerReference(container)\n\tcontainerExists, err := containerRef.Exists()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif !containerExists {\n\t\treturn nil, fmt.Errorf(\"container %v does not exist\", container)\n\t}\n\n\tblob := containerRef.GetBlobReference(key)\n\treturn blob.Get(&storage.GetBlobOptions{})\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/backup/reader/cos_reader.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage reader\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"github.com/coreos/etcd-operator/pkg/backup/util\"\n\tcos \"github.com/tencentyun/cos-go-sdk-v5\"\n\t\"io\"\n\t\"net/url\"\n)\n\n// ensure cosReader satisfies reader interface.\nvar _ Reader = &cosReader{}\n\ntype cosReader struct {\n\tcos *cos.Client\n}\n\n// NewCOSReader creates a cos reader.\nfunc NewCOSReader(cos *cos.Client) Reader {\n\treturn &cosReader{cos}\n}\n\n// Open opens the file on path where path must be in the format \"<cos-bucket-name>/<key>\"\nfunc (cosr *cosReader) Open(path string) (io.ReadCloser, error) {\n\tbk, key, err := util.ParseBucketAndKey(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfmt.Printf(\"bucket name is %s,key is %s\\n\", bk, key)\n\t//opt := &cos.ObjectGetOptions{\n\t//\tResponseContentType: \"text/html\",\n\t//}\n\tu, err := url.Parse(\"https://\" + bk)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcosr.cos.BaseURL = &cos.BaseURL{BucketURL: u}\n\tresp, err := cosr.cos.Object.Get(context.Background(), key, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn resp.Body, nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/backup/reader/gcs_reader.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage reader\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/coreos/etcd-operator/pkg/backup/util\"\n\n\t\"cloud.google.com/go/storage\"\n)\n\n// ensure gcsReader satisfies reader interface.\nvar _ Reader = &gcsReader{}\n\n// gcsReader provides Reader implementation for reading a file from GCS\ntype gcsReader struct {\n\tctx context.Context\n\tgcs *storage.Client\n}\n\n// NewGCSReader return a Reader implementation to read a file from GCS in the form of gcsReader\nfunc NewGCSReader(ctx context.Context, gcs *storage.Client) Reader {\n\treturn &gcsReader{ctx, gcs}\n}\n\n// Open opens the file on path where path must be in the format \"<gcs-bucket-name>/<key>\"\nfunc (gcsr *gcsReader) Open(path string) (io.ReadCloser, error) {\n\tbucket, key, err := util.ParseBucketAndKey(path)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse gcs bucket and key: %v\", err)\n\t}\n\n\treturn gcsr.gcs.Bucket(bucket).Object(key).NewReader(gcsr.ctx)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/backup/reader/hostPath_reader.go",
    "content": "// Copyright 2019 The etcd-operator 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\npackage reader\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"bytes\"\n\t\"io/ioutil\"\n)\n\n// ensure hostPathReader satisfies reader interface.\nvar _ Reader = &hostPathReader{}\n\n// hostPathReader provides Reader imlementation for reading a file from S3\ntype hostPathReader struct {\n\tbasePath string\n}\n\n// NewHostPathReader return a Reader implementation to read a file from hostPath in the form of hostPathReader\nfunc NewHostPathReader(path string) Reader {\n\treturn &hostPathReader{path}\n}\n\n// Open opens the file on path where path must be in the format \"/data/etcdbackup_xxxx\"\nfunc (hostPathr *hostPathReader) Open(path string) (io.ReadCloser, error) {\n\tfile,err := ioutil.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read hostPath file %s: %v\", path,err)\n\t}\n\treturn ioutil.NopCloser(bytes.NewReader(file)),err\n}"
  },
  {
    "path": "third_party/etcd-operator/pkg/backup/reader/oss_reader.go",
    "content": "// Copyright 2019 The etcd-operator 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\npackage reader\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/coreos/etcd-operator/pkg/backup/util\"\n\n\t\"github.com/aliyun/aliyun-oss-go-sdk/oss\"\n)\n\n// ensure ossReader satisfies reader interface.\nvar _ Reader = &ossReader{}\n\n// ossReader provides Reader imlementation for reading a file from S3\ntype ossReader struct {\n\tclient *oss.Client\n}\n\n// NewOSSReader return a Reader implementation to read a file from OSS in the form of ossReader\nfunc NewOSSReader(client *oss.Client) Reader {\n\treturn &ossReader{client: client}\n}\n\n// Open opens the file on path where path must be in the format \"<oss-bucket-name>/<key>\"\nfunc (ossr *ossReader) Open(path string) (io.ReadCloser, error) {\n\tbk, key, err := util.ParseBucketAndKey(path)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse oss bucket and key: %v\", err)\n\t}\n\n\texist, err := ossr.client.IsBucketExist(bk)\n\tif err != nil {\n\t\treturn nil, err\n\t} else if !exist {\n\t\treturn nil, fmt.Errorf(\"OSS: bucket<%s> not found\", bk)\n\t}\n\n\tbucket, err := ossr.client.Bucket(bk)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn bucket.GetObject(key)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/backup/reader/reader.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage reader\n\nimport \"io\"\n\n// Reader defines required reader operations\ntype Reader interface {\n\t// Open opens up a backup file for reading.\n\tOpen(path string) (rc io.ReadCloser, err error)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/backup/reader/s3_reader.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage reader\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/coreos/etcd-operator/pkg/backup/util\"\n\n\t\"github.com/aws/aws-sdk-go/aws\"\n\t\"github.com/aws/aws-sdk-go/service/s3\"\n)\n\n// ensure s3Reader satisfies reader interface.\nvar _ Reader = &s3Reader{}\n\n// s3Reader provides Reader imlementation for reading a file from S3\ntype s3Reader struct {\n\ts3 *s3.S3\n}\n\nfunc NewS3Reader(s3 *s3.S3) Reader {\n\treturn &s3Reader{s3}\n}\n\n// Open opens the file on path where path must be in the format \"<s3-bucket-name>/<key>\"\nfunc (s3r *s3Reader) Open(path string) (io.ReadCloser, error) {\n\tbucket, key, err := util.ParseBucketAndKey(path)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse s3 bucket and key: %v\", err)\n\t}\n\tresp, err := s3r.s3.GetObject(&s3.GetObjectInput{\n\t\tBucket: aws.String(bucket),\n\t\tKey:    aws.String(key),\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn resp.Body, nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/backup/util/constants.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage util\n\nconst (\n\tBackupFilenameSuffix = \"etcd.backup\"\n)\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/backup/util/util.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage util\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\nfunc MakeBackupName(ver string, rev int64) string {\n\treturn fmt.Sprintf(\"%s_%016x_%s\", ver, rev, BackupFilenameSuffix)\n}\n\n// ParseBucketAndKey parses the path to return the s3 bucket name and key(path in the bucket)\n// returns error if path is not in the format <s3-bucket-name>/<key>\nfunc ParseBucketAndKey(path string) (string, string, error) {\n\ttoks := strings.SplitN(path, \"/\", 2)\n\tif len(toks) != 2 || len(toks[0]) == 0 || len(toks[1]) == 0 {\n\t\treturn \"\", \"\", fmt.Errorf(\"Invalid S3 path (%v)\", path)\n\t}\n\treturn toks[0], toks[1], nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/backup/writer/abs_writer.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage writer\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/coreos/etcd-operator/pkg/backup/util\"\n\n\t\"github.com/Azure/azure-sdk-for-go/storage\"\n\t\"github.com/pborman/uuid\"\n)\n\nvar _ Writer = &absWriter{}\n\ntype absWriter struct {\n\tabs *storage.BlobStorageClient\n}\n\n// NewABSWriter creates a abs writer.\nfunc NewABSWriter(abs *storage.BlobStorageClient) Writer {\n\treturn &absWriter{abs}\n}\n\nconst (\n\t// AzureBlobBlockChunkLimitInBytes 100MiB is the limit\n\tAzureBlobBlockChunkLimitInBytes = 100 * 1024 * 1024\n)\n\n// Write writes the backup file to the given abs path, \"<abs-container-name>/<key>\".\nfunc (absw *absWriter) Write(ctx context.Context, path string, r io.Reader) (int64, error) {\n\t// TODO: support context.\n\tcontainer, key, err := util.ParseBucketAndKey(path)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\tcontainerRef := absw.abs.GetContainerReference(container)\n\tcontainerExists, err := containerRef.Exists()\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\tif !containerExists {\n\t\treturn 0, fmt.Errorf(\"container %v does not exist\", container)\n\t}\n\n\tblob := containerRef.GetBlobReference(key)\n\terr = blob.CreateBlockBlob(&storage.PutBlobOptions{})\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\tbuf := new(bytes.Buffer)\n\tbuf.ReadFrom(r)\n\tlen := len(buf.Bytes())\n\tchunckCount := len/AzureBlobBlockChunkLimitInBytes + 1\n\tblocks := make([]storage.Block, 0, chunckCount)\n\tfor i := 0; i < chunckCount; i++ {\n\t\tblockID := base64.StdEncoding.EncodeToString([]byte(uuid.New()))\n\t\tblocks = append(blocks, storage.Block{ID: blockID, Status: storage.BlockStatusLatest})\n\t\tstart := i * AzureBlobBlockChunkLimitInBytes\n\t\tend := (i + 1) * AzureBlobBlockChunkLimitInBytes\n\t\tif len < end {\n\t\t\tend = len\n\t\t}\n\n\t\tchunk := buf.Bytes()[start:end]\n\t\terr = blob.PutBlock(blockID, chunk, &storage.PutBlockOptions{})\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t}\n\n\terr = blob.PutBlockList(blocks, &storage.PutBlockListOptions{})\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\t_, err = blob.Get(&storage.GetBlobOptions{})\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\treturn blob.Properties.ContentLength, nil\n}\n\nfunc (absw *absWriter) List(ctx context.Context, basePath string) ([]string, error) {\n\t// TODO: support context.\n\tcontainer, key, err := util.ParseBucketAndKey(basePath)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tcontainerRef := absw.abs.GetContainerReference(container)\n\tcontainerExists, err := containerRef.Exists()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif !containerExists {\n\t\treturn nil, fmt.Errorf(\"container %v does not exist\", container)\n\t}\n\n\tblobs, err := containerRef.ListBlobs(\n\t\tstorage.ListBlobsParameters{Prefix: key})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tblobKeys := []string{}\n\tfor _, blob := range blobs.Blobs {\n\t\tblobKeys = append(blobKeys, container+\"/\"+blob.Name)\n\t}\n\treturn blobKeys, nil\n}\n\nfunc (absw *absWriter) Delete(ctx context.Context, path string) error {\n\t// TODO: support context.\n\tcontainer, key, err := util.ParseBucketAndKey(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tcontainerRef := absw.abs.GetContainerReference(container)\n\tcontainerExists, err := containerRef.Exists()\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !containerExists {\n\t\treturn fmt.Errorf(\"container %v does not exist\", container)\n\t}\n\n\tblob := containerRef.GetBlobReference(key)\n\treturn blob.Delete(&storage.DeleteBlobOptions{})\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/backup/writer/cos_writer.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage writer\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"github.com/coreos/etcd-operator/pkg/backup/util\"\n\t\"github.com/sirupsen/logrus\"\n\tcos \"github.com/tencentyun/cos-go-sdk-v5\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n)\n\nvar _ Writer = &cosWriter{}\n\ntype cosWriter struct {\n\tcos *cos.Client\n}\n\n// NewCOSWriter creates a cos writer.\nfunc NewCOSWriter(cos *cos.Client) Writer {\n\treturn &cosWriter{cos}\n}\n\n// Write writes the backup file to the given cos path, \"<cos-bucket-name>/<key>\".\nfunc (cosw *cosWriter) Write(ctx context.Context, path string, r io.Reader) (int64, error) {\n\tbk, key, err := util.ParseBucketAndKey(path)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tfmt.Printf(\"bucket name is %s,key is %s\\n\", bk, key)\n\n\tu, err := url.Parse(\"https://\" + bk)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tcosw.cos.BaseURL = &cos.BaseURL{BucketURL: u}\n\n\t// create bucket if not exist\n\trsp, err := cosw.cos.Bucket.Head(ctx)\n\tif rsp != nil && rsp.StatusCode == http.StatusNotFound {\n\t\t_, err := cosw.cos.Bucket.Put(ctx, &cos.BucketPutOptions{\n\t\t\tXCosACL: \"private\",\n\t\t})\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t} else if err != nil {\n\t\treturn 0, err\n\t}\n\n\toptcom := &cos.CompleteMultipartUploadOptions{}\n\n\tv, _, err := cosw.cos.Object.InitiateMultipartUpload(ctx, key, nil)\n\tif err != nil {\n\t\tlogrus.Errorf(\"failed to init multipart upload, err: %v\", err)\n\t\treturn 0, err\n\t}\n\tuploadID := v.UploadID\n\n\n\tcount := 1\n\tp := make([]byte, 1 << 30)\n\tfor {\n\t\t//n, err := r.Read(p)\n\t\tn, err := io.ReadFull(r, p)\n\t\tif err != nil  && err != io.ErrUnexpectedEOF{\n\t\t\tif err == io.EOF {\n\t\t\t\tlogrus.Infof(\"meet EOF, complete reading data\")\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tlogrus.Errorf(\"failed to read data, err: %v\", err)\n\t\t\treturn 0, err\n\t\t}\n\n\t\ttemp := strings.NewReader(string(p[:n]))\n\n\t\tresp, err := cosw.cos.Object.UploadPart(ctx, key, uploadID, count, temp, nil)\n\t\tif err != nil {\n\t\t\tlogrus.Errorf(\"failed to upload part %d, err: %v\", count, err)\n\t\t\treturn 0, err\n\t\t}\n\n\t\toptcom.Parts = append(optcom.Parts, cos.Object{\n\t\t\tPartNumber: count, ETag: resp.Header.Get(\"ETag\"),\n\t\t})\n\n\t\tlogrus.Infof(\"complete uploading part %d\", count)\n\n\t\tcount++\n\t}\n\n\t_, _, err = cosw.cos.Object.CompleteMultipartUpload(ctx, key, uploadID, optcom)\n\tif err != nil {\n\t\tlogrus.Errorf(\"failed to complete uploading multipart, uploadID: %s, err: %v\", uploadID, err)\n\t\treturn 0, err\n\t}\n\n\tlogrus.Infof(\"complete uploading the backup file, bucket name is %s, key is %s\", bk, key)\n\n\tresp, err := cosw.cos.Object.Get(ctx, key, nil)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tresp.Body.Close()\n\treturn resp.ContentLength, nil\n}\n\nfunc (cosw *cosWriter) Delete(ctx context.Context, path string) error {\n\tbk, key, err := util.ParseBucketAndKey(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tu, err := url.Parse(\"https://\" + bk)\n\tif err != nil {\n\t\treturn err\n\t}\n\tcosw.cos.BaseURL = &cos.BaseURL{BucketURL: u}\n\n\t_, err = cosw.cos.Object.Delete(ctx, key)\n\n\treturn err\n}\n\n// List return the file paths which match the given cos path\nfunc (cosw *cosWriter) List(ctx context.Context, basePath string) ([]string, error) {\n\tbk, key, err := util.ParseBucketAndKey(basePath)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tu, err := url.Parse(\"https://\" + bk)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcosw.cos.BaseURL = &cos.BaseURL{BucketURL: u}\n\n\tobjects, _, err := cosw.cos.Bucket.Get(ctx, &cos.BucketGetOptions{Prefix: key})\n\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tobjectKeys := []string{}\n\tfor _, object := range objects.Contents {\n\t\tobjectKeys = append(objectKeys, bk+\"/\"+object.Key)\n\t}\n\treturn objectKeys, nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/backup/writer/gcs_writer.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage writer\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/coreos/etcd-operator/pkg/backup/util\"\n\n\t\"cloud.google.com/go/storage\"\n\t\"github.com/sirupsen/logrus\"\n\t\"google.golang.org/api/iterator\"\n)\n\nvar _ Writer = &gcsWriter{}\n\ntype gcsWriter struct {\n\tgcs *storage.Client\n}\n\n// NewGCSWriter creates a gcs writer.\nfunc NewGCSWriter(gcs *storage.Client) Writer {\n\treturn &gcsWriter{gcs}\n}\n\n// Write writes the backup file to the given gcs path, \"<gcs-bucket-name>/<key>\".\nfunc (gcsw *gcsWriter) Write(ctx context.Context, path string, r io.Reader) (int64, error) {\n\t// TODO: support context.\n\tbucket, key, err := util.ParseBucketAndKey(path)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\tw := gcsw.gcs.Bucket(bucket).Object(key).NewWriter(ctx)\n\tdefer func() {\n\t\terr := w.Close()\n\t\tif err != nil {\n\t\t\tlogrus.Errorf(\"failed to close GCS object writer: %v\", err)\n\t\t}\n\t}()\n\n\tn, err := io.Copy(w, r)\n\tif err != nil {\n\t\terr = fmt.Errorf(\"failed to write GCS object: %v\", err)\n\t}\n\treturn n, err\n}\n\nfunc (gcsw *gcsWriter) List(ctx context.Context, basePath string) ([]string, error) {\n\tbucket, key, err := util.ParseBucketAndKey(basePath)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tobjects := gcsw.gcs.Bucket(bucket).Objects(ctx, &storage.Query{Prefix: key})\n\tif objects == nil {\n\t\treturn nil, fmt.Errorf(\"failed to get objects having %s prefix\", key)\n\t}\n\n\tobjectKeys := []string{}\n\n\tfor {\n\t\tobjAttrs, err := objects.Next()\n\t\tif err == iterator.Done {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tobjectKeys = append(objectKeys, bucket+\"/\"+objAttrs.Name)\n\t}\n\treturn objectKeys, nil\n}\n\nfunc (gcsw *gcsWriter) Delete(ctx context.Context, path string) error {\n\tbucket, key, err := util.ParseBucketAndKey(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn gcsw.gcs.Bucket(bucket).Object(key).Delete(ctx)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/backup/writer/hostPath_writer.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage writer\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"io\"\n\t\"io/ioutil\"\n)\n\nvar _ Writer = &hostPathWriter{}\n\ntype hostPathWriter struct {\n\tbasePath string\n}\n\n// NewHostPathSWriter creates a hostPath writer.\nfunc NewHostPathWriter(path string) Writer {\n\treturn &hostPathWriter{path}\n}\n\n// Write writes the backup file to the given path, \"/data/etcdbackup-xxxx\".\nfunc (hostPathw *hostPathWriter) Write(ctx context.Context, path string, r io.Reader) (int64, error) {\n\tw,err := os.Create(path)\n\tif err != nil{\n\t\terr = fmt.Errorf(\"failed to create backup file of hostPath: %v\", err)\n\t\treturn 0, err\n\t}\n\n\tdefer w.Close()\n\tn, err := io.Copy(w, r)\n\tif err != nil {\n\t\terr = fmt.Errorf(\"failed to write to hostPath: %v\", err)\n\t}\n\treturn n, err\n}\n\nfunc (hostPathw *hostPathWriter) Delete(ctx context.Context, path string) error {\n\terr := os.Remove(path)\n\tif err != nil {\n\t\terr = fmt.Errorf(\"failed to delete deprecated backup file of hostPath: %v\", err)\t\n\t}\n\n\treturn err\n}\n\n// List return the file paths which match the given host path\nfunc (hostPathw *hostPathWriter) List(ctx context.Context, basePath string) ([]string, error) {\n\tfiles, err := ioutil.ReadDir(basePath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get backup files under path:%s\", basePath)\n\t}\n\n\tresults := []string{}\n\tfor _, file := range files {\n\t\tresults = append(results, basePath + file.Name())\n\t}\n\treturn results, nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/backup/writer/oss_writer.go",
    "content": "// Copyright 2019 The etcd-operator 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\npackage writer\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"path\"\n\t\"strconv\"\n\n\t\"github.com/coreos/etcd-operator/pkg/backup/util\"\n\n\t\"github.com/aliyun/aliyun-oss-go-sdk/oss\"\n)\n\ntype ossWriter struct {\n\toss *oss.Client\n}\n\n// NewOSSWriter creates a oss writer.\nfunc NewOSSWriter(oss *oss.Client) Writer {\n\treturn &ossWriter{oss: oss}\n}\n\n// Write writes the backup file to the given oss path, \"<oss-bucket-name>/<key>\".\nfunc (ossw *ossWriter) Write(ctx context.Context, path string, r io.Reader) (int64, error) {\n\t// TODO: support context.\n\tbk, key, err := util.ParseBucketAndKey(path)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\t// If bucket doesn't exist, we create it.\n\texist, err := ossw.oss.IsBucketExist(bk)\n\tif err != nil {\n\t\treturn 0, err\n\t} else if !exist {\n\t\tif err = ossw.oss.CreateBucket(bk); err != nil {\n\t\t\treturn 0, fmt.Errorf(\"failed to create bucket, error: %v\", err)\n\t\t}\n\t}\n\n\tbucket, err := ossw.oss.Bucket(bk)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\tif err = bucket.PutObject(key, r); err != nil {\n\t\treturn 0, err\n\t}\n\n\trc, err := bucket.GetObject(key)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"failed to get oss object: %v\", err)\n\t}\n\n\tvar resp *oss.Response\n\tvar ok bool\n\n\tif resp, ok = rc.(*oss.Response); !ok {\n\t\treturn 0, fmt.Errorf(\"the response type from GetObject(%s) is not *oss.Response\", key)\n\t}\n\n\tdefer resp.Close()\n\n\tclstr := resp.Headers.Get(\"content-length\")\n\tif clstr == \"\" {\n\t\treturn 0, fmt.Errorf(\"content-length not found in headers of response in GetObject\")\n\t}\n\n\tcl, err := strconv.ParseInt(clstr, 10, 64)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"invalid content-length: %s\", clstr)\n\t}\n\n\treturn cl, nil\n}\n\nfunc (ossw *ossWriter) List(ctx context.Context, basePath string) ([]string, error) {\n\t// TODO: support context.\n\tbk, key, err := util.ParseBucketAndKey(basePath)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tbucket, err := ossw.oss.Bucket(bk)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar objKeys []string\n\n\tmarker := oss.Marker(\"\")\n\tprefix := oss.Prefix(key)\n\tfor {\n\t\tresp, err := bucket.ListObjects(oss.MaxKeys(1000), marker, prefix)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to list objects: %v\", err)\n\t\t}\n\n\t\tfor _, obj := range resp.Objects {\n\t\t\tobjKeys = append(objKeys, path.Join(bk, obj.Key))\n\t\t}\n\n\t\tprefix = oss.Prefix(resp.Prefix)\n\t\tmarker = oss.Marker(resp.NextMarker)\n\n\t\tif !resp.IsTruncated {\n\t\t\tbreak\n\t\t}\n\t}\n\n\treturn objKeys, nil\n}\n\nfunc (ossw *ossWriter) Delete(ctx context.Context, path string) error {\n\t// TODO: support context.\n\tbk, key, err := util.ParseBucketAndKey(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tbucket, err := ossw.oss.Bucket(bk)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn bucket.DeleteObject(key)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/backup/writer/s3_writer.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage writer\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/coreos/etcd-operator/pkg/backup/util\"\n\n\t\"github.com/aws/aws-sdk-go/aws\"\n\t\"github.com/aws/aws-sdk-go/service/s3\"\n\t\"github.com/aws/aws-sdk-go/service/s3/s3manager\"\n)\n\ntype s3Writer struct {\n\ts3 *s3.S3\n}\n\n// NewS3Writer creates a s3 writer.\nfunc NewS3Writer(s3 *s3.S3) Writer {\n\treturn &s3Writer{s3}\n}\n\n// Write writes the backup file to the given s3 path, \"<s3-bucket-name>/<key>\".\nfunc (s3w *s3Writer) Write(ctx context.Context, path string, r io.Reader) (int64, error) {\n\tbk, key, err := util.ParseBucketAndKey(path)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\t_, err = s3manager.NewUploaderWithClient(s3w.s3).UploadWithContext(ctx,\n\t\t&s3manager.UploadInput{\n\t\t\tBucket: aws.String(bk),\n\t\t\tKey:    aws.String(key),\n\t\t\tBody:   r,\n\t\t})\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\tresp, err := s3w.s3.GetObject(&s3.GetObjectInput{\n\t\tBucket: aws.String(bk),\n\t\tKey:    aws.String(key),\n\t})\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tif resp.Body != nil {\n\t\tdefer resp.Body.Close()\n\t}\n\tif resp.ContentLength == nil {\n\t\treturn 0, fmt.Errorf(\"failed to compute s3 object size\")\n\t}\n\treturn *resp.ContentLength, nil\n}\n\n// List return the file paths which match the given s3 path\nfunc (s3w *s3Writer) List(ctx context.Context, basePath string) ([]string, error) {\n\tbk, key, err := util.ParseBucketAndKey(basePath)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tobjects, err := s3w.s3.ListObjectsWithContext(ctx,\n\t\t&s3.ListObjectsInput{\n\t\t\tBucket: aws.String(bk),\n\t\t\tPrefix: aws.String(key),\n\t\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tobjectKeys := []string{}\n\tfor _, object := range objects.Contents {\n\t\tobjectKeys = append(objectKeys, bk+\"/\"+*object.Key)\n\t}\n\treturn objectKeys, nil\n}\n\nfunc (s3w *s3Writer) Delete(ctx context.Context, path string) error {\n\tbk, key, err := util.ParseBucketAndKey(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t_, err = s3w.s3.DeleteObjectWithContext(ctx,\n\t\t&s3.DeleteObjectInput{\n\t\t\tBucket: aws.String(bk),\n\t\t\tKey:    aws.String(key),\n\t\t})\n\treturn err\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/backup/writer/writer.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage writer\n\nimport (\n\t\"context\"\n\t\"io\"\n)\n\n// Writer defines the required writer operations.\ntype Writer interface {\n\t// Write writes a backup file to the given path and returns size of written file.\n\tWrite(ctx context.Context, path string, r io.Reader) (int64, error)\n\n\t// List backup files\n\tList(ctx context.Context, basePath string) ([]string, error)\n\n\t// Delete a backup file\n\tDelete(ctx context.Context, path string) error\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/chaos/chaos.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage chaos\n\nimport (\n\t\"context\"\n\t\"math/rand\"\n\n\t\"github.com/sirupsen/logrus\"\n\t\"golang.org/x/time/rate\"\n\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n\t\"k8s.io/client-go/kubernetes\"\n)\n\n// Monkeys knows how to crush pods and nodes.\ntype Monkeys struct {\n\tkubecli kubernetes.Interface\n}\n\nfunc NewMonkeys(kubecli kubernetes.Interface) *Monkeys {\n\treturn &Monkeys{kubecli: kubecli}\n}\n\ntype CrashConfig struct {\n\tNamespace string\n\tSelector  labels.Selector\n\n\tKillRate        rate.Limit\n\tKillProbability float64\n\tKillMax         int\n}\n\n// TODO: respect context in k8s operations.\nfunc (m *Monkeys) CrushPods(ctx context.Context, c *CrashConfig) {\n\tburst := int(c.KillRate)\n\tif burst <= 0 {\n\t\tburst = 1\n\t}\n\tlimiter := rate.NewLimiter(c.KillRate, burst)\n\tls := c.Selector.String()\n\tns := c.Namespace\n\tfor {\n\t\terr := limiter.Wait(ctx)\n\t\tif err != nil { // user cancellation\n\t\t\tlogrus.Infof(\"crushPods is canceled for selector %v by the user: %v\", ls, err)\n\t\t\treturn\n\t\t}\n\n\t\tif p := rand.Float64(); p > c.KillProbability {\n\t\t\tlogrus.Infof(\"skip killing pod: probability: %v, got p: %v\", c.KillProbability, p)\n\t\t\tcontinue\n\t\t}\n\n\t\tpods, err := m.kubecli.CoreV1().Pods(ns).List(metav1.ListOptions{LabelSelector: ls})\n\t\tif err != nil {\n\t\t\tlogrus.Errorf(\"failed to list pods for selector %v: %v\", ls, err)\n\t\t\tcontinue\n\t\t}\n\t\tif len(pods.Items) == 0 {\n\t\t\tlogrus.Infof(\"no pods to kill for selector %v\", ls)\n\t\t\tcontinue\n\t\t}\n\n\t\tmax := len(pods.Items)\n\t\tkmax := rand.Intn(c.KillMax) + 1\n\t\tif kmax < max {\n\t\t\tmax = kmax\n\t\t}\n\n\t\tlogrus.Infof(\"start to kill %d pods for selector %v\", max, ls)\n\n\t\ttokills := make(map[string]struct{})\n\t\tfor len(tokills) < max {\n\t\t\ttokills[pods.Items[rand.Intn(len(pods.Items))].Name] = struct{}{}\n\t\t}\n\n\t\tfor tokill := range tokills {\n\t\t\terr = m.kubecli.CoreV1().Pods(ns).Delete(tokill, metav1.NewDeleteOptions(0))\n\t\t\tif err != nil {\n\t\t\t\tlogrus.Errorf(\"failed to kill pod %v: %v\", tokill, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tlogrus.Infof(\"killed pod %v for selector %v\", tokill, ls)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/client/client.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage client\n\nimport (\n\t\"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned\"\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\n\t\"k8s.io/client-go/rest\"\n)\n\nfunc MustNewInCluster() versioned.Interface {\n\tcfg, err := k8sutil.InClusterConfig()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn MustNew(cfg)\n}\n\nfunc MustNew(cfg *rest.Config) versioned.Interface {\n\tcli, err := versioned.NewForConfig(cfg)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn cli\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/cluster/cluster.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage cluster\n\nimport (\n\t\"crypto/tls\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"math\"\n\t\"reflect\"\n\t\"strings\"\n\t\"time\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned\"\n\t\"github.com/coreos/etcd-operator/pkg/util/etcdutil\"\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\t\"github.com/coreos/etcd-operator/pkg/util/retryutil\"\n\n\t\"github.com/pborman/uuid\"\n\t\"github.com/sirupsen/logrus\"\n\t\"k8s.io/api/core/v1\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n\tcorev1 \"k8s.io/client-go/kubernetes/typed/core/v1\"\n)\n\nvar (\n\treconcileInterval         = 8 * time.Second\n\tpodTerminationGracePeriod = int64(5)\n)\n\ntype clusterEventType string\n\nconst (\n\teventModifyCluster clusterEventType = \"Modify\"\n)\n\ntype clusterEvent struct {\n\ttyp     clusterEventType\n\tcluster *api.EtcdCluster\n}\n\ntype Config struct {\n\tServiceAccount string\n\n\tKubeCli   kubernetes.Interface\n\tEtcdCRCli versioned.Interface\n}\n\ntype Cluster struct {\n\tlogger *logrus.Entry\n\n\tconfig Config\n\n\tcluster *api.EtcdCluster\n\n\t// in memory state of the cluster\n\t// status is the source of truth after Cluster struct is materialized.\n\tstatus api.ClusterStatus\n\n\teventCh chan *clusterEvent\n\tstopCh  chan struct{}\n\n\t// members repsersents the members in the etcd cluster.\n\t// the name of the member is the the name of the pod the member\n\t// process runs in.\n\tmembers etcdutil.MemberSet\n\n\ttlsConfig *tls.Config\n\n\teventsCli corev1.EventInterface\n}\n\nfunc New(config Config, cl *api.EtcdCluster) *Cluster {\n\tlg := logrus.WithField(\"pkg\", \"cluster\").WithField(\"cluster-name\", cl.Name).WithField(\"cluster-namespace\", cl.Namespace)\n\tif len(cl.Name) > k8sutil.MaxNameLength || len(cl.ClusterName) > k8sutil.MaxNameLength {\n\t\treturn nil\n\t}\n\n\tc := &Cluster{\n\t\tlogger:    lg,\n\t\tconfig:    config,\n\t\tcluster:   cl,\n\t\teventCh:   make(chan *clusterEvent, 100),\n\t\tstopCh:    make(chan struct{}),\n\t\tstatus:    *(cl.Status.DeepCopy()),\n\t\teventsCli: config.KubeCli.Core().Events(cl.Namespace),\n\t}\n\n\tgo func() {\n\t\tif err := c.setup(); err != nil {\n\t\t\tc.logger.Errorf(\"cluster failed to setup: %v\", err)\n\t\t\tif c.status.Phase != api.ClusterPhaseFailed {\n\t\t\t\tc.status.SetReason(err.Error())\n\t\t\t\tc.status.SetPhase(api.ClusterPhaseFailed)\n\t\t\t\tif err := c.updateCRStatus(); err != nil {\n\t\t\t\t\tc.logger.Errorf(\"failed to update cluster phase (%v): %v\", api.ClusterPhaseFailed, err)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tc.run()\n\t}()\n\n\treturn c\n}\n\nfunc (c *Cluster) setup() error {\n\tvar shouldCreateCluster bool\n\tswitch c.status.Phase {\n\tcase api.ClusterPhaseNone:\n\t\tshouldCreateCluster = true\n\tcase api.ClusterPhaseCreating:\n\t\treturn errCreatedCluster\n\tcase api.ClusterPhaseRunning:\n\t\tshouldCreateCluster = false\n\n\tdefault:\n\t\treturn fmt.Errorf(\"unexpected cluster phase: %s\", c.status.Phase)\n\t}\n\n\tif c.isSecureClient() {\n\t\td, err := k8sutil.GetTLSDataFromSecret(c.config.KubeCli, c.cluster.Namespace, c.cluster.Spec.TLS.Static.OperatorSecret)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tc.tlsConfig, err = etcdutil.NewTLSConfig(d.CertData, d.KeyData, d.CAData)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif shouldCreateCluster {\n\t\treturn c.create()\n\t}\n\treturn nil\n}\n\nfunc (c *Cluster) create() error {\n\tc.status.SetPhase(api.ClusterPhaseCreating)\n\n\tif err := c.updateCRStatus(); err != nil {\n\t\treturn fmt.Errorf(\"cluster create: failed to update cluster phase (%v): %v\", api.ClusterPhaseCreating, err)\n\t}\n\tc.logClusterCreation()\n\n\treturn c.prepareSeedMember()\n}\n\nfunc (c *Cluster) prepareSeedMember() error {\n\tc.status.SetScalingUpCondition(0, c.cluster.Spec.Size)\n\n\terr := c.bootstrap()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tc.status.Size = 1\n\treturn nil\n}\n\nfunc (c *Cluster) Delete() {\n\tc.logger.Info(\"cluster is deleted by user\")\n\tclose(c.stopCh)\n}\n\nfunc (c *Cluster) send(ev *clusterEvent) {\n\tselect {\n\tcase c.eventCh <- ev:\n\t\tl, ecap := len(c.eventCh), cap(c.eventCh)\n\t\tif l > int(float64(ecap)*0.8) {\n\t\t\tc.logger.Warningf(\"eventCh buffer is almost full [%d/%d]\", l, ecap)\n\t\t}\n\tcase <-c.stopCh:\n\t}\n}\n\nfunc (c *Cluster) run() {\n\tif err := c.setupServices(); err != nil {\n\t\tc.logger.Errorf(\"fail to setup etcd services: %v\", err)\n\t}\n\tc.status.ServiceName = k8sutil.ClientServiceName(c.cluster.Name)\n\tc.status.ClientPort = k8sutil.EtcdClientPort\n\n\tc.status.SetPhase(api.ClusterPhaseRunning)\n\tif err := c.updateCRStatus(); err != nil {\n\t\tc.logger.Warningf(\"update initial CR status failed: %v\", err)\n\t}\n\tc.logger.Infof(\"start running...\")\n\n\tvar rerr error\n\tfor {\n\t\tselect {\n\t\tcase <-c.stopCh:\n\t\t\treturn\n\t\tcase event := <-c.eventCh:\n\t\t\tswitch event.typ {\n\t\t\tcase eventModifyCluster:\n\t\t\t\terr := c.handleUpdateEvent(event)\n\t\t\t\tif err != nil {\n\t\t\t\t\tc.logger.Errorf(\"handle update event failed: %v\", err)\n\t\t\t\t\tc.status.SetReason(err.Error())\n\t\t\t\t\tc.reportFailedStatus()\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\tpanic(\"unknown event type\" + event.typ)\n\t\t\t}\n\n\t\tcase <-time.After(reconcileInterval):\n\t\t\tstart := time.Now()\n\n\t\t\tif c.cluster.Spec.Paused {\n\t\t\t\tc.status.PauseControl()\n\t\t\t\tc.logger.Infof(\"control is paused, skipping reconciliation\")\n\t\t\t\tcontinue\n\t\t\t} else {\n\t\t\t\tc.status.Control()\n\t\t\t}\n\n\t\t\trunning, pending, err := c.pollPods()\n\t\t\tif err != nil {\n\t\t\t\tc.logger.Errorf(\"fail to poll pods: %v\", err)\n\t\t\t\treconcileFailed.WithLabelValues(\"failed to poll pods\").Inc()\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif len(pending) > 0 {\n\t\t\t\t// Pod startup might take long, e.g. pulling image. It would deterministically become running or succeeded/failed later.\n\t\t\t\tc.logger.Infof(\"skip reconciliation: running (%v), pending (%v)\", k8sutil.GetPodNames(running), k8sutil.GetPodNames(pending))\n\t\t\t\treconcileFailed.WithLabelValues(\"not all pods are running\").Inc()\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif len(running) == 0 {\n\t\t\t\t// TODO: how to handle this case?\n\t\t\t\tc.logger.Warningf(\"all etcd pods are dead.\")\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\t// On controller restore, we could have \"members == nil\"\n\t\t\tif rerr != nil || c.members == nil {\n\t\t\t\trerr = c.updateMembers(podsToMemberSet(running, c.isSecureClient()))\n\t\t\t\tif rerr != nil {\n\t\t\t\t\tc.logger.Errorf(\"failed to update members: %v\", rerr)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\trerr = c.reconcile(running)\n\t\t\tif rerr != nil {\n\t\t\t\tc.logger.Errorf(\"failed to reconcile: %v\", rerr)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tc.updateMemberStatus(running)\n\t\t\tif err := c.updateCRStatus(); err != nil {\n\t\t\t\tc.logger.Warningf(\"periodic update CR status failed: %v\", err)\n\t\t\t}\n\n\t\t\treconcileHistogram.WithLabelValues(c.name()).Observe(time.Since(start).Seconds())\n\t\t}\n\n\t\tif rerr != nil {\n\t\t\treconcileFailed.WithLabelValues(rerr.Error()).Inc()\n\t\t}\n\n\t\tif isFatalError(rerr) {\n\t\t\tc.status.SetReason(rerr.Error())\n\t\t\tc.logger.Errorf(\"cluster failed: %v\", rerr)\n\t\t\tc.reportFailedStatus()\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc (c *Cluster) handleUpdateEvent(event *clusterEvent) error {\n\toldSpec := c.cluster.Spec.DeepCopy()\n\tc.cluster = event.cluster\n\n\tif isSpecEqual(event.cluster.Spec, *oldSpec) {\n\t\t// We have some fields that once created could not be mutated.\n\t\tif !reflect.DeepEqual(event.cluster.Spec, *oldSpec) {\n\t\t\tc.logger.Infof(\"ignoring update event: %#v\", event.cluster.Spec)\n\t\t}\n\t\treturn nil\n\t}\n\t// TODO: we can't handle another upgrade while an upgrade is in progress\n\n\tc.logSpecUpdate(*oldSpec, event.cluster.Spec)\n\treturn nil\n}\n\nfunc isSpecEqual(s1, s2 api.ClusterSpec) bool {\n\tif s1.Size != s2.Size || s1.Paused != s2.Paused || s1.Version != s2.Version {\n\t\treturn false\n\t}\n\treturn true\n}\n\nfunc (c *Cluster) startSeedMember() error {\n\tm := &etcdutil.Member{\n\t\tName:         k8sutil.UniqueMemberName(c.cluster.Name),\n\t\tNamespace:    c.cluster.Namespace,\n\t\tSecurePeer:   c.isSecurePeer(),\n\t\tSecureClient: c.isSecureClient(),\n\t}\n\tif c.cluster.Spec.Pod != nil {\n\t\tm.ClusterDomain = c.cluster.Spec.Pod.ClusterDomain\n\t}\n\tms := etcdutil.NewMemberSet(m)\n\tif err := c.createPod(ms, m, \"new\"); err != nil {\n\t\treturn fmt.Errorf(\"failed to create seed member (%s): %v\", m.Name, err)\n\t}\n\tc.members = ms\n\tc.logger.Infof(\"cluster created with seed member (%s)\", m.Name)\n\t_, err := c.eventsCli.Create(k8sutil.NewMemberAddEvent(m.Name, c.cluster))\n\tif err != nil {\n\t\tc.logger.Errorf(\"failed to create new member add event: %v\", err)\n\t}\n\n\treturn nil\n}\n\nfunc (c *Cluster) isSecurePeer() bool {\n\treturn c.cluster.Spec.TLS.IsSecurePeer()\n}\n\nfunc (c *Cluster) isSecureClient() bool {\n\treturn c.cluster.Spec.TLS.IsSecureClient()\n}\n\n// bootstrap creates the seed etcd member for a new cluster.\nfunc (c *Cluster) bootstrap() error {\n\treturn c.startSeedMember()\n}\n\nfunc (c *Cluster) Update(cl *api.EtcdCluster) {\n\tc.send(&clusterEvent{\n\t\ttyp:     eventModifyCluster,\n\t\tcluster: cl,\n\t})\n}\n\nfunc (c *Cluster) setupServices() error {\n\terr := k8sutil.CreateClientService(c.config.KubeCli, c.cluster.Name, c.cluster.Namespace, c.cluster.AsOwner())\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn k8sutil.CreatePeerService(c.config.KubeCli, c.cluster.Name, c.cluster.Namespace, c.cluster.AsOwner())\n}\n\nfunc (c *Cluster) isPodPVEnabled() bool {\n\tif podPolicy := c.cluster.Spec.Pod; podPolicy != nil {\n\t\treturn podPolicy.PersistentVolumeClaimSpec != nil\n\t}\n\treturn false\n}\n\nfunc (c *Cluster) createPod(members etcdutil.MemberSet, m *etcdutil.Member, state string) error {\n\tpod := k8sutil.NewEtcdPod(m, members.PeerURLPairs(), c.cluster.Name, state, uuid.New(), c.cluster.Spec, c.cluster.AsOwner())\n\tif c.isPodPVEnabled() {\n\t\tpvc := k8sutil.NewEtcdPodPVC(m, *c.cluster.Spec.Pod.PersistentVolumeClaimSpec, c.cluster.Name, c.cluster.Namespace, c.cluster.AsOwner())\n\t\t_, err := c.config.KubeCli.CoreV1().PersistentVolumeClaims(c.cluster.Namespace).Create(pvc)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to create PVC for member (%s): %v\", m.Name, err)\n\t\t}\n\t\tk8sutil.AddEtcdVolumeToPod(pod, pvc)\n\t} else {\n\t\tk8sutil.AddEtcdVolumeToPod(pod, nil)\n\t}\n\t_, err := c.config.KubeCli.CoreV1().Pods(c.cluster.Namespace).Create(pod)\n\treturn err\n}\n\nfunc (c *Cluster) removePod(name string) error {\n\tns := c.cluster.Namespace\n\topts := metav1.NewDeleteOptions(podTerminationGracePeriod)\n\terr := c.config.KubeCli.Core().Pods(ns).Delete(name, opts)\n\tif err != nil {\n\t\tif !k8sutil.IsKubernetesResourceNotFoundError(err) {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (c *Cluster) pollPods() (running, pending []*v1.Pod, err error) {\n\tpodList, err := c.config.KubeCli.Core().Pods(c.cluster.Namespace).List(k8sutil.ClusterListOpt(c.cluster.Name))\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed to list running pods: %v\", err)\n\t}\n\n\tfor i := range podList.Items {\n\t\tpod := &podList.Items[i]\n\t\t// Avoid polling deleted pods. k8s issue where deleted pods would sometimes show the status Pending\n\t\t// See https://github.com/coreos/etcd-operator/issues/1693\n\t\tif pod.DeletionTimestamp != nil {\n\t\t\tcontinue\n\t\t}\n\t\tif len(pod.OwnerReferences) < 1 {\n\t\t\tc.logger.Warningf(\"pollPods: ignore pod %v: no owner\", pod.Name)\n\t\t\tcontinue\n\t\t}\n\t\tif pod.OwnerReferences[0].UID != c.cluster.UID {\n\t\t\tc.logger.Warningf(\"pollPods: ignore pod %v: owner (%v) is not %v\",\n\t\t\t\tpod.Name, pod.OwnerReferences[0].UID, c.cluster.UID)\n\t\t\tcontinue\n\t\t}\n\t\tswitch pod.Status.Phase {\n\t\tcase v1.PodRunning:\n\t\t\trunning = append(running, pod)\n\t\tcase v1.PodPending:\n\t\t\tpending = append(pending, pod)\n\t\t}\n\t}\n\n\treturn running, pending, nil\n}\n\nfunc (c *Cluster) updateMemberStatus(running []*v1.Pod) {\n\tvar unready []string\n\tvar ready []string\n\tfor _, pod := range running {\n\t\tif k8sutil.IsPodReady(pod) {\n\t\t\tready = append(ready, pod.Name)\n\t\t\tcontinue\n\t\t}\n\t\tunready = append(unready, pod.Name)\n\t}\n\n\tc.status.Members.Ready = ready\n\tc.status.Members.Unready = unready\n}\n\nfunc (c *Cluster) updateCRStatus() error {\n\tif reflect.DeepEqual(c.cluster.Status, c.status) {\n\t\treturn nil\n\t}\n\n\tnewCluster := c.cluster\n\tnewCluster.Status = c.status\n\tnewCluster, err := c.config.EtcdCRCli.EtcdV1beta2().EtcdClusters(c.cluster.Namespace).Update(c.cluster)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to update CR status: %v\", err)\n\t}\n\n\tc.cluster = newCluster\n\n\treturn nil\n}\n\nfunc (c *Cluster) reportFailedStatus() {\n\tc.logger.Info(\"cluster failed. Reporting failed reason...\")\n\n\tretryInterval := 5 * time.Second\n\tf := func() (bool, error) {\n\t\tc.status.SetPhase(api.ClusterPhaseFailed)\n\t\terr := c.updateCRStatus()\n\t\tif err == nil || k8sutil.IsKubernetesResourceNotFoundError(err) {\n\t\t\treturn true, nil\n\t\t}\n\n\t\tif !apierrors.IsConflict(err) {\n\t\t\tc.logger.Warningf(\"retry report status in %v: fail to update: %v\", retryInterval, err)\n\t\t\treturn false, nil\n\t\t}\n\n\t\tcl, err := c.config.EtcdCRCli.EtcdV1beta2().EtcdClusters(c.cluster.Namespace).\n\t\t\tGet(c.cluster.Name, metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\t// Update (PUT) will return conflict even if object is deleted since we have UID set in object.\n\t\t\t// Because it will check UID first and return something like:\n\t\t\t// \"Precondition failed: UID in precondition: 0xc42712c0f0, UID in object meta: \".\n\t\t\tif k8sutil.IsKubernetesResourceNotFoundError(err) {\n\t\t\t\treturn true, nil\n\t\t\t}\n\t\t\tc.logger.Warningf(\"retry report status in %v: fail to get latest version: %v\", retryInterval, err)\n\t\t\treturn false, nil\n\t\t}\n\t\tc.cluster = cl\n\t\treturn false, nil\n\t}\n\n\tretryutil.Retry(retryInterval, math.MaxInt64, f)\n}\n\nfunc (c *Cluster) name() string {\n\treturn c.cluster.GetName()\n}\n\nfunc (c *Cluster) logClusterCreation() {\n\tspecBytes, err := json.MarshalIndent(c.cluster.Spec, \"\", \"    \")\n\tif err != nil {\n\t\tc.logger.Errorf(\"failed to marshal cluster spec: %v\", err)\n\t}\n\n\tc.logger.Info(\"creating cluster with Spec:\")\n\tfor _, m := range strings.Split(string(specBytes), \"\\n\") {\n\t\tc.logger.Info(m)\n\t}\n}\n\nfunc (c *Cluster) logSpecUpdate(oldSpec, newSpec api.ClusterSpec) {\n\toldSpecBytes, err := json.MarshalIndent(oldSpec, \"\", \"    \")\n\tif err != nil {\n\t\tc.logger.Errorf(\"failed to marshal cluster spec: %v\", err)\n\t}\n\tnewSpecBytes, err := json.MarshalIndent(newSpec, \"\", \"    \")\n\tif err != nil {\n\t\tc.logger.Errorf(\"failed to marshal cluster spec: %v\", err)\n\t}\n\n\tc.logger.Infof(\"spec update: Old Spec:\")\n\tfor _, m := range strings.Split(string(oldSpecBytes), \"\\n\") {\n\t\tc.logger.Info(m)\n\t}\n\n\tc.logger.Infof(\"New Spec:\")\n\tfor _, m := range strings.Split(string(newSpecBytes), \"\\n\") {\n\t\tc.logger.Info(m)\n\t}\n\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/cluster/cluster_test.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage cluster\n\nimport (\n\t\"testing\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\n// When EtcdCluster update event happens, local object ref should be updated.\nfunc TestUpdateEventUpdateLocalClusterObj(t *testing.T) {\n\toldVersion := \"123\"\n\tnewVersion := \"321\"\n\n\toldObj := &api.EtcdCluster{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tAPIVersion: api.SchemeGroupVersion.String(),\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tResourceVersion: oldVersion,\n\t\t\tName:            \"test\",\n\t\t\tNamespace:       metav1.NamespaceDefault,\n\t\t},\n\t}\n\tnewObj := oldObj.DeepCopy()\n\tnewObj.ResourceVersion = newVersion\n\n\tc := &Cluster{\n\t\tcluster: oldObj,\n\t}\n\te := &clusterEvent{\n\t\ttyp:     eventModifyCluster,\n\t\tcluster: newObj,\n\t}\n\n\terr := c.handleUpdateEvent(e)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif c.cluster.ResourceVersion != newVersion {\n\t\tt.Errorf(\"expect version=%s, get=%s\", newVersion, c.cluster.ResourceVersion)\n\t}\n}\n\nfunc TestNewLongClusterName(t *testing.T) {\n\tclus := &api.EtcdCluster{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tAPIVersion: api.SchemeGroupVersion.String(),\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      \"example-etcd-cluster123456789123456789123456789123456789123456\",\n\t\t\tNamespace: metav1.NamespaceDefault,\n\t\t},\n\t}\n\tclus.SetClusterName(\"example-etcd-cluster123456789123456789123456789123456789123456\")\n\tif c := New(Config{}, clus); c != nil {\n\t\tt.Errorf(\"expect c to be nil\")\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/cluster/error.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage cluster\n\nimport (\n\t\"github.com/pkg/errors\"\n)\n\nvar (\n\terrCreatedCluster = errors.New(\"cluster failed to be created\")\n)\n\ntype fatalError struct {\n\treason string\n}\n\nfunc (fe *fatalError) Error() string {\n\treturn fe.reason\n}\n\nfunc newFatalError(reason string) *fatalError {\n\treturn &fatalError{reason}\n}\n\nfunc isFatalError(err error) bool {\n\tswitch errors.Cause(err).(type) {\n\tcase *fatalError:\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/cluster/error_test.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage cluster\n\nimport (\n\t\"testing\"\n\n\t\"github.com/pkg/errors\"\n)\n\nfunc TestWrapFatalError(t *testing.T) {\n\ttests := []struct {\n\t\terr     error\n\t\tisFatal bool\n\t}{{\n\t\terr:     &fatalError{},\n\t\tisFatal: true,\n\t}, {\n\t\terr:     newFatalError(\"some reason\"),\n\t\tisFatal: true,\n\t}, {\n\n\t\terr:     errors.Wrap(newFatalError(\"cause\"), \"wrap\"),\n\t\tisFatal: true,\n\t}, {\n\t\terr:     errors.New(\"not fatal\"),\n\t\tisFatal: false,\n\t}}\n\n\tfor i, tt := range tests {\n\t\tf := isFatalError(tt.err)\n\t\tif f != tt.isFatal {\n\t\t\tt.Errorf(\"#%d: isFatal want=%v, get=%v\", i, tt.isFatal, f)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/cluster/member.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage cluster\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/coreos/etcd-operator/pkg/util/etcdutil\"\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\t\"github.com/coreos/etcd/etcdserver/etcdserverpb\"\n\t\"github.com/pkg/errors\"\n\n\t\"k8s.io/api/core/v1\"\n)\n\nfunc (c *Cluster) updateMembers(known etcdutil.MemberSet) error {\n\tresp, err := etcdutil.ListMembers(known.ClientURLs(), c.tlsConfig)\n\tif err != nil {\n\t\treturn err\n\t}\n\tmembers := etcdutil.MemberSet{}\n\tfor _, m := range resp.Members {\n\t\tname, err := getMemberName(m, c.cluster.GetName())\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"get member name failed\")\n\t\t}\n\n\t\tmembers[name] = &etcdutil.Member{\n\t\t\tName:         name,\n\t\t\tNamespace:    c.cluster.Namespace,\n\t\t\tID:           m.ID,\n\t\t\tSecurePeer:   c.isSecurePeer(),\n\t\t\tSecureClient: c.isSecureClient(),\n\t\t}\n\t}\n\tc.members = members\n\treturn nil\n}\n\nfunc (c *Cluster) newMember() *etcdutil.Member {\n\tname := k8sutil.UniqueMemberName(c.cluster.Name)\n\tm := &etcdutil.Member{\n\t\tName:         name,\n\t\tNamespace:    c.cluster.Namespace,\n\t\tSecurePeer:   c.isSecurePeer(),\n\t\tSecureClient: c.isSecureClient(),\n\t}\n\n\tif c.cluster.Spec.Pod != nil {\n\t\tm.ClusterDomain = c.cluster.Spec.Pod.ClusterDomain\n\t}\n\treturn m\n}\n\nfunc podsToMemberSet(pods []*v1.Pod, sc bool) etcdutil.MemberSet {\n\tmembers := etcdutil.MemberSet{}\n\tfor _, pod := range pods {\n\t\tm := &etcdutil.Member{Name: pod.Name, Namespace: pod.Namespace, SecureClient: sc}\n\t\tmembers.Add(m)\n\t}\n\treturn members\n}\n\nfunc getMemberName(m *etcdserverpb.Member, clusterName string) (string, error) {\n\tname, err := etcdutil.MemberNameFromPeerURL(m.PeerURLs[0])\n\tif err != nil {\n\t\treturn \"\", newFatalError(fmt.Sprintf(\"invalid member peerURL (%s): %v\", m.PeerURLs[0], err))\n\t}\n\treturn name, nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/cluster/metrics.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage cluster\n\nimport (\n\t\"github.com/prometheus/client_golang/prometheus\"\n)\n\nvar reconcileHistogram = prometheus.NewHistogramVec(prometheus.HistogramOpts{\n\tNamespace: \"etcd_operator\",\n\tSubsystem: \"cluster\",\n\tName:      \"reconcile_duration\",\n\tHelp:      \"Reconcile duration histogram in second\",\n\tBuckets:   prometheus.ExponentialBuckets(0.1, 2, 10),\n},\n\t[]string{\"ClusterName\"},\n)\n\nvar reconcileFailed = prometheus.NewCounterVec(prometheus.CounterOpts{\n\tNamespace: \"etcd_operator\",\n\tSubsystem: \"cluster\",\n\tName:      \"reconcile_failed\",\n\tHelp:      \"Total number of failed reconcilations\",\n},\n\t[]string{\"Reason\"},\n)\n\nfunc init() {\n\tprometheus.MustRegister(reconcileHistogram)\n\tprometheus.MustRegister(reconcileFailed)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/cluster/reconcile.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage cluster\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/util/constants\"\n\t\"github.com/coreos/etcd-operator/pkg/util/etcdutil\"\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\n\t\"github.com/coreos/etcd/clientv3\"\n\t\"github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes\"\n\t\"k8s.io/api/core/v1\"\n)\n\n// ErrLostQuorum indicates that the etcd cluster lost its quorum.\nvar ErrLostQuorum = errors.New(\"lost quorum\")\n\n// reconcile reconciles cluster current state to desired state specified by spec.\n// - it tries to reconcile the cluster to desired size.\n// - if the cluster needs for upgrade, it tries to upgrade old member one by one.\nfunc (c *Cluster) reconcile(pods []*v1.Pod) error {\n\tc.logger.Infoln(\"Start reconciling\")\n\tdefer c.logger.Infoln(\"Finish reconciling\")\n\n\tdefer func() {\n\t\tc.status.Size = c.members.Size()\n\t}()\n\n\tsp := c.cluster.Spec\n\trunning := podsToMemberSet(pods, c.isSecureClient())\n\tif !running.IsEqual(c.members) || c.members.Size() != sp.Size {\n\t\treturn c.reconcileMembers(running)\n\t}\n\tc.status.ClearCondition(api.ClusterConditionScaling)\n\n\tif needUpgrade(pods, sp) {\n\t\tc.status.UpgradeVersionTo(sp.Version)\n\n\t\tm := pickOneOldMember(pods, sp.Version)\n\t\treturn c.upgradeOneMember(m.Name)\n\t}\n\tc.status.ClearCondition(api.ClusterConditionUpgrading)\n\n\tc.status.SetVersion(sp.Version)\n\tc.status.SetReadyCondition()\n\n\treturn nil\n}\n\n// reconcileMembers reconciles\n// - running pods on k8s and cluster membership\n// - cluster membership and expected size of etcd cluster\n// Steps:\n// 1. Remove all pods from running set that does not belong to member set.\n// 2. L consist of remaining pods of runnings\n// 3. If L = members, the current state matches the membership state. END.\n// 4. If len(L) < len(members)/2 + 1, return quorum lost error.\n// 5. Add one missing member. END.\nfunc (c *Cluster) reconcileMembers(running etcdutil.MemberSet) error {\n\tc.logger.Infof(\"running members: %s\", running)\n\tc.logger.Infof(\"cluster membership: %s\", c.members)\n\n\tunknownMembers := running.Diff(c.members)\n\tif unknownMembers.Size() > 0 {\n\t\tc.logger.Infof(\"removing unexpected pods: %v\", unknownMembers)\n\t\tfor _, m := range unknownMembers {\n\t\t\tif err := c.removePod(m.Name); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\tL := running.Diff(unknownMembers)\n\n\tif L.Size() == c.members.Size() {\n\t\treturn c.resize()\n\t}\n\n\tif L.Size() < c.members.Size()/2+1 {\n\t\treturn ErrLostQuorum\n\t}\n\n\tc.logger.Infof(\"removing one dead member\")\n\t// remove dead members that doesn't have any running pods before doing resizing.\n\treturn c.removeDeadMember(c.members.Diff(L).PickOne())\n}\n\nfunc (c *Cluster) resize() error {\n\tif c.members.Size() == c.cluster.Spec.Size {\n\t\treturn nil\n\t}\n\n\tif c.members.Size() < c.cluster.Spec.Size {\n\t\treturn c.addOneMember()\n\t}\n\n\treturn c.removeOneMember()\n}\n\nfunc (c *Cluster) addOneMember() error {\n\tc.status.SetScalingUpCondition(c.members.Size(), c.cluster.Spec.Size)\n\n\tcfg := clientv3.Config{\n\t\tEndpoints:   c.members.ClientURLs(),\n\t\tDialTimeout: constants.DefaultDialTimeout,\n\t\tTLS:         c.tlsConfig,\n\t}\n\tetcdcli, err := clientv3.New(cfg)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"add one member failed: creating etcd client failed %v\", err)\n\t}\n\tdefer etcdcli.Close()\n\n\tnewMember := c.newMember()\n\tctx, cancel := context.WithTimeout(context.Background(), constants.DefaultRequestTimeout)\n\tresp, err := etcdcli.MemberAdd(ctx, []string{newMember.PeerURL()})\n\tcancel()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"fail to add new member (%s): %v\", newMember.Name, err)\n\t}\n\tnewMember.ID = resp.Member.ID\n\tc.members.Add(newMember)\n\n\tif err := c.createPod(c.members, newMember, \"existing\"); err != nil {\n\t\treturn fmt.Errorf(\"fail to create member's pod (%s): %v\", newMember.Name, err)\n\t}\n\tc.logger.Infof(\"added member (%s)\", newMember.Name)\n\t_, err = c.eventsCli.Create(k8sutil.NewMemberAddEvent(newMember.Name, c.cluster))\n\tif err != nil {\n\t\tc.logger.Errorf(\"failed to create new member add event: %v\", err)\n\t}\n\treturn nil\n}\n\nfunc (c *Cluster) removeOneMember() error {\n\tc.status.SetScalingDownCondition(c.members.Size(), c.cluster.Spec.Size)\n\n\treturn c.removeMember(c.members.PickOne())\n}\n\nfunc (c *Cluster) removeDeadMember(toRemove *etcdutil.Member) error {\n\tc.logger.Infof(\"removing dead member %q\", toRemove.Name)\n\t_, err := c.eventsCli.Create(k8sutil.ReplacingDeadMemberEvent(toRemove.Name, c.cluster))\n\tif err != nil {\n\t\tc.logger.Errorf(\"failed to create replacing dead member event: %v\", err)\n\t}\n\n\treturn c.removeMember(toRemove)\n}\n\nfunc (c *Cluster) removeMember(toRemove *etcdutil.Member) (err error) {\n\tdefer func() {\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"remove member (%s) failed: %v\", toRemove.Name, err)\n\t\t}\n\t}()\n\n\terr = etcdutil.RemoveMember(c.members.ClientURLs(), c.tlsConfig, toRemove.ID)\n\tif err != nil {\n\t\tswitch err {\n\t\tcase rpctypes.ErrMemberNotFound:\n\t\t\tc.logger.Infof(\"etcd member (%v) has been removed\", toRemove.Name)\n\t\tdefault:\n\t\t\treturn err\n\t\t}\n\t}\n\tc.members.Remove(toRemove.Name)\n\t_, err = c.eventsCli.Create(k8sutil.MemberRemoveEvent(toRemove.Name, c.cluster))\n\tif err != nil {\n\t\tc.logger.Errorf(\"failed to create remove member event: %v\", err)\n\t}\n\tif err := c.removePod(toRemove.Name); err != nil {\n\t\treturn err\n\t}\n\tif c.isPodPVEnabled() {\n\t\terr = c.removePVC(k8sutil.PVCNameFromMember(toRemove.Name))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tc.logger.Infof(\"removed member (%v) with ID (%d)\", toRemove.Name, toRemove.ID)\n\treturn nil\n}\n\nfunc (c *Cluster) removePVC(pvcName string) error {\n\terr := c.config.KubeCli.Core().PersistentVolumeClaims(c.cluster.Namespace).Delete(pvcName, nil)\n\tif err != nil && !k8sutil.IsKubernetesResourceNotFoundError(err) {\n\t\treturn fmt.Errorf(\"remove pvc (%s) failed: %v\", pvcName, err)\n\t}\n\treturn nil\n}\n\nfunc needUpgrade(pods []*v1.Pod, cs api.ClusterSpec) bool {\n\treturn len(pods) == cs.Size && pickOneOldMember(pods, cs.Version) != nil\n}\n\nfunc pickOneOldMember(pods []*v1.Pod, newVersion string) *etcdutil.Member {\n\tfor _, pod := range pods {\n\t\tif k8sutil.GetEtcdVersion(pod) == newVersion {\n\t\t\tcontinue\n\t\t}\n\t\treturn &etcdutil.Member{Name: pod.Name, Namespace: pod.Namespace}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/cluster/upgrade.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage cluster\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\n\t\"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/types\"\n)\n\nfunc (c *Cluster) upgradeOneMember(memberName string) error {\n\tc.status.SetUpgradingCondition(c.cluster.Spec.Version)\n\n\tns := c.cluster.Namespace\n\n\tpod, err := c.config.KubeCli.CoreV1().Pods(ns).Get(memberName, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"fail to get pod (%s): %v\", memberName, err)\n\t}\n\toldpod := pod.DeepCopy()\n\n\tc.logger.Infof(\"upgrading the etcd member %v from %s to %s\", memberName, k8sutil.GetEtcdVersion(pod), c.cluster.Spec.Version)\n\tpod.Spec.Containers[0].Image = k8sutil.ImageName(c.cluster.Spec.Repository, c.cluster.Spec.Version)\n\tk8sutil.SetEtcdVersion(pod, c.cluster.Spec.Version)\n\n\tpatchdata, err := k8sutil.CreatePatch(oldpod, pod, v1.Pod{})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error creating patch: %v\", err)\n\t}\n\n\t_, err = c.config.KubeCli.CoreV1().Pods(ns).Patch(pod.GetName(), types.StrategicMergePatchType, patchdata)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"fail to update the etcd member (%s): %v\", memberName, err)\n\t}\n\tc.logger.Infof(\"finished upgrading the etcd member %v\", memberName)\n\t_, err = c.eventsCli.Create(k8sutil.MemberUpgradedEvent(memberName, k8sutil.GetEtcdVersion(oldpod), c.cluster.Spec.Version, c.cluster))\n\tif err != nil {\n\t\tc.logger.Errorf(\"failed to create member upgraded event: %v\", err)\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/controller/backup-operator/abs_backup.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage controller\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"fmt\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/backup\"\n\t\"github.com/coreos/etcd-operator/pkg/backup/writer\"\n\t\"github.com/coreos/etcd-operator/pkg/util/azureutil/absfactory\"\n\n\t\"k8s.io/client-go/kubernetes\"\n)\n\n// handleABS saves etcd cluster's backup to specificed ABS path.\nfunc handleABS(ctx context.Context, kubecli kubernetes.Interface, s *api.ABSBackupSource, endpoints []string, clientTLSSecret, basicAuthSecret,\n\tnamespace string, insecureSkipVerify, isPeriodic bool, maxBackup int) (*api.BackupStatus, error) {\n\t// TODO: controls NewClientFromSecret with ctx. This depends on upstream kubernetes to support API calls with ctx.\n\tcli, err := absfactory.NewClientFromSecret(kubecli, namespace, s.ABSSecret)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar tlsConfig *tls.Config\n\tif tlsConfig, err = generateTLSConfigWithVerify(kubecli, clientTLSSecret, namespace, insecureSkipVerify); err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar username, password string\n\tif username, password, err = generateUsernamePassword(kubecli, basicAuthSecret, namespace); err != nil {\n\t\treturn nil, err\n\t}\n\n\tbm := backup.NewBackupManagerFromWriter(kubecli, writer.NewABSWriter(cli.ABS), tlsConfig, endpoints, namespace, username, password)\n\n\trev, etcdVersion, now, err := bm.SaveSnap(ctx, s.Path, isPeriodic)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to save snapshot (%v)\", err)\n\t}\n\tif maxBackup > 0 {\n\t\terr := bm.EnsureMaxBackup(ctx, s.Path, maxBackup)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"succeeded in saving snapshot but failed to delete old snapshot (%v)\", err)\n\t\t}\n\t}\n\treturn &api.BackupStatus{EtcdVersion: etcdVersion, EtcdRevision: rev, LastSuccessDate: *now}, nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/controller/backup-operator/controller.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage controller\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\n\t\"k8s.io/apimachinery/pkg/fields\"\n\t\"k8s.io/apimachinery/pkg/util/wait\"\n\t\"k8s.io/client-go/tools/cache\"\n\t\"k8s.io/client-go/util/workqueue\"\n)\n\nfunc (b *Backup) run(ctx context.Context) {\n\tsource := cache.NewListWatchFromClient(\n\t\tb.backupCRCli.EtcdV1beta2().RESTClient(),\n\t\tapi.EtcdBackupResourcePlural,\n\t\tb.watchNamespace,\n\t\tfields.Everything(),\n\t)\n\n\tb.queue = workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), \"etcd-backup-operator\")\n\tb.indexer, b.informer = cache.NewIndexerInformer(source, &api.EtcdBackup{}, 0, cache.ResourceEventHandlerFuncs{\n\t\tAddFunc:    b.onAdd,\n\t\tUpdateFunc: b.onUpdate,\n\t\tDeleteFunc: b.onDelete,\n\t}, cache.Indexers{})\n\n\tdefer b.queue.ShutDown()\n\n\tb.logger.Info(\"starting backup controller\")\n\tgo b.informer.Run(ctx.Done())\n\n\tif !cache.WaitForCacheSync(ctx.Done(), b.informer.HasSynced) {\n\t\treturn\n\t}\n\n\tconst numWorkers = 1\n\tfor i := 0; i < numWorkers; i++ {\n\t\tgo wait.Until(b.runWorker, time.Second, ctx.Done())\n\t}\n\n\t<-ctx.Done()\n\tb.logger.Info(\"stopping backup controller\")\n}\n\nfunc (b *Backup) onAdd(obj interface{}) {\n\tkey, err := cache.MetaNamespaceKeyFunc(obj)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tb.queue.Add(key)\n}\n\nfunc (b *Backup) onUpdate(oldObj, newObj interface{}) {\n\tkey, err := cache.MetaNamespaceKeyFunc(newObj)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tb.queue.Add(key)\n}\n\nfunc (b *Backup) onDelete(obj interface{}) {\n\tkey, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tb.queue.Add(key)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/controller/backup-operator/cos_backup.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage controller\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"fmt\"\n\t\"os\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/backup\"\n\t\"github.com/coreos/etcd-operator/pkg/backup/writer\"\n\t\"github.com/coreos/etcd-operator/pkg/util/tencentcloudutil/cosfactory\"\n\n\t\"k8s.io/client-go/kubernetes\"\n)\n\n// handleCOS saves etcd cluster's backup to specificed COS path.\nfunc handleCOS(ctx context.Context, kubecli kubernetes.Interface, s *api.COSBackupSource, endpoints []string, clientTLSSecret, basicAuthSecret, namespace string, insecureSkipVerify bool, isPeriodic bool, maxBackup int) (bs *api.BackupStatus, err error) {\n\tvar cli *cosfactory.COSClient\n\tif len(s.COSSecret) > 0 {\n\t\tcli, err = cosfactory.NewClientFromSecret(kubecli, namespace, s.COSSecret)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t} else {\n\t\trole := os.Getenv(\"COS_CAM_ROLE_NAME\")\n\t\tif len(role) == 0 {\n\t\t\treturn nil, fmt.Errorf(\"COS secret and COS_CAM_ROLE_NAME env must have one set\")\n\t\t}\n\t\tcli, err = cosfactory.NewClientFromMetadata(role)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\tvar tlsConfig *tls.Config\n\tif tlsConfig, err = generateTLSConfigWithVerify(kubecli, clientTLSSecret, namespace, insecureSkipVerify); err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar username, password string\n\tif username, password, err = generateUsernamePassword(kubecli, basicAuthSecret, namespace); err != nil {\n\t\treturn nil, err\n\t}\n\n\tbm := backup.NewBackupManagerFromWriter(kubecli, writer.NewCOSWriter(cli.COS), tlsConfig, endpoints, namespace, username, password)\n\n\trev, etcdVersion, now, err := bm.SaveSnap(ctx, s.Path, isPeriodic)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to save snapshot (%v)\", err)\n\t}\n\tif maxBackup > 0 {\n\t\terr := bm.EnsureMaxBackup(ctx, s.Path, maxBackup)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"succeeded in saving snapshot but failed to delete old snapshot (%v)\", err)\n\t\t}\n\t}\n\treturn &api.BackupStatus{EtcdVersion: etcdVersion, EtcdRevision: rev, LastSuccessDate: *now}, nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/controller/backup-operator/gcs_backup.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage controller\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"fmt\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/backup\"\n\t\"github.com/coreos/etcd-operator/pkg/backup/writer\"\n\t\"github.com/coreos/etcd-operator/pkg/util/gcputil/gcsfactory\"\n\n\t\"k8s.io/client-go/kubernetes\"\n)\n\n// handleGCS saves etcd cluster's backup to specificed GCS path.\nfunc handleGCS(ctx context.Context, kubecli kubernetes.Interface, s *api.GCSBackupSource, endpoints []string, clientTLSSecret, basicAuthSecret,\n\tnamespace string, insecureSkipVerify, isPeriodic bool, maxBackup int) (*api.BackupStatus, error) {\n\t// TODO: controls NewClientFromSecret with ctx. This depends on upstream kubernetes to support API calls with ctx.\n\tcli, err := gcsfactory.NewClientFromSecret(ctx, kubecli, namespace, s.GCPSecret)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer cli.GCS.Close()\n\n\tvar tlsConfig *tls.Config\n\tif tlsConfig, err = generateTLSConfigWithVerify(kubecli, clientTLSSecret, namespace, insecureSkipVerify); err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar username, password string\n\tif username, password, err = generateUsernamePassword(kubecli, basicAuthSecret, namespace); err != nil {\n\t\treturn nil, err\n\t}\n\n\tbm := backup.NewBackupManagerFromWriter(kubecli, writer.NewGCSWriter(cli.GCS), tlsConfig, endpoints, namespace, username, password)\n\n\trev, etcdVersion, now, err := bm.SaveSnap(ctx, s.Path, isPeriodic)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to save snapshot (%v)\", err)\n\t}\n\tif maxBackup > 0 {\n\t\terr := bm.EnsureMaxBackup(ctx, s.Path, maxBackup)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"succeeded in saving snapshot but failed to delete old snapshot (%v)\", err)\n\t\t}\n\t}\n\treturn &api.BackupStatus{EtcdVersion: etcdVersion, EtcdRevision: rev, LastSuccessDate: *now}, nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/controller/backup-operator/hostPath_backup.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage controller\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"fmt\"\n\t\"os\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/backup\"\n\t\"github.com/coreos/etcd-operator/pkg/backup/writer\"\n\n\t\"k8s.io/client-go/kubernetes\"\n)\nconst etcdBackFilePrefix = \"etcdbackup\"\n// handleHostPath saves etcd cluster's backup to specificed host path.\nfunc handleHostPath(ctx context.Context, kubecli kubernetes.Interface, s *api.HostPathBackupSource,endpoints []string, clientTLSSecret, basicAuthSecret, namespace string, insecureSkipVerify bool, isPeriodic bool, maxBackup int) (bs *api.BackupStatus, err error) {\n\thostPath := os.Getenv(\"HOST_PATH_NAME\")\n\tif len(hostPath) == 0 {\n\t\treturn nil, fmt.Errorf(\"HOST_PATH_NAME env must be set\")\n\t}\n\n\tvar tlsConfig *tls.Config\n\tif tlsConfig, err = generateTLSConfigWithVerify(kubecli, clientTLSSecret, namespace, insecureSkipVerify); err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar username, password string\n\tif username, password, err = generateUsernamePassword(kubecli, basicAuthSecret, namespace); err != nil {\n\t\treturn nil, err\n\t}\n\n\tbm := backup.NewBackupManagerFromWriter(kubecli, writer.NewHostPathWriter(hostPath), tlsConfig, endpoints, namespace, username, password)\n\n\trev, etcdVersion, now, err := bm.SaveSnap(ctx, hostPath + etcdBackFilePrefix, isPeriodic)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to save snapshot (%v)\", err)\n\t}\n\tif maxBackup > 0 {\n\t\terr := bm.EnsureMaxBackup(ctx,hostPath, maxBackup)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"succeeded in saving snapshot but failed to delete old snapshot (%v)\", err)\n\t\t}\n\t}\n\treturn &api.BackupStatus{EtcdVersion: etcdVersion, EtcdRevision: rev, LastSuccessDate: *now}, nil\n}"
  },
  {
    "path": "third_party/etcd-operator/pkg/controller/backup-operator/operator.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage controller\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"sync\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/client\"\n\t\"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned\"\n\t\"github.com/coreos/etcd-operator/pkg/util/constants\"\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\n\t\"github.com/sirupsen/logrus\"\n\tapiextensionsclient \"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/client-go/tools/cache\"\n\t\"k8s.io/client-go/util/workqueue\"\n)\n\ntype Backup struct {\n\tlogger *logrus.Entry\n\n\toperatorNamespace string\n\twatchNamespace    string\n\t// k8s workqueue pattern\n\tindexer  cache.Indexer\n\tinformer cache.Controller\n\tqueue    workqueue.RateLimitingInterface\n\n\tkubecli     kubernetes.Interface\n\tbackupCRCli versioned.Interface\n\tkubeExtCli  apiextensionsclient.Interface\n\n\tbackupRunnerStore sync.Map\n\n\tcreateCRD bool\n}\n\ntype BackupRunner struct {\n\tspec       api.BackupSpec\n\tcancelFunc context.CancelFunc\n}\n\n// New creates a backup operator.\nfunc New(createCRD bool) *Backup {\n\treturn &Backup{\n\t\tlogger:            logrus.WithField(\"pkg\", \"controller\"),\n\t\toperatorNamespace: os.Getenv(constants.EnvOperatorPodNamespace),\n\t\twatchNamespace:    os.Getenv(constants.EnvOperatorWatchNamespace),\n\t\tkubecli:           k8sutil.MustNewKubeClient(),\n\t\tbackupCRCli:       client.MustNewInCluster(),\n\t\tkubeExtCli:        k8sutil.MustNewKubeExtClient(),\n\t\tcreateCRD:         createCRD,\n\t}\n}\n\n// Start starts the Backup operator.\nfunc (b *Backup) Start(ctx context.Context) error {\n\tif b.createCRD {\n\t\tif err := b.initCRD(); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tgo b.run(ctx)\n\t<-ctx.Done()\n\treturn ctx.Err()\n}\n\nfunc (b *Backup) initCRD() error {\n\terr := k8sutil.CreateCRD(b.kubeExtCli, api.EtcdBackupCRDName, api.EtcdBackupResourceKind, api.EtcdBackupResourcePlural, \"\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create CRD: %v\", err)\n\t}\n\treturn k8sutil.WaitCRDReady(b.kubeExtCli, api.EtcdBackupCRDName)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/controller/backup-operator/oss_backup.go",
    "content": "// Copyright 2019 The etcd-operator 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\npackage controller\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/backup\"\n\t\"github.com/coreos/etcd-operator/pkg/backup/writer\"\n\t\"github.com/coreos/etcd-operator/pkg/util/alibabacloudutil/ossfactory\"\n\n\t\"k8s.io/client-go/kubernetes\"\n)\n\n// handleOSS saves etcd cluster's backup to specificed OSS path.\nfunc handleOSS(ctx context.Context, kubecli kubernetes.Interface, s *api.OSSBackupSource, endpoints []string, clientTLSSecret, basicAuthSecret,\n\tnamespace string, insecureSkipVerify, isPeriodic bool, maxBackup int) (*api.BackupStatus, error) {\n\tif s.Endpoint == \"\" {\n\t\ts.Endpoint = \"http://oss-cn-hangzhou.aliyuncs.com\"\n\t}\n\t// TODO: controls NewClientFromSecret with ctx. This depends on upstream kubernetes to support API calls with ctx.\n\tcli, err := ossfactory.NewClientFromSecret(kubecli, namespace, s.Endpoint, s.OSSSecret)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\ttlsConfig, err := generateTLSConfigWithVerify(kubecli, clientTLSSecret, namespace, insecureSkipVerify)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar username, password string\n\tif username, password, err = generateUsernamePassword(kubecli, basicAuthSecret, namespace); err != nil {\n\t\treturn nil, err\n\t}\n\n\tbm := backup.NewBackupManagerFromWriter(kubecli, writer.NewOSSWriter(cli.OSS), tlsConfig, endpoints, namespace, username, password)\n\n\trev, etcdVersion, now, err := bm.SaveSnap(ctx, s.Path, isPeriodic)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to save snapshot (%v)\", err)\n\t}\n\n\tif maxBackup > 0 {\n\t\terr := bm.EnsureMaxBackup(ctx, s.Path, maxBackup)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"succeeded in saving snapshot but failed to delete old snapshot (%v)\", err)\n\t\t}\n\t}\n\n\treturn &api.BackupStatus{EtcdVersion: etcdVersion, EtcdRevision: rev, LastSuccessDate: *now}, nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/controller/backup-operator/s3_backup.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage controller\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"fmt\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/backup\"\n\t\"github.com/coreos/etcd-operator/pkg/backup/writer\"\n\t\"github.com/coreos/etcd-operator/pkg/util/awsutil/s3factory\"\n\n\t\"k8s.io/client-go/kubernetes\"\n)\n\n// TODO: replace this with generic backend interface for other options (PV, Azure)\n// handleS3 saves etcd cluster's backup to specificed S3 path.\nfunc handleS3(ctx context.Context, kubecli kubernetes.Interface, s *api.S3BackupSource, endpoints []string, clientTLSSecret, basicAuthSecret,\n\tnamespace string, insecureSkipVerify, isPeriodic bool, maxBackup int) (*api.BackupStatus, error) {\n\t// TODO: controls NewClientFromSecret with ctx. This depends on upstream kubernetes to support API calls with ctx.\n\tcli, err := s3factory.NewClientFromSecret(kubecli, namespace, s.Endpoint, s.AWSSecret, s.ForcePathStyle)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer cli.Close()\n\n\tvar tlsConfig *tls.Config\n\tif tlsConfig, err = generateTLSConfigWithVerify(kubecli, clientTLSSecret, namespace, insecureSkipVerify); err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar username, password string\n\tif username, password, err = generateUsernamePassword(kubecli, basicAuthSecret, namespace); err != nil {\n\t\treturn nil, err\n\t}\n\n\tbm := backup.NewBackupManagerFromWriter(kubecli, writer.NewS3Writer(cli.S3), tlsConfig, endpoints, namespace, username, password)\n\n\trev, etcdVersion, now, err := bm.SaveSnap(ctx, s.Path, isPeriodic)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to save snapshot (%v)\", err)\n\t}\n\tif maxBackup > 0 {\n\t\terr := bm.EnsureMaxBackup(ctx, s.Path, maxBackup)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"succeeded in saving snapshot but failed to delete old snapshot (%v)\", err)\n\t\t}\n\t}\n\treturn &api.BackupStatus{EtcdVersion: etcdVersion, EtcdRevision: rev, LastSuccessDate: *now}, nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/controller/backup-operator/sync.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage controller\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"reflect\"\n\t\"time\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/util/constants\"\n\n\t\"github.com/sirupsen/logrus\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\t\"k8s.io/apimachinery/pkg/api/meta\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/types\"\n)\n\nconst (\n\t// Copy from deployment_controller.go:\n\t// maxRetries is the number of times a etcd backup will be retried before it is dropped out of the queue.\n\t// With the current rate-limiter in use (5ms*2^(maxRetries-1)) the following numbers represent the times\n\t// an etcd backup is going to be requeued:\n\t//\n\t// 5ms, 10ms, 20ms, 40ms, 80ms, 160ms, 320ms, 640ms, 1.3s, 2.6s, 5.1s, 10.2s, 20.4s, 41s, 82s\n\tmaxRetries = 15\n)\n\nfunc (b *Backup) runWorker() {\n\tfor b.processNextItem() {\n\t}\n}\n\nfunc (b *Backup) processNextItem() bool {\n\t// Wait until there is a new item in the working queue\n\tkey, quit := b.queue.Get()\n\tif quit {\n\t\treturn false\n\t}\n\t// Tell the queue that we are done with processing this key. This unblocks the key for other workers\n\t// This allows safe parallel processing because two pods with the same key are never processed in\n\t// parallel.\n\tdefer b.queue.Done(key)\n\terr := b.processItem(key.(string))\n\t// Handle the error if something went wrong during the execution of the business logic\n\tb.handleErr(err, key)\n\treturn true\n}\n\nfunc (b *Backup) processItem(key string) error {\n\tobj, exists, err := b.indexer.GetByKey(key)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !exists {\n\t\treturn nil\n\t}\n\n\teb := obj.(*api.EtcdBackup)\n\n\tif eb.DeletionTimestamp != nil {\n\t\tb.deletePeriodicBackupRunner(eb.ObjectMeta.UID)\n\t\treturn b.removeFinalizerOfPeriodicBackup(eb)\n\t}\n\tisPeriodic := isPeriodicBackup(&eb.Spec)\n\n\t// don't process the CR if it has a status since\n\t// having a status means that the backup is either made or failed.\n\tif !isPeriodic &&\n\t\t(eb.Status.Succeeded || len(eb.Status.Reason) != 0) {\n\t\treturn nil\n\t}\n\n\tif isPeriodic && b.isChanged(eb) {\n\t\t// Stop previous backup runner if it exists\n\t\tb.deletePeriodicBackupRunner(eb.ObjectMeta.UID)\n\n\t\t// Add finalizer if need\n\t\teb, err = b.addFinalizerOfPeriodicBackupIfNeed(eb)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// Run new backup runner\n\t\tticker := time.NewTicker(\n\t\t\ttime.Duration(eb.Spec.BackupPolicy.BackupIntervalInSecond) * time.Second)\n\t\tctx := context.Background()\n\t\tctx, cancel := context.WithCancel(ctx)\n\t\tb.logger.Infof(\"periodic backup runner,task info is %v\", eb)\n\t\tgo b.periodicRunnerFunc(ctx, ticker, eb)\n\n\t\t// Store cancel function for periodic\n\t\tb.backupRunnerStore.Store(eb.ObjectMeta.UID, BackupRunner{eb.Spec, cancel})\n\n\t} else if !isPeriodic {\n\t\t// Perform backup\n\t\tbs, err := b.handleBackup(nil, eb, false)\n\t\t// Report backup status\n\t\tb.reportBackupStatus(bs, err, eb)\n\t}\n\treturn err\n}\n\nfunc (b *Backup) isChanged(eb *api.EtcdBackup) bool {\n\tbackupRunner, exists := b.backupRunnerStore.Load(eb.ObjectMeta.UID)\n\tif !exists {\n\t\treturn true\n\t}\n\treturn !reflect.DeepEqual(eb.Spec, backupRunner.(BackupRunner).spec)\n}\n\nfunc (b *Backup) deletePeriodicBackupRunner(uid types.UID) bool {\n\tbackupRunner, exists := b.backupRunnerStore.Load(uid)\n\tif exists {\n\t\tbackupRunner.(BackupRunner).cancelFunc()\n\t\tb.backupRunnerStore.Delete(uid)\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc (b *Backup) addFinalizerOfPeriodicBackupIfNeed(eb *api.EtcdBackup) (*api.EtcdBackup, error) {\n\tebNew := eb.DeepCopyObject()\n\tmetadata, err := meta.Accessor(ebNew)\n\tif err != nil {\n\t\treturn eb, err\n\t}\n\tif !containsString(metadata.GetFinalizers(), \"backup-operator-periodic\") {\n\t\tmetadata.SetFinalizers(append(metadata.GetFinalizers(), \"backup-operator-periodic\"))\n\t\t_, err := b.backupCRCli.EtcdV1beta2().EtcdBackups(eb.Namespace).Update(ebNew.(*api.EtcdBackup))\n\t\tif err != nil {\n\t\t\treturn eb, err\n\t\t}\n\t\treturn ebNew.(*api.EtcdBackup), nil\n\t}\n\treturn eb, nil\n}\n\nfunc (b *Backup) removeFinalizerOfPeriodicBackup(eb *api.EtcdBackup) error {\n\tebNew := eb.DeepCopyObject()\n\tmetadata, err := meta.Accessor(ebNew)\n\tif err != nil {\n\t\treturn err\n\t}\n\tvar finalizers []string\n\tfor _, finalizer := range metadata.GetFinalizers() {\n\t\tif finalizer == \"backup-operator-periodic\" {\n\t\t\tcontinue\n\t\t}\n\t\tfinalizers = append(finalizers, finalizer)\n\t}\n\tmetadata.SetFinalizers(finalizers)\n\t_, err = b.backupCRCli.EtcdV1beta2().EtcdBackups(eb.Namespace).Update(ebNew.(*api.EtcdBackup))\n\treturn err\n}\n\nfunc (b *Backup) periodicRunnerFunc(ctx context.Context, t *time.Ticker, eb *api.EtcdBackup) {\n\tdefer t.Stop()\n\tfor {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\tbreak\n\t\tcase <-t.C:\n\t\t\tvar latestEb *api.EtcdBackup\n\t\t\tvar bs *api.BackupStatus\n\t\t\tvar err error\n\t\t\tretryLimit := 5\n\t\t\tfor i := 1; i < retryLimit+1; i++ {\n\t\t\t\tlatestEb, err = b.backupCRCli.EtcdV1beta2().EtcdBackups(eb.Namespace).Get(eb.Name, metav1.GetOptions{})\n\t\t\t\tif err != nil {\n\t\t\t\t\tif apierrors.IsNotFound(err) {\n\t\t\t\t\t\tb.logger.Infof(\"Could not find EtcdBackup. Stopping periodic backup for EtcdBackup CR %v\",\n\t\t\t\t\t\t\teb.Name)\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tb.logger.Warningf(\"[Attempt: %d/%d] Failed to get latest EtcdBackup %v : (%v)\",\n\t\t\t\t\t\ti, retryLimit, eb.Name, err)\n\t\t\t\t\ttime.Sleep(1)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif err == nil {\n\t\t\t\t// Perform backup\n\t\t\t\tbs, err = b.handleBackup(&ctx, latestEb, true)\n\t\t\t}\n\t\t\t// Report backup status\n\t\t\tb.reportBackupStatus(bs, err, latestEb)\n\t\tdefault:\n\t\t\ttime.Sleep(time.Second)\n\t\t}\n\t}\n}\n\nfunc (b *Backup) reportBackupStatus(bs *api.BackupStatus, berr error, eb *api.EtcdBackup) {\n\tif berr != nil {\n\t\teb.Status.Succeeded = false\n\t\teb.Status.Reason = berr.Error()\n\t} else {\n\t\teb.Status.Reason = \"\"\n\t\teb.Status.Succeeded = true\n\t\teb.Status.EtcdRevision = bs.EtcdRevision\n\t\teb.Status.EtcdVersion = bs.EtcdVersion\n\t\teb.Status.LastSuccessDate = bs.LastSuccessDate\n\t}\n\t_, err := b.backupCRCli.EtcdV1beta2().EtcdBackups(eb.Namespace).Update(eb)\n\tif err != nil {\n\t\tb.logger.Warningf(\"failed to update status of backup CR %v : (%v)\", eb.Name, err)\n\t}\n}\n\nfunc (b *Backup) handleErr(err error, key interface{}) {\n\tif err == nil {\n\t\t// Forget about the #AddRateLimited history of the key on every successful synchronization.\n\t\t// This ensures that future processing of updates for this key is not delayed because of\n\t\t// an outdated error history.\n\t\tb.queue.Forget(key)\n\t\treturn\n\t}\n\n\t// This controller retries maxRetries times if something goes wrong. After that, it stops trying.\n\tif b.queue.NumRequeues(key) < maxRetries {\n\t\tb.logger.Errorf(\"error syncing etcd backup (%v): %v\", key, err)\n\n\t\t// Re-enqueue the key rate limited. Based on the rate limiter on the\n\t\t// queue and the re-enqueue history, the key will be processed later again.\n\t\tb.queue.AddRateLimited(key)\n\t\treturn\n\t}\n\n\tb.queue.Forget(key)\n\t// Report that, even after several retries, we could not successfully process this key\n\tb.logger.Infof(\"Dropping etcd backup (%v) out of the queue: %v\", key, err)\n}\n\nfunc (b *Backup) handleBackup(parentContext *context.Context, eb *api.EtcdBackup, isPeriodic bool) (*api.BackupStatus, error) {\n\tspec := &eb.Spec\n\terr := validate(spec)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// When BackupPolicy.TimeoutInSecond <= 0, use default DefaultBackupTimeout.\n\tbackupTimeout := time.Duration(constants.DefaultBackupTimeout)\n\tif spec.BackupPolicy != nil && spec.BackupPolicy.TimeoutInSecond > 0 {\n\t\tbackupTimeout = time.Duration(spec.BackupPolicy.TimeoutInSecond) * time.Second\n\t}\n\tbackupMaxCount := 0\n\tif spec.BackupPolicy != nil && spec.BackupPolicy.MaxBackups > 0 {\n\t\tbackupMaxCount = spec.BackupPolicy.MaxBackups\n\t}\n\n\tif parentContext == nil {\n\t\ttmpParent := context.Background()\n\t\tparentContext = &tmpParent\n\t}\n\tctx, cancel := context.WithTimeout(*parentContext, backupTimeout)\n\tdefer cancel()\n\tswitch spec.StorageType {\n\tcase api.BackupStorageTypeS3:\n\t\tbs, err := handleS3(ctx, b.kubecli, spec.S3, spec.EtcdEndpoints, spec.ClientTLSSecret, spec.BasicAuthSecret,\n\t\t\teb.Namespace, spec.InsecureSkipVerify, isPeriodic, backupMaxCount)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn bs, nil\n\tcase api.BackupStorageTypeABS:\n\t\tbs, err := handleABS(ctx, b.kubecli, spec.ABS, spec.EtcdEndpoints, spec.ClientTLSSecret, spec.BasicAuthSecret,\n\t\t\teb.Namespace, spec.InsecureSkipVerify, isPeriodic, backupMaxCount)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn bs, nil\n\tcase api.BackupStorageTypeGCS:\n\t\tbs, err := handleGCS(ctx, b.kubecli, spec.GCS, spec.EtcdEndpoints, spec.ClientTLSSecret, spec.BasicAuthSecret,\n\t\t\teb.Namespace, spec.InsecureSkipVerify, isPeriodic, backupMaxCount)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn bs, nil\n\tcase api.BackupStorageTypeOSS:\n\t\tbs, err := handleOSS(ctx, b.kubecli, spec.OSS, spec.EtcdEndpoints, spec.ClientTLSSecret, spec.BasicAuthSecret,\n\t\t\teb.Namespace, spec.InsecureSkipVerify, isPeriodic, backupMaxCount)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn bs, nil\n\tcase api.BackupStorageTypeCOS:\n\t\tbs, err := handleCOS(ctx, b.kubecli, spec.COS, spec.EtcdEndpoints, spec.ClientTLSSecret, spec.BasicAuthSecret,\n\t\t\teb.Namespace, spec.InsecureSkipVerify, isPeriodic, backupMaxCount)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn bs, nil\n\tcase api.BackupStorageTypeHostPath:\n\t\tbs, err := handleHostPath(ctx, b.kubecli, spec.HostPath, spec.EtcdEndpoints, spec.ClientTLSSecret, spec.BasicAuthSecret,\n\t\t\teb.Namespace, spec.InsecureSkipVerify, isPeriodic, backupMaxCount)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn bs, nil\n\tdefault:\n\t\tlogrus.Fatalf(\"unknown StorageType: %v\", spec.StorageType)\n\t}\n\treturn nil, nil\n}\n\n// TODO: move this to initializer\nfunc validate(spec *api.BackupSpec) error {\n\tif len(spec.EtcdEndpoints) == 0 {\n\t\treturn errors.New(\"spec.etcdEndpoints should not be empty\")\n\t}\n\tif spec.BackupPolicy != nil {\n\t\tif spec.BackupPolicy.BackupIntervalInSecond < 0 {\n\t\t\treturn errors.New(\"spec.BackupPolicy.BackupIntervalInSecond should not be lower than 0\")\n\t\t}\n\t\tif spec.BackupPolicy.MaxBackups < 0 {\n\t\t\treturn errors.New(\"spec.BackupPolicy.MaxBackups should not be lower than 0\")\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/controller/backup-operator/sync_test.go",
    "content": "// Copyright 2018 The etcd-operator 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\npackage controller\n\nimport (\n\t\"testing\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n)\n\nfunc TestValidate(t *testing.T) {\n\ttests := []struct {\n\t\tspec      *api.BackupSpec\n\t\texpectErr bool\n\t}{{\n\t\tspec: &api.BackupSpec{\n\t\t\tEtcdEndpoints: []string{\"http://localhost:2379\"},\n\t\t},\n\t\texpectErr: false,\n\t}, { // fail due to empty etcd endpoints\n\t\tspec:      &api.BackupSpec{},\n\t\texpectErr: true,\n\t}}\n\n\tfor i, tt := range tests {\n\t\terr := validate(tt.spec)\n\t\tif err != nil && !tt.expectErr {\n\t\t\tt.Errorf(\"#%d: validate failed: %v\", i, err)\n\t\t}\n\t\tif err == nil && tt.expectErr {\n\t\t\tt.Errorf(\"#%d: expect error, but got nil\", i)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/controller/backup-operator/util.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage controller\n\nimport (\n\t\"crypto/tls\"\n\t\"fmt\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/util/etcdutil\"\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n)\n\nfunc generateTLSConfig(kubecli kubernetes.Interface, clientTLSSecret, namespace string) (*tls.Config, error) {\n\tvar tlsConfig *tls.Config\n\tif len(clientTLSSecret) != 0 {\n\t\td, err := k8sutil.GetTLSDataFromSecret(kubecli, namespace, clientTLSSecret)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to get TLS data from secret (%v): %v\", clientTLSSecret, err)\n\t\t}\n\t\ttlsConfig, err = etcdutil.NewTLSConfig(d.CertData, d.KeyData, d.CAData)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to constructs tls config: %v\", err)\n\t\t}\n\t}\n\treturn tlsConfig, nil\n}\n\n//tlsConfig  with insecureSkipVerify\nfunc generateTLSConfigWithVerify(kubecli kubernetes.Interface, clientTLSSecret, namespace string, insecureSkipVerify bool) (*tls.Config, error) {\n\ttlsConfig, err := generateTLSConfig(kubecli, clientTLSSecret, namespace)\n\tif err != nil {\n\t\treturn tlsConfig, err\n\t}\n\t//add skip verify\n\tif tlsConfig != nil {\n\t\ttlsConfig.InsecureSkipVerify = insecureSkipVerify\n\t}\n\treturn tlsConfig, nil\n}\n\nfunc generateUsernamePassword(kubecli kubernetes.Interface, basicAuthSecret, namespace string) (username, password string, err error) {\n\tif len(basicAuthSecret) != 0 {\n\t\tsecret, err := kubecli.CoreV1().Secrets(namespace).Get(basicAuthSecret, metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\treturn \"\", \"\", err\n\t\t}\n\t\tusername, password = string(secret.Data[\"username\"]), string(secret.Data[\"password\"])\n\t}\n\treturn \"\", \"\", nil\n}\n\nfunc isPeriodicBackup(ebSpec *api.BackupSpec) bool {\n\tif ebSpec.BackupPolicy != nil {\n\t\treturn ebSpec.BackupPolicy.BackupIntervalInSecond != 0\n\t}\n\treturn false\n}\n\nfunc containsString(slice []string, s string) bool {\n\tfor _, item := range slice {\n\t\tif item == s {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/controller/controller.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage controller\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/cluster\"\n\t\"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned\"\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\n\t\"github.com/sirupsen/logrus\"\n\tapiextensionsclient \"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset\"\n\tkwatch \"k8s.io/apimachinery/pkg/watch\"\n\t\"k8s.io/client-go/kubernetes\"\n)\n\nvar initRetryWaitTime = 30 * time.Second\n\ntype Event struct {\n\tType   kwatch.EventType\n\tObject *api.EtcdCluster\n}\n\ntype Controller struct {\n\tlogger *logrus.Entry\n\tConfig\n\n\tclusters map[string]*cluster.Cluster\n}\n\ntype Config struct {\n\tNamespace      string\n\tClusterWide    bool\n\tServiceAccount string\n\tKubeCli        kubernetes.Interface\n\tKubeExtCli     apiextensionsclient.Interface\n\tEtcdCRCli      versioned.Interface\n\tCreateCRD      bool\n}\n\nfunc New(cfg Config) *Controller {\n\treturn &Controller{\n\t\tlogger: logrus.WithField(\"pkg\", \"controller\"),\n\n\t\tConfig:   cfg,\n\t\tclusters: make(map[string]*cluster.Cluster),\n\t}\n}\n\n// handleClusterEvent returns true if cluster is ignored (not managed) by this instance.\nfunc (c *Controller) handleClusterEvent(event *Event) (bool, error) {\n\tclus := event.Object\n\n\tif !c.managed(clus) {\n\t\treturn true, nil\n\t}\n\n\tif clus.Status.IsFailed() {\n\t\tclustersFailed.Inc()\n\t\tif event.Type == kwatch.Deleted {\n\t\t\tdelete(c.clusters, getNamespacedName(clus))\n\t\t\treturn false, nil\n\t\t}\n\t\treturn false, fmt.Errorf(\"ignore failed cluster (%s). Please delete its CR\", clus.Name)\n\t}\n\n\tclus.SetDefaults()\n\n\tif err := clus.Spec.Validate(); err != nil {\n\t\treturn false, fmt.Errorf(\"invalid cluster spec. please fix the following problem with the cluster spec: %v\", err)\n\t}\n\n\tswitch event.Type {\n\tcase kwatch.Added:\n\t\tif _, ok := c.clusters[getNamespacedName(clus)]; ok {\n\t\t\treturn false, fmt.Errorf(\"unsafe state. cluster (%s) was created before but we received event (%s)\", clus.Name, event.Type)\n\t\t}\n\n\t\tnc := cluster.New(c.makeClusterConfig(), clus)\n\t\tif nc == nil {\n\t\t\treturn false, fmt.Errorf(\"cluster name cannot be more than %v characters long, please delete the CR\\n\", k8sutil.MaxNameLength)\n\t\t}\n\t\tc.clusters[getNamespacedName(clus)] = nc\n\n\t\tclustersCreated.Inc()\n\t\tclustersTotal.Inc()\n\n\tcase kwatch.Modified:\n\t\tif _, ok := c.clusters[getNamespacedName(clus)]; !ok {\n\t\t\treturn false, fmt.Errorf(\"unsafe state. cluster (%s) was never created but we received event (%s)\", clus.Name, event.Type)\n\t\t}\n\t\tc.clusters[getNamespacedName(clus)].Update(clus)\n\t\tclustersModified.Inc()\n\n\tcase kwatch.Deleted:\n\t\tif _, ok := c.clusters[getNamespacedName(clus)]; !ok {\n\t\t\treturn false, fmt.Errorf(\"unsafe state. cluster (%s) was never created but we received event (%s)\", clus.Name, event.Type)\n\t\t}\n\t\tc.clusters[getNamespacedName(clus)].Delete()\n\t\tdelete(c.clusters, getNamespacedName(clus))\n\t\tclustersDeleted.Inc()\n\t\tclustersTotal.Dec()\n\t}\n\treturn false, nil\n}\n\nfunc (c *Controller) makeClusterConfig() cluster.Config {\n\treturn cluster.Config{\n\t\tServiceAccount: c.Config.ServiceAccount,\n\t\tKubeCli:        c.Config.KubeCli,\n\t\tEtcdCRCli:      c.Config.EtcdCRCli,\n\t}\n}\n\nfunc (c *Controller) initCRD() error {\n\terr := k8sutil.CreateCRD(c.KubeExtCli, api.EtcdClusterCRDName, api.EtcdClusterResourceKind, api.EtcdClusterResourcePlural, \"etcd\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create CRD: %v\", err)\n\t}\n\treturn k8sutil.WaitCRDReady(c.KubeExtCli, api.EtcdClusterCRDName)\n}\n\nfunc getNamespacedName(c *api.EtcdCluster) string {\n\treturn fmt.Sprintf(\"%s%c%s\", c.Namespace, '/', c.Name)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/controller/controller_test.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage controller\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/cluster\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/watch\"\n)\n\nfunc TestHandleClusterEventUpdateFailedCluster(t *testing.T) {\n\tc := New(Config{})\n\n\tclus := &api.EtcdCluster{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName: \"test\",\n\t\t},\n\t\tStatus: api.ClusterStatus{\n\t\t\tPhase: api.ClusterPhaseFailed,\n\t\t},\n\t}\n\te := &Event{\n\t\tType:   watch.Modified,\n\t\tObject: clus,\n\t}\n\t_, err := c.handleClusterEvent(e)\n\tprefix := \"ignore failed cluster\"\n\tif !strings.HasPrefix(err.Error(), prefix) {\n\t\tt.Errorf(\"expect err='%s...', get=%v\", prefix, err)\n\t}\n}\n\nfunc TestHandleClusterEventDeleteFailedCluster(t *testing.T) {\n\tc := New(Config{})\n\tname := \"tests\"\n\tclus := &api.EtcdCluster{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName: name,\n\t\t},\n\t\tStatus: api.ClusterStatus{\n\t\t\tPhase: api.ClusterPhaseFailed,\n\t\t},\n\t}\n\te := &Event{\n\t\tType:   watch.Deleted,\n\t\tObject: clus,\n\t}\n\n\tc.clusters[getNamespacedName(clus)] = &cluster.Cluster{}\n\n\tif _, err := c.handleClusterEvent(e); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif c.clusters[getNamespacedName(clus)] != nil {\n\t\tt.Errorf(\"failed cluster not cleaned up after delete event, cluster struct: %v\", c.clusters[getNamespacedName(clus)])\n\t}\n}\n\nfunc TestHandleClusterEventClusterwide(t *testing.T) {\n\tc := New(Config{ClusterWide: true})\n\n\tclus := &api.EtcdCluster{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      \"test\",\n\t\t\tNamespace: \"a\",\n\t\t\tAnnotations: map[string]string{\n\t\t\t\t\"etcd.database.coreos.com/scope\": \"clusterwide\",\n\t\t\t},\n\t\t},\n\t}\n\te := &Event{\n\t\tType:   watch.Modified,\n\t\tObject: clus,\n\t}\n\tif ignored, _ := c.handleClusterEvent(e); ignored {\n\t\tt.Errorf(\"cluster shouldn't be ignored\")\n\t}\n}\n\nfunc TestHandleClusterEventClusterwideIgnored(t *testing.T) {\n\tc := New(Config{ClusterWide: true})\n\n\tclus := &api.EtcdCluster{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName: \"test\",\n\t\t},\n\t}\n\te := &Event{\n\t\tType:   watch.Modified,\n\t\tObject: clus,\n\t}\n\tif ignored, _ := c.handleClusterEvent(e); !ignored {\n\t\tt.Errorf(\"cluster should be ignored\")\n\t}\n}\n\nfunc TestHandleClusterEventClusterwideAddTwoCR(t *testing.T) {\n\tc := New(Config{ClusterWide: true})\n\tclusA := &api.EtcdCluster{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      \"test\",\n\t\t\tNamespace: \"a\",\n\t\t},\n\t}\n\tclusB := &api.EtcdCluster{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      \"test\",\n\t\t\tNamespace: \"b\",\n\t\t},\n\t}\n\te := &Event{\n\t\tType:   watch.Added,\n\t\tObject: clusA,\n\t}\n\tignored, errA := c.handleClusterEvent(e)\n\tif !ignored && errA != nil {\n\t\tt.Errorf(\"cluster should be Added\")\n\t}\n\te.Object = clusB\n\tignored, errB := c.handleClusterEvent(e)\n\tif !ignored && errB != nil {\n\t\tt.Errorf(\"cluster should be Added\")\n\t}\n}\n\nfunc TestHandleClusterEventNamespacedIgnored(t *testing.T) {\n\tc := New(Config{})\n\n\tclus := &api.EtcdCluster{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName: \"test\",\n\t\t\tAnnotations: map[string]string{\n\t\t\t\t\"etcd.database.coreos.com/scope\": \"clusterwide\",\n\t\t\t},\n\t\t},\n\t}\n\te := &Event{\n\t\tType:   watch.Modified,\n\t\tObject: clus,\n\t}\n\tif ignored, _ := c.handleClusterEvent(e); !ignored {\n\t\tt.Errorf(\"cluster should be ignored\")\n\t}\n}\n\nfunc TestHandleClusterEventWithLongClusterName(t *testing.T) {\n\tc := New(Config{})\n\n\tclus := &api.EtcdCluster{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName: \"example-etcd-cluster123456789123456789123456789123456789123456\",\n\t\t},\n\t}\n\te := &Event{\n\t\tType:   watch.Added,\n\t\tObject: clus,\n\t}\n\tif ignored, err := c.handleClusterEvent(e); !ignored {\n\t\tif err == nil {\n\t\t\tt.Errorf(\"err should not be nil\")\n\t\t}\n\t} else {\n\t\tt.Errorf(\"cluster should not be ignored\")\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/controller/informer.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage controller\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"time\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\t\"github.com/coreos/etcd-operator/pkg/util/probe\"\n\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/fields\"\n\tkwatch \"k8s.io/apimachinery/pkg/watch\"\n\t\"k8s.io/client-go/tools/cache\"\n)\n\n// TODO: get rid of this once we use workqueue\nvar pt *panicTimer\n\nfunc init() {\n\tpt = newPanicTimer(time.Minute, \"unexpected long blocking (> 1 Minute) when handling cluster event\")\n}\n\nfunc (c *Controller) Start() error {\n\t// TODO: get rid of this init code. CRD and storage class will be managed outside of operator.\n\tfor {\n\t\terr := c.initResource()\n\t\tif err == nil {\n\t\t\tbreak\n\t\t}\n\t\tc.logger.Errorf(\"initialization failed: %v\", err)\n\t\tc.logger.Infof(\"retry in %v...\", initRetryWaitTime)\n\t\ttime.Sleep(initRetryWaitTime)\n\t}\n\n\tprobe.SetReady()\n\tc.run()\n\tpanic(\"unreachable\")\n}\n\nfunc (c *Controller) run() {\n\tvar ns string\n\tif c.Config.ClusterWide {\n\t\tns = metav1.NamespaceAll\n\t} else {\n\t\tns = c.Config.Namespace\n\t}\n\n\tsource := cache.NewListWatchFromClient(\n\t\tc.Config.EtcdCRCli.EtcdV1beta2().RESTClient(),\n\t\tapi.EtcdClusterResourcePlural,\n\t\tns,\n\t\tfields.Everything())\n\n\t_, informer := cache.NewIndexerInformer(source, &api.EtcdCluster{}, 0, cache.ResourceEventHandlerFuncs{\n\t\tAddFunc:    c.onAddEtcdClus,\n\t\tUpdateFunc: c.onUpdateEtcdClus,\n\t\tDeleteFunc: c.onDeleteEtcdClus,\n\t}, cache.Indexers{})\n\n\tctx := context.TODO()\n\t// TODO: use workqueue to avoid blocking\n\tinformer.Run(ctx.Done())\n}\n\nfunc (c *Controller) initResource() error {\n\tif c.Config.CreateCRD {\n\t\terr := c.initCRD()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"fail to init CRD: %v\", err)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (c *Controller) onAddEtcdClus(obj interface{}) {\n\tc.syncEtcdClus(obj.(*api.EtcdCluster))\n}\n\nfunc (c *Controller) onUpdateEtcdClus(oldObj, newObj interface{}) {\n\tc.syncEtcdClus(newObj.(*api.EtcdCluster))\n}\n\nfunc (c *Controller) onDeleteEtcdClus(obj interface{}) {\n\tclus, ok := obj.(*api.EtcdCluster)\n\tif !ok {\n\t\ttombstone, ok := obj.(cache.DeletedFinalStateUnknown)\n\t\tif !ok {\n\t\t\tpanic(fmt.Sprintf(\"unknown object from EtcdCluster delete event: %#v\", obj))\n\t\t}\n\t\tclus, ok = tombstone.Obj.(*api.EtcdCluster)\n\t\tif !ok {\n\t\t\tpanic(fmt.Sprintf(\"Tombstone contained object that is not an EtcdCluster: %#v\", obj))\n\t\t}\n\t}\n\tev := &Event{\n\t\tType:   kwatch.Deleted,\n\t\tObject: clus,\n\t}\n\n\tpt.start()\n\t_, err := c.handleClusterEvent(ev)\n\tif err != nil {\n\t\tc.logger.Warningf(\"fail to handle event: %v\", err)\n\t}\n\tpt.stop()\n}\n\nfunc (c *Controller) syncEtcdClus(clus *api.EtcdCluster) {\n\tev := &Event{\n\t\tType:   kwatch.Added,\n\t\tObject: clus,\n\t}\n\t// re-watch or restart could give ADD event.\n\t// If for an ADD event the cluster spec is invalid then it is not added to the local cache\n\t// so modifying that cluster will result in another ADD event\n\tif _, ok := c.clusters[getNamespacedName(clus)]; ok {\n\t\tev.Type = kwatch.Modified\n\t}\n\n\tpt.start()\n\t_, err := c.handleClusterEvent(ev)\n\tif err != nil {\n\t\tc.logger.Warningf(\"fail to handle event: %v\", err)\n\t}\n\tpt.stop()\n}\n\nfunc (c *Controller) managed(clus *api.EtcdCluster) bool {\n\tif v, ok := clus.Annotations[k8sutil.AnnotationScope]; ok {\n\t\tif c.Config.ClusterWide {\n\t\t\treturn v == k8sutil.AnnotationClusterWide\n\t\t}\n\t} else {\n\t\tif !c.Config.ClusterWide {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/controller/metrics.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage controller\n\nimport \"github.com/prometheus/client_golang/prometheus\"\n\nvar (\n\tclustersTotal = prometheus.NewGauge(prometheus.GaugeOpts{\n\t\tNamespace: \"etcd_operator\",\n\t\tSubsystem: \"controller\",\n\t\tName:      \"clusters\",\n\t\tHelp:      \"Total number of clusters managed by the controller\",\n\t})\n\n\tclustersCreated = prometheus.NewCounter(prometheus.CounterOpts{\n\t\tNamespace: \"etcd_operator\",\n\t\tSubsystem: \"controller\",\n\t\tName:      \"clusters_created\",\n\t\tHelp:      \"Total number of clusters created\",\n\t})\n\n\tclustersDeleted = prometheus.NewCounter(prometheus.CounterOpts{\n\t\tNamespace: \"etcd_operator\",\n\t\tSubsystem: \"controller\",\n\t\tName:      \"clusters_deleted\",\n\t\tHelp:      \"Total number of clusters deleted\",\n\t})\n\n\tclustersModified = prometheus.NewCounter(prometheus.CounterOpts{\n\t\tNamespace: \"etcd_operator\",\n\t\tSubsystem: \"controller\",\n\t\tName:      \"clusters_modified\",\n\t\tHelp:      \"Total number of clusters modified\",\n\t})\n\n\tclustersFailed = prometheus.NewCounter(prometheus.CounterOpts{\n\t\tNamespace: \"etcd_operator\",\n\t\tSubsystem: \"controller\",\n\t\tName:      \"clusters_failed\",\n\t\tHelp:      \"Total number of clusters failed\",\n\t})\n)\n\nfunc init() {\n\tprometheus.MustRegister(clustersTotal)\n\tprometheus.MustRegister(clustersCreated)\n\tprometheus.MustRegister(clustersDeleted)\n\tprometheus.MustRegister(clustersModified)\n\tprometheus.MustRegister(clustersFailed)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/controller/restore-operator/controller.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage controller\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\n\t\"k8s.io/apimachinery/pkg/fields\"\n\t\"k8s.io/apimachinery/pkg/util/wait\"\n\t\"k8s.io/client-go/tools/cache\"\n\t\"k8s.io/client-go/util/workqueue\"\n)\n\nfunc (r *Restore) run(ctx context.Context) {\n\tsource := cache.NewListWatchFromClient(\n\t\tr.etcdCRCli.EtcdV1beta2().RESTClient(),\n\t\tapi.EtcdRestoreResourcePlural,\n\t\tr.namespace,\n\t\tfields.Everything(),\n\t)\n\n\tr.queue = workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), \"etcd-restore-operator\")\n\tr.indexer, r.informer = cache.NewIndexerInformer(source, &api.EtcdRestore{}, 0, cache.ResourceEventHandlerFuncs{\n\t\tAddFunc:    r.onAdd,\n\t\tUpdateFunc: r.onUpdate,\n\t\tDeleteFunc: r.onDelete,\n\t}, cache.Indexers{})\n\n\tdefer r.queue.ShutDown()\n\n\tr.logger.Info(\"starting restore controller\")\n\tgo r.informer.Run(ctx.Done())\n\n\tif !cache.WaitForCacheSync(ctx.Done(), r.informer.HasSynced) {\n\t\treturn\n\t}\n\n\tconst numWorkers = 1\n\tfor i := 0; i < numWorkers; i++ {\n\t\tgo wait.Until(r.runWorker, time.Second, ctx.Done())\n\t}\n\n\t<-ctx.Done()\n\tr.logger.Info(\"stopping restore controller\")\n}\n\nfunc (r *Restore) onAdd(obj interface{}) {\n\tkey, err := cache.MetaNamespaceKeyFunc(obj)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tr.queue.Add(key)\n}\n\nfunc (r *Restore) onUpdate(oldObj, newObj interface{}) {\n\tkey, err := cache.MetaNamespaceKeyFunc(newObj)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tr.queue.Add(key)\n}\n\nfunc (r *Restore) onDelete(obj interface{}) {\n\tkey, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tr.queue.Add(key)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/controller/restore-operator/http.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage controller\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/backup/backupapi\"\n\t\"github.com/coreos/etcd-operator/pkg/backup/reader\"\n\t\"github.com/coreos/etcd-operator/pkg/util/alibabacloudutil/ossfactory\"\n\t\"github.com/coreos/etcd-operator/pkg/util/awsutil/s3factory\"\n\t\"github.com/coreos/etcd-operator/pkg/util/azureutil/absfactory\"\n\t\"github.com/coreos/etcd-operator/pkg/util/gcputil/gcsfactory\"\n\t\"github.com/coreos/etcd-operator/pkg/util/tencentcloudutil/cosfactory\"\n\n\t\"github.com/sirupsen/logrus\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\nconst (\n\tbackupHTTPPath = backupapi.APIV1 + \"/backup/\"\n\tlistenAddr     = \"0.0.0.0:19999\"\n)\n\nfunc (r *Restore) startHTTP() {\n\thttp.HandleFunc(backupapi.APIV1+\"/backup/\", r.handleServeBackup)\n\tlogrus.Infof(\"listening on %v\", listenAddr)\n\tpanic(http.ListenAndServe(listenAddr, nil))\n}\n\nfunc (r *Restore) handleServeBackup(w http.ResponseWriter, req *http.Request) {\n\terr := r.serveBackup(w, req)\n\tif err != nil {\n\t\tlogrus.Error(err)\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t}\n}\n\n// serveBackup parses incoming request url of the form /backup/<restore-name>\n// get the etcd restore name.\n// Then it returns the etcd cluster backup snapshot to the caller.\nfunc (r *Restore) serveBackup(w http.ResponseWriter, req *http.Request) error {\n\trestoreName := string(req.URL.Path[len(backupHTTPPath):])\n\tif len(restoreName) == 0 {\n\t\treturn errors.New(\"restore name is not specified\")\n\t}\n\n\tobj := &api.EtcdRestore{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      restoreName,\n\t\t\tNamespace: r.namespace,\n\t\t},\n\t}\n\tv, exists, err := r.indexer.Get(obj)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get restore CR for restore-name (%v): %v\", restoreName, err)\n\t}\n\tif !exists {\n\t\treturn fmt.Errorf(\"no restore CR found for restore-name (%v)\", restoreName)\n\t}\n\n\tlogrus.Infof(\"serving backup for restore CR %v\", restoreName)\n\tcr := v.(*api.EtcdRestore)\n\n\tvar (\n\t\tbackupReader reader.Reader\n\t\tpath         string\n\t)\n\n\tswitch cr.Spec.BackupStorageType {\n\tcase api.BackupStorageTypeS3:\n\t\trestoreSource := cr.Spec.RestoreSource\n\t\tif restoreSource.S3 == nil {\n\t\t\treturn errors.New(\"empty s3 restore source\")\n\t\t}\n\t\ts3RestoreSource := restoreSource.S3\n\t\tif len(s3RestoreSource.AWSSecret) == 0 || len(s3RestoreSource.Path) == 0 {\n\t\t\treturn errors.New(\"invalid s3 restore source field (spec.s3), must specify all required subfields\")\n\t\t}\n\n\t\ts3Cli, err := s3factory.NewClientFromSecret(r.kubecli, r.namespace, s3RestoreSource.Endpoint, s3RestoreSource.AWSSecret, s3RestoreSource.ForcePathStyle)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to create S3 client: %v\", err)\n\t\t}\n\t\tdefer s3Cli.Close()\n\n\t\tbackupReader = reader.NewS3Reader(s3Cli.S3)\n\t\tpath = s3RestoreSource.Path\n\tcase api.BackupStorageTypeABS:\n\t\trestoreSource := cr.Spec.RestoreSource\n\t\tif restoreSource.ABS == nil {\n\t\t\treturn errors.New(\"empty abs restore source\")\n\t\t}\n\t\tabsRestoreSource := restoreSource.ABS\n\t\tif len(absRestoreSource.ABSSecret) == 0 || len(absRestoreSource.Path) == 0 {\n\t\t\treturn errors.New(\"invalid abs restore source field (spec.abs), must specify all required subfields\")\n\t\t}\n\n\t\tabsCli, err := absfactory.NewClientFromSecret(r.kubecli, r.namespace, absRestoreSource.ABSSecret)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to create ABS client: %v\", err)\n\t\t}\n\t\t// Nothing to Close for absCli yet\n\n\t\tbackupReader = reader.NewABSReader(absCli.ABS)\n\t\tpath = absRestoreSource.Path\n\tcase api.BackupStorageTypeCOS:\n\t\trestoreSource := cr.Spec.RestoreSource\n\t\tif restoreSource.COS == nil {\n\t\t\treturn errors.New(\"empty cos restore source\")\n\t\t}\n\t\tcosRestoreSource := restoreSource.COS\n\t\tif len(cosRestoreSource.COSSecret) == 0 || len(cosRestoreSource.Path) == 0 {\n\t\t\treturn errors.New(\"invalid cos restore source field (spec.cos), must specify all required subfields\")\n\t\t}\n\n\t\tcosCli, err := cosfactory.NewClientFromSecret(r.kubecli, r.namespace, cosRestoreSource.COSSecret)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to create ABS client: %v\", err)\n\t\t}\n\t\t// Nothing to Close for cosCli yet\n\n\t\tbackupReader = reader.NewCOSReader(cosCli.COS)\n\t\tpath = cosRestoreSource.Path\n\tcase api.BackupStorageTypeGCS:\n\t\tctx := context.TODO()\n\t\trestoreSource := cr.Spec.RestoreSource\n\t\tif restoreSource.GCS == nil {\n\t\t\treturn errors.New(\"empty gcs restore source\")\n\t\t}\n\t\tgcsRestoreSource := restoreSource.GCS\n\t\tif len(gcsRestoreSource.Path) == 0 {\n\t\t\treturn errors.New(\"invalid gcs restore source field (spec.gcs), must specify all required subfields\")\n\t\t}\n\n\t\tgcsCli, err := gcsfactory.NewClientFromSecret(ctx, r.kubecli, r.namespace, gcsRestoreSource.GCPSecret)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to create GCS client: %v\", err)\n\t\t}\n\t\tdefer gcsCli.GCS.Close()\n\n\t\tbackupReader = reader.NewGCSReader(ctx, gcsCli.GCS)\n\t\tpath = gcsRestoreSource.Path\n\tcase api.BackupStorageTypeOSS:\n\t\trestoreSource := cr.Spec.RestoreSource\n\t\tif restoreSource.OSS == nil {\n\t\t\treturn errors.New(\"empty oss restore source\")\n\t\t}\n\t\tossRestoreSource := restoreSource.OSS\n\t\tif len(ossRestoreSource.OSSSecret) == 0 || len(ossRestoreSource.Path) == 0 {\n\t\t\treturn errors.New(\"invalid oss restore source field (spec.oss), must specify all required subfields\")\n\t\t}\n\n\t\tossCli, err := ossfactory.NewClientFromSecret(r.kubecli, r.namespace, ossRestoreSource.Endpoint, ossRestoreSource.OSSSecret)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to create OSS client: %v\", err)\n\t\t}\n\n\t\tbackupReader = reader.NewOSSReader(ossCli.OSS)\n\t\tpath = ossRestoreSource.Path\n\tcase api.BackupStorageTypeHostPath:\n\t\trestoreSource := cr.Spec.RestoreSource\n\t\tif restoreSource.HostPath == nil {\n\t\t\treturn errors.New(\"empty hostPath restore source\")\n\t\t}\n\t\thostPathRestoreSource := restoreSource.HostPath\n\t\tif len(hostPathRestoreSource.Path) == 0 {\n\t\t\treturn errors.New(\"invalid hostPath restore source field (spec.hostPath), must specify a file path\")\n\t\t}\n\n\t\tbackupReader = reader.NewHostPathReader(hostPathRestoreSource.Path)\n\t\tpath = hostPathRestoreSource.Path\n\tdefault:\n\t\treturn fmt.Errorf(\"unknown backup storage type (%s) for restore CR (%v)\", cr.Spec.BackupStorageType, restoreName)\n\t}\n\n\trc, err := backupReader.Open(path)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read backup file(%v): %v\", path, err)\n\t}\n\tdefer rc.Close()\n\n\t_, err = io.Copy(w, rc)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to write backup to %s: %v\", req.RemoteAddr, err)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/controller/restore-operator/operator.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage controller\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/client\"\n\t\"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned\"\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\n\t\"github.com/sirupsen/logrus\"\n\tapiextensionsclient \"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/client-go/tools/cache\"\n\t\"k8s.io/client-go/util/workqueue\"\n)\n\ntype Restore struct {\n\tlogger *logrus.Entry\n\n\tnamespace string\n\tmySvcAddr string\n\t// k8s workqueue pattern\n\tindexer  cache.Indexer\n\tinformer cache.Controller\n\tqueue    workqueue.RateLimitingInterface\n\n\tkubecli    kubernetes.Interface\n\tetcdCRCli  versioned.Interface\n\tkubeExtCli apiextensionsclient.Interface\n\n\tcreateCRD bool\n}\n\n// New creates a restore operator.\nfunc New(createCRD bool, namespace, mySvcAddr string) *Restore {\n\treturn &Restore{\n\t\tlogger:     logrus.WithField(\"pkg\", \"controller\"),\n\t\tnamespace:  namespace,\n\t\tmySvcAddr:  mySvcAddr,\n\t\tkubecli:    k8sutil.MustNewKubeClient(),\n\t\tetcdCRCli:  client.MustNewInCluster(),\n\t\tkubeExtCli: k8sutil.MustNewKubeExtClient(),\n\t\tcreateCRD:  createCRD,\n\t}\n}\n\n// Start starts the restore operator.\nfunc (r *Restore) Start(ctx context.Context) error {\n\tif r.createCRD {\n\t\tif err := r.initCRD(); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tgo r.run(ctx)\n\tgo r.startHTTP()\n\t<-ctx.Done()\n\treturn ctx.Err()\n}\n\nfunc (r *Restore) initCRD() error {\n\terr := k8sutil.CreateCRD(r.kubeExtCli, api.EtcdRestoreCRDName, api.EtcdRestoreResourceKind, api.EtcdRestoreResourcePlural, \"\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create CRD: %v\", err)\n\t}\n\treturn k8sutil.WaitCRDReady(r.kubeExtCli, api.EtcdRestoreCRDName)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/controller/restore-operator/sync.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage controller\n\nimport (\n\t\"fmt\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/backup/backupapi\"\n\t\"github.com/coreos/etcd-operator/pkg/util/etcdutil\"\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\t\"github.com/coreos/etcd-operator/pkg/util/retryutil\"\n\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\nconst (\n\t// Copy from deployment_controller.go:\n\t// maxRetries is the number of times a restore request will be retried before it is dropped out of the queue.\n\t// With the current rate-limiter in use (5ms*2^(maxRetries-1)) the following numbers represent the times\n\t// an restore request is going to be requeued:\n\t//\n\t// 5ms, 10ms, 20ms, 40ms, 80ms, 160ms, 320ms, 640ms, 1.3s, 2.6s, 5.1s, 10.2s, 20.4s, 41s, 82s\n\tmaxRetries = 15\n)\n\nfunc (r *Restore) runWorker() {\n\tfor r.processNextItem() {\n\t}\n}\n\nfunc (r *Restore) processNextItem() bool {\n\t// Wait until there is a new item in the working queue\n\tkey, quit := r.queue.Get()\n\tif quit {\n\t\treturn false\n\t}\n\t// Tell the queue that we are done with processing this key. This unblocks the key for other workers\n\t// This allows safe parallel processing because two pods with the same key are never processed in\n\t// parallel.\n\tdefer r.queue.Done(key)\n\terr := r.processItem(key.(string))\n\t// Handle the error if something went wrong during the execution of the business logic\n\tr.handleErr(err, key)\n\treturn true\n}\n\nfunc (r *Restore) processItem(key string) error {\n\tobj, exists, err := r.indexer.GetByKey(key)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !exists {\n\t\treturn nil\n\t}\n\treturn r.handleCR(obj.(*api.EtcdRestore), key)\n}\n\n// handleCR takes in EtcdRestore CR and prepares the seed so that etcd operator can take over it later.\nfunc (r *Restore) handleCR(er *api.EtcdRestore, key string) (err error) {\n\t// don't process the CR if it has a status since\n\t// having a status means that the restore is either made or failed.\n\tif er.Status.Succeeded || len(er.Status.Reason) != 0 {\n\t\treturn nil\n\t}\n\n\tdefer r.reportStatus(err, er)\n\t// NOTE: Since the restore EtcdCluster is created with the same name as the EtcdClusterRef,\n\t// the seed member will send a request of the form /backup/<cluster-name> to the backup server.\n\t// The EtcdRestore CR name must be the same as the EtcdCluster name in order for the backup server\n\t// to successfully lookup the EtcdRestore CR associated with this <cluster-name>.\n\tif er.Name != er.Spec.EtcdCluster.Name {\n\t\terr = fmt.Errorf(\"failed to handle restore CR: EtcdRestore CR name(%v) must be the same as EtcdCluster name(%v)\", er.Name, er.Spec.EtcdCluster.Name)\n\t\treturn err\n\t}\n\terr = r.prepareSeed(er)\n\treturn err\n}\n\nfunc (r *Restore) reportStatus(rerr error, er *api.EtcdRestore) {\n\tif rerr != nil {\n\t\ter.Status.Succeeded = false\n\t\ter.Status.Reason = rerr.Error()\n\t} else {\n\t\ter.Status.Succeeded = true\n\t}\n\t_, err := r.etcdCRCli.EtcdV1beta2().EtcdRestores(r.namespace).Update(er)\n\tif err != nil {\n\t\tr.logger.Warningf(\"failed to update status of restore CR %v : (%v)\", er.Name, err)\n\t}\n}\n\nfunc (r *Restore) handleErr(err error, key interface{}) {\n\tif err == nil {\n\t\t// Forget about the #AddRateLimited history of the key on every successful synchronization.\n\t\t// This ensures that future processing of updates for this key is not delayed because of\n\t\t// an outdated error history.\n\t\tr.queue.Forget(key)\n\t\treturn\n\t}\n\n\t// This controller retries maxRetries times if something goes wrong. After that, it stops trying.\n\tif r.queue.NumRequeues(key) < maxRetries {\n\t\tr.logger.Errorf(\"error syncing restore request (%v): %v\", key, err)\n\n\t\t// Re-enqueue the key rate limited. Based on the rate limiter on the\n\t\t// queue and the re-enqueue history, the key will be processed later again.\n\t\tr.queue.AddRateLimited(key)\n\t\treturn\n\t}\n\n\tr.queue.Forget(key)\n\t// Report that, even after several retries, we could not successfully process this key\n\tr.logger.Infof(\"dropping restore request (%v) out of the queue: %v\", key, err)\n}\n\n// prepareSeed does the following:\n// - fetches and deletes the reference EtcdCluster CR\n// - creates new EtcdCluster CR with same metadata and spec as the reference CR\n// - and spec.paused=true and status.phase=\"Running\"\n//  - spec.paused=true: keep operator from touching membership\n// \t- status.phase=Running:\n//  \t1. expect operator to setup the services\n//  \t2. make operator ignore the \"create seed member\" phase\n// - create seed member that would restore data from backup\n// \t- ownerRef to above EtcdCluster CR\n// - update EtcdCluster CR spec.paused=false\n// \t- etcd operator should pick up the membership and scale the etcd cluster\nfunc (r *Restore) prepareSeed(er *api.EtcdRestore) (err error) {\n\tdefer func() {\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"prepare seed failed: %v\", err)\n\t\t}\n\t}()\n\n\t// Fetch the reference EtcdCluster\n\tecRef := er.Spec.EtcdCluster\n\tec, err := r.etcdCRCli.EtcdV1beta2().EtcdClusters(r.namespace).Get(ecRef.Name, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get reference EtcdCluster(%s/%s): %v\", r.namespace, ecRef.Name, err)\n\t}\n\tif err := ec.Spec.Validate(); err != nil {\n\t\treturn fmt.Errorf(\"invalid cluster spec: %v\", err)\n\t}\n\n\t// Delete reference EtcdCluster\n\terr = r.etcdCRCli.EtcdV1beta2().EtcdClusters(r.namespace).Delete(ecRef.Name, &metav1.DeleteOptions{})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to delete reference EtcdCluster (%s/%s): %v\", r.namespace, ecRef.Name, err)\n\t}\n\t// Need to delete etcd pods, etc. completely before creating new cluster.\n\tr.deleteClusterResourcesCompletely(ecRef.Name)\n\n\t// Create the restored EtcdCluster with the same metadata and spec as reference EtcdCluster\n\tclusterName := ecRef.Name\n\tec = &api.EtcdCluster{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:            clusterName,\n\t\t\tLabels:          ec.ObjectMeta.Labels,\n\t\t\tAnnotations:     ec.ObjectMeta.Annotations,\n\t\t\tOwnerReferences: ec.ObjectMeta.OwnerReferences,\n\t\t},\n\t\tSpec: ec.Spec,\n\t}\n\n\tec.Spec.Paused = true\n\tec.Status.Phase = api.ClusterPhaseRunning\n\tec, err = r.etcdCRCli.EtcdV1beta2().EtcdClusters(r.namespace).Create(ec)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create restored EtcdCluster (%s/%s): %v\", r.namespace, clusterName, err)\n\t}\n\n\terr = r.createSeedMember(ec, r.mySvcAddr, clusterName, ec.AsOwner())\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create seed member for cluster (%s): %v\", clusterName, err)\n\t}\n\n\t// Retry updating the etcdcluster CR spec.paused=false. The etcd-operator will update the CR once so there needs to be a single retry in case of conflict\n\terr = retryutil.Retry(2, 1, func() (bool, error) {\n\t\tec, err = r.etcdCRCli.EtcdV1beta2().EtcdClusters(r.namespace).Get(clusterName, metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\tec.Spec.Paused = false\n\t\t_, err = r.etcdCRCli.EtcdV1beta2().EtcdClusters(r.namespace).Update(ec)\n\t\tif err != nil {\n\t\t\tif apierrors.IsConflict(err) {\n\t\t\t\treturn false, nil\n\t\t\t}\n\t\t\treturn false, err\n\t\t}\n\t\treturn true, nil\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to update etcdcluster CR to spec.paused=false: %v\", err)\n\t}\n\treturn nil\n}\n\nfunc (r *Restore) createSeedMember(ec *api.EtcdCluster, svcAddr, clusterName string, owner metav1.OwnerReference) error {\n\tm := &etcdutil.Member{\n\t\tName:         k8sutil.UniqueMemberName(clusterName),\n\t\tNamespace:    r.namespace,\n\t\tSecurePeer:   ec.Spec.TLS.IsSecurePeer(),\n\t\tSecureClient: ec.Spec.TLS.IsSecureClient(),\n\t}\n\tif ec.Spec.Pod != nil {\n\t\tm.ClusterDomain = ec.Spec.Pod.ClusterDomain\n\t}\n\tms := etcdutil.NewMemberSet(m)\n\tbackupURL := backupapi.BackupURLForRestore(\"http\", svcAddr, clusterName)\n\tec.SetDefaults()\n\tpod := k8sutil.NewSeedMemberPod(clusterName, ms, m, ec.Spec, owner, backupURL)\n\t_, err := r.kubecli.Core().Pods(r.namespace).Create(pod)\n\treturn err\n}\n\nfunc (r *Restore) deleteClusterResourcesCompletely(clusterName string) error {\n\t// Delete etcd pods\n\terr := r.kubecli.Core().Pods(r.namespace).Delete(clusterName, metav1.NewDeleteOptions(0))\n\tif err != nil && !k8sutil.IsKubernetesResourceNotFoundError(err) {\n\t\treturn fmt.Errorf(\"failed to delete cluster pods: %v\", err)\n\t}\n\n\terr = r.kubecli.Core().Services(r.namespace).Delete(clusterName, metav1.NewDeleteOptions(0))\n\tif err != nil && !k8sutil.IsKubernetesResourceNotFoundError(err) {\n\t\treturn fmt.Errorf(\"failed to delete cluster services: %v\", err)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/controller/util.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage controller\n\nimport (\n\t\"time\"\n)\n\n// panicTimer panics when it reaches the given duration.\ntype panicTimer struct {\n\td   time.Duration\n\tmsg string\n\tt   *time.Timer\n}\n\nfunc newPanicTimer(d time.Duration, msg string) *panicTimer {\n\treturn &panicTimer{\n\t\td:   d,\n\t\tmsg: msg,\n\t}\n}\n\nfunc (pt *panicTimer) start() {\n\tpt.t = time.AfterFunc(pt.d, func() {\n\t\tpanic(pt.msg)\n\t})\n}\n\n// stop stops the timer and resets the elapsed duration.\nfunc (pt *panicTimer) stop() {\n\tif pt.t != nil {\n\t\tpt.t.Stop()\n\t\tpt.t = nil\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/clientset/versioned/clientset.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by client-gen. DO NOT EDIT.\n\npackage versioned\n\nimport (\n\tetcdv1beta2 \"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned/typed/etcd/v1beta2\"\n\tdiscovery \"k8s.io/client-go/discovery\"\n\trest \"k8s.io/client-go/rest\"\n\tflowcontrol \"k8s.io/client-go/util/flowcontrol\"\n)\n\ntype Interface interface {\n\tDiscovery() discovery.DiscoveryInterface\n\tEtcdV1beta2() etcdv1beta2.EtcdV1beta2Interface\n\t// Deprecated: please explicitly pick a version if possible.\n\tEtcd() etcdv1beta2.EtcdV1beta2Interface\n}\n\n// Clientset contains the clients for groups. Each group has exactly one\n// version included in a Clientset.\ntype Clientset struct {\n\t*discovery.DiscoveryClient\n\tetcdV1beta2 *etcdv1beta2.EtcdV1beta2Client\n}\n\n// EtcdV1beta2 retrieves the EtcdV1beta2Client\nfunc (c *Clientset) EtcdV1beta2() etcdv1beta2.EtcdV1beta2Interface {\n\treturn c.etcdV1beta2\n}\n\n// Deprecated: Etcd retrieves the default version of EtcdClient.\n// Please explicitly pick a version.\nfunc (c *Clientset) Etcd() etcdv1beta2.EtcdV1beta2Interface {\n\treturn c.etcdV1beta2\n}\n\n// Discovery retrieves the DiscoveryClient\nfunc (c *Clientset) Discovery() discovery.DiscoveryInterface {\n\tif c == nil {\n\t\treturn nil\n\t}\n\treturn c.DiscoveryClient\n}\n\n// NewForConfig creates a new Clientset for the given config.\nfunc NewForConfig(c *rest.Config) (*Clientset, error) {\n\tconfigShallowCopy := *c\n\tif configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {\n\t\tconfigShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)\n\t}\n\tvar cs Clientset\n\tvar err error\n\tcs.etcdV1beta2, err = etcdv1beta2.NewForConfig(&configShallowCopy)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tcs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &cs, nil\n}\n\n// NewForConfigOrDie creates a new Clientset for the given config and\n// panics if there is an error in the config.\nfunc NewForConfigOrDie(c *rest.Config) *Clientset {\n\tvar cs Clientset\n\tcs.etcdV1beta2 = etcdv1beta2.NewForConfigOrDie(c)\n\n\tcs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)\n\treturn &cs\n}\n\n// New creates a new Clientset for the given RESTClient.\nfunc New(c rest.Interface) *Clientset {\n\tvar cs Clientset\n\tcs.etcdV1beta2 = etcdv1beta2.New(c)\n\n\tcs.DiscoveryClient = discovery.NewDiscoveryClient(c)\n\treturn &cs\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/clientset/versioned/doc.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by client-gen. DO NOT EDIT.\n\n// This package has the automatically generated clientset.\npackage versioned\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/clientset/versioned/fake/clientset_generated.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by client-gen. DO NOT EDIT.\n\npackage fake\n\nimport (\n\tclientset \"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned\"\n\tetcdv1beta2 \"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned/typed/etcd/v1beta2\"\n\tfakeetcdv1beta2 \"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned/typed/etcd/v1beta2/fake\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/watch\"\n\t\"k8s.io/client-go/discovery\"\n\tfakediscovery \"k8s.io/client-go/discovery/fake\"\n\t\"k8s.io/client-go/testing\"\n)\n\n// NewSimpleClientset returns a clientset that will respond with the provided objects.\n// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,\n// without applying any validations and/or defaults. It shouldn't be considered a replacement\n// for a real clientset and is mostly useful in simple unit tests.\nfunc NewSimpleClientset(objects ...runtime.Object) *Clientset {\n\to := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())\n\tfor _, obj := range objects {\n\t\tif err := o.Add(obj); err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t}\n\n\tcs := &Clientset{}\n\tcs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}\n\tcs.AddReactor(\"*\", \"*\", testing.ObjectReaction(o))\n\tcs.AddWatchReactor(\"*\", func(action testing.Action) (handled bool, ret watch.Interface, err error) {\n\t\tgvr := action.GetResource()\n\t\tns := action.GetNamespace()\n\t\twatch, err := o.Watch(gvr, ns)\n\t\tif err != nil {\n\t\t\treturn false, nil, err\n\t\t}\n\t\treturn true, watch, nil\n\t})\n\n\treturn cs\n}\n\n// Clientset implements clientset.Interface. Meant to be embedded into a\n// struct to get a default implementation. This makes faking out just the method\n// you want to test easier.\ntype Clientset struct {\n\ttesting.Fake\n\tdiscovery *fakediscovery.FakeDiscovery\n}\n\nfunc (c *Clientset) Discovery() discovery.DiscoveryInterface {\n\treturn c.discovery\n}\n\nvar _ clientset.Interface = &Clientset{}\n\n// EtcdV1beta2 retrieves the EtcdV1beta2Client\nfunc (c *Clientset) EtcdV1beta2() etcdv1beta2.EtcdV1beta2Interface {\n\treturn &fakeetcdv1beta2.FakeEtcdV1beta2{Fake: &c.Fake}\n}\n\n// Etcd retrieves the EtcdV1beta2Client\nfunc (c *Clientset) Etcd() etcdv1beta2.EtcdV1beta2Interface {\n\treturn &fakeetcdv1beta2.FakeEtcdV1beta2{Fake: &c.Fake}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/clientset/versioned/fake/doc.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by client-gen. DO NOT EDIT.\n\n// This package has the automatically generated fake clientset.\npackage fake\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/clientset/versioned/fake/register.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by client-gen. DO NOT EDIT.\n\npackage fake\n\nimport (\n\tetcdv1beta2 \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n\tschema \"k8s.io/apimachinery/pkg/runtime/schema\"\n\tserializer \"k8s.io/apimachinery/pkg/runtime/serializer\"\n\tutilruntime \"k8s.io/apimachinery/pkg/util/runtime\"\n)\n\nvar scheme = runtime.NewScheme()\nvar codecs = serializer.NewCodecFactory(scheme)\nvar parameterCodec = runtime.NewParameterCodec(scheme)\nvar localSchemeBuilder = runtime.SchemeBuilder{\n\tetcdv1beta2.AddToScheme,\n}\n\n// AddToScheme adds all types of this clientset into the given scheme. This allows composition\n// of clientsets, like in:\n//\n//   import (\n//     \"k8s.io/client-go/kubernetes\"\n//     clientsetscheme \"k8s.io/client-go/kubernetes/scheme\"\n//     aggregatorclientsetscheme \"k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme\"\n//   )\n//\n//   kclientset, _ := kubernetes.NewForConfig(c)\n//   _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)\n//\n// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types\n// correctly.\nvar AddToScheme = localSchemeBuilder.AddToScheme\n\nfunc init() {\n\tv1.AddToGroupVersion(scheme, schema.GroupVersion{Version: \"v1\"})\n\tutilruntime.Must(AddToScheme(scheme))\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/clientset/versioned/scheme/doc.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by client-gen. DO NOT EDIT.\n\n// This package contains the scheme of the automatically generated clientset.\npackage scheme\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/clientset/versioned/scheme/register.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by client-gen. DO NOT EDIT.\n\npackage scheme\n\nimport (\n\tetcdv1beta2 \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n\tschema \"k8s.io/apimachinery/pkg/runtime/schema\"\n\tserializer \"k8s.io/apimachinery/pkg/runtime/serializer\"\n\tutilruntime \"k8s.io/apimachinery/pkg/util/runtime\"\n)\n\nvar Scheme = runtime.NewScheme()\nvar Codecs = serializer.NewCodecFactory(Scheme)\nvar ParameterCodec = runtime.NewParameterCodec(Scheme)\nvar localSchemeBuilder = runtime.SchemeBuilder{\n\tetcdv1beta2.AddToScheme,\n}\n\n// AddToScheme adds all types of this clientset into the given scheme. This allows composition\n// of clientsets, like in:\n//\n//   import (\n//     \"k8s.io/client-go/kubernetes\"\n//     clientsetscheme \"k8s.io/client-go/kubernetes/scheme\"\n//     aggregatorclientsetscheme \"k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme\"\n//   )\n//\n//   kclientset, _ := kubernetes.NewForConfig(c)\n//   _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)\n//\n// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types\n// correctly.\nvar AddToScheme = localSchemeBuilder.AddToScheme\n\nfunc init() {\n\tv1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: \"v1\"})\n\tutilruntime.Must(AddToScheme(Scheme))\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/clientset/versioned/typed/etcd/v1beta2/doc.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by client-gen. DO NOT EDIT.\n\n// This package has the automatically generated typed clients.\npackage v1beta2\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/clientset/versioned/typed/etcd/v1beta2/etcd_client.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by client-gen. DO NOT EDIT.\n\npackage v1beta2\n\nimport (\n\tv1beta2 \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned/scheme\"\n\tserializer \"k8s.io/apimachinery/pkg/runtime/serializer\"\n\trest \"k8s.io/client-go/rest\"\n)\n\ntype EtcdV1beta2Interface interface {\n\tRESTClient() rest.Interface\n\tEtcdBackupsGetter\n\tEtcdClustersGetter\n\tEtcdRestoresGetter\n}\n\n// EtcdV1beta2Client is used to interact with features provided by the etcd.database.coreos.com group.\ntype EtcdV1beta2Client struct {\n\trestClient rest.Interface\n}\n\nfunc (c *EtcdV1beta2Client) EtcdBackups(namespace string) EtcdBackupInterface {\n\treturn newEtcdBackups(c, namespace)\n}\n\nfunc (c *EtcdV1beta2Client) EtcdClusters(namespace string) EtcdClusterInterface {\n\treturn newEtcdClusters(c, namespace)\n}\n\nfunc (c *EtcdV1beta2Client) EtcdRestores(namespace string) EtcdRestoreInterface {\n\treturn newEtcdRestores(c, namespace)\n}\n\n// NewForConfig creates a new EtcdV1beta2Client for the given config.\nfunc NewForConfig(c *rest.Config) (*EtcdV1beta2Client, error) {\n\tconfig := *c\n\tif err := setConfigDefaults(&config); err != nil {\n\t\treturn nil, err\n\t}\n\tclient, err := rest.RESTClientFor(&config)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &EtcdV1beta2Client{client}, nil\n}\n\n// NewForConfigOrDie creates a new EtcdV1beta2Client for the given config and\n// panics if there is an error in the config.\nfunc NewForConfigOrDie(c *rest.Config) *EtcdV1beta2Client {\n\tclient, err := NewForConfig(c)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn client\n}\n\n// New creates a new EtcdV1beta2Client for the given RESTClient.\nfunc New(c rest.Interface) *EtcdV1beta2Client {\n\treturn &EtcdV1beta2Client{c}\n}\n\nfunc setConfigDefaults(config *rest.Config) error {\n\tgv := v1beta2.SchemeGroupVersion\n\tconfig.GroupVersion = &gv\n\tconfig.APIPath = \"/apis\"\n\tconfig.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}\n\n\tif config.UserAgent == \"\" {\n\t\tconfig.UserAgent = rest.DefaultKubernetesUserAgent()\n\t}\n\n\treturn nil\n}\n\n// RESTClient returns a RESTClient that is used to communicate\n// with API server by this client implementation.\nfunc (c *EtcdV1beta2Client) RESTClient() rest.Interface {\n\tif c == nil {\n\t\treturn nil\n\t}\n\treturn c.restClient\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/clientset/versioned/typed/etcd/v1beta2/etcdbackup.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by client-gen. DO NOT EDIT.\n\npackage v1beta2\n\nimport (\n\tv1beta2 \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\tscheme \"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned/scheme\"\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\ttypes \"k8s.io/apimachinery/pkg/types\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\trest \"k8s.io/client-go/rest\"\n)\n\n// EtcdBackupsGetter has a method to return a EtcdBackupInterface.\n// A group's client should implement this interface.\ntype EtcdBackupsGetter interface {\n\tEtcdBackups(namespace string) EtcdBackupInterface\n}\n\n// EtcdBackupInterface has methods to work with EtcdBackup resources.\ntype EtcdBackupInterface interface {\n\tCreate(*v1beta2.EtcdBackup) (*v1beta2.EtcdBackup, error)\n\tUpdate(*v1beta2.EtcdBackup) (*v1beta2.EtcdBackup, error)\n\tUpdateStatus(*v1beta2.EtcdBackup) (*v1beta2.EtcdBackup, error)\n\tDelete(name string, options *v1.DeleteOptions) error\n\tDeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error\n\tGet(name string, options v1.GetOptions) (*v1beta2.EtcdBackup, error)\n\tList(opts v1.ListOptions) (*v1beta2.EtcdBackupList, error)\n\tWatch(opts v1.ListOptions) (watch.Interface, error)\n\tPatch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta2.EtcdBackup, err error)\n\tEtcdBackupExpansion\n}\n\n// etcdBackups implements EtcdBackupInterface\ntype etcdBackups struct {\n\tclient rest.Interface\n\tns     string\n}\n\n// newEtcdBackups returns a EtcdBackups\nfunc newEtcdBackups(c *EtcdV1beta2Client, namespace string) *etcdBackups {\n\treturn &etcdBackups{\n\t\tclient: c.RESTClient(),\n\t\tns:     namespace,\n\t}\n}\n\n// Get takes name of the etcdBackup, and returns the corresponding etcdBackup object, and an error if there is any.\nfunc (c *etcdBackups) Get(name string, options v1.GetOptions) (result *v1beta2.EtcdBackup, err error) {\n\tresult = &v1beta2.EtcdBackup{}\n\terr = c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdbackups\").\n\t\tName(name).\n\t\tVersionedParams(&options, scheme.ParameterCodec).\n\t\tDo().\n\t\tInto(result)\n\treturn\n}\n\n// List takes label and field selectors, and returns the list of EtcdBackups that match those selectors.\nfunc (c *etcdBackups) List(opts v1.ListOptions) (result *v1beta2.EtcdBackupList, err error) {\n\tresult = &v1beta2.EtcdBackupList{}\n\terr = c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdbackups\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tDo().\n\t\tInto(result)\n\treturn\n}\n\n// Watch returns a watch.Interface that watches the requested etcdBackups.\nfunc (c *etcdBackups) Watch(opts v1.ListOptions) (watch.Interface, error) {\n\topts.Watch = true\n\treturn c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdbackups\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tWatch()\n}\n\n// Create takes the representation of a etcdBackup and creates it.  Returns the server's representation of the etcdBackup, and an error, if there is any.\nfunc (c *etcdBackups) Create(etcdBackup *v1beta2.EtcdBackup) (result *v1beta2.EtcdBackup, err error) {\n\tresult = &v1beta2.EtcdBackup{}\n\terr = c.client.Post().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdbackups\").\n\t\tBody(etcdBackup).\n\t\tDo().\n\t\tInto(result)\n\treturn\n}\n\n// Update takes the representation of a etcdBackup and updates it. Returns the server's representation of the etcdBackup, and an error, if there is any.\nfunc (c *etcdBackups) Update(etcdBackup *v1beta2.EtcdBackup) (result *v1beta2.EtcdBackup, err error) {\n\tresult = &v1beta2.EtcdBackup{}\n\terr = c.client.Put().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdbackups\").\n\t\tName(etcdBackup.Name).\n\t\tBody(etcdBackup).\n\t\tDo().\n\t\tInto(result)\n\treturn\n}\n\n// UpdateStatus was generated because the type contains a Status member.\n// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().\n\nfunc (c *etcdBackups) UpdateStatus(etcdBackup *v1beta2.EtcdBackup) (result *v1beta2.EtcdBackup, err error) {\n\tresult = &v1beta2.EtcdBackup{}\n\terr = c.client.Put().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdbackups\").\n\t\tName(etcdBackup.Name).\n\t\tSubResource(\"status\").\n\t\tBody(etcdBackup).\n\t\tDo().\n\t\tInto(result)\n\treturn\n}\n\n// Delete takes name of the etcdBackup and deletes it. Returns an error if one occurs.\nfunc (c *etcdBackups) Delete(name string, options *v1.DeleteOptions) error {\n\treturn c.client.Delete().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdbackups\").\n\t\tName(name).\n\t\tBody(options).\n\t\tDo().\n\t\tError()\n}\n\n// DeleteCollection deletes a collection of objects.\nfunc (c *etcdBackups) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {\n\treturn c.client.Delete().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdbackups\").\n\t\tVersionedParams(&listOptions, scheme.ParameterCodec).\n\t\tBody(options).\n\t\tDo().\n\t\tError()\n}\n\n// Patch applies the patch and returns the patched etcdBackup.\nfunc (c *etcdBackups) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta2.EtcdBackup, err error) {\n\tresult = &v1beta2.EtcdBackup{}\n\terr = c.client.Patch(pt).\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdbackups\").\n\t\tSubResource(subresources...).\n\t\tName(name).\n\t\tBody(data).\n\t\tDo().\n\t\tInto(result)\n\treturn\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/clientset/versioned/typed/etcd/v1beta2/etcdcluster.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by client-gen. DO NOT EDIT.\n\npackage v1beta2\n\nimport (\n\tv1beta2 \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\tscheme \"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned/scheme\"\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\ttypes \"k8s.io/apimachinery/pkg/types\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\trest \"k8s.io/client-go/rest\"\n)\n\n// EtcdClustersGetter has a method to return a EtcdClusterInterface.\n// A group's client should implement this interface.\ntype EtcdClustersGetter interface {\n\tEtcdClusters(namespace string) EtcdClusterInterface\n}\n\n// EtcdClusterInterface has methods to work with EtcdCluster resources.\ntype EtcdClusterInterface interface {\n\tCreate(*v1beta2.EtcdCluster) (*v1beta2.EtcdCluster, error)\n\tUpdate(*v1beta2.EtcdCluster) (*v1beta2.EtcdCluster, error)\n\tUpdateStatus(*v1beta2.EtcdCluster) (*v1beta2.EtcdCluster, error)\n\tDelete(name string, options *v1.DeleteOptions) error\n\tDeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error\n\tGet(name string, options v1.GetOptions) (*v1beta2.EtcdCluster, error)\n\tList(opts v1.ListOptions) (*v1beta2.EtcdClusterList, error)\n\tWatch(opts v1.ListOptions) (watch.Interface, error)\n\tPatch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta2.EtcdCluster, err error)\n\tEtcdClusterExpansion\n}\n\n// etcdClusters implements EtcdClusterInterface\ntype etcdClusters struct {\n\tclient rest.Interface\n\tns     string\n}\n\n// newEtcdClusters returns a EtcdClusters\nfunc newEtcdClusters(c *EtcdV1beta2Client, namespace string) *etcdClusters {\n\treturn &etcdClusters{\n\t\tclient: c.RESTClient(),\n\t\tns:     namespace,\n\t}\n}\n\n// Get takes name of the etcdCluster, and returns the corresponding etcdCluster object, and an error if there is any.\nfunc (c *etcdClusters) Get(name string, options v1.GetOptions) (result *v1beta2.EtcdCluster, err error) {\n\tresult = &v1beta2.EtcdCluster{}\n\terr = c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tName(name).\n\t\tVersionedParams(&options, scheme.ParameterCodec).\n\t\tDo().\n\t\tInto(result)\n\treturn\n}\n\n// List takes label and field selectors, and returns the list of EtcdClusters that match those selectors.\nfunc (c *etcdClusters) List(opts v1.ListOptions) (result *v1beta2.EtcdClusterList, err error) {\n\tresult = &v1beta2.EtcdClusterList{}\n\terr = c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tDo().\n\t\tInto(result)\n\treturn\n}\n\n// Watch returns a watch.Interface that watches the requested etcdClusters.\nfunc (c *etcdClusters) Watch(opts v1.ListOptions) (watch.Interface, error) {\n\topts.Watch = true\n\treturn c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tWatch()\n}\n\n// Create takes the representation of a etcdCluster and creates it.  Returns the server's representation of the etcdCluster, and an error, if there is any.\nfunc (c *etcdClusters) Create(etcdCluster *v1beta2.EtcdCluster) (result *v1beta2.EtcdCluster, err error) {\n\tresult = &v1beta2.EtcdCluster{}\n\terr = c.client.Post().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tBody(etcdCluster).\n\t\tDo().\n\t\tInto(result)\n\treturn\n}\n\n// Update takes the representation of a etcdCluster and updates it. Returns the server's representation of the etcdCluster, and an error, if there is any.\nfunc (c *etcdClusters) Update(etcdCluster *v1beta2.EtcdCluster) (result *v1beta2.EtcdCluster, err error) {\n\tresult = &v1beta2.EtcdCluster{}\n\terr = c.client.Put().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tName(etcdCluster.Name).\n\t\tBody(etcdCluster).\n\t\tDo().\n\t\tInto(result)\n\treturn\n}\n\n// UpdateStatus was generated because the type contains a Status member.\n// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().\n\nfunc (c *etcdClusters) UpdateStatus(etcdCluster *v1beta2.EtcdCluster) (result *v1beta2.EtcdCluster, err error) {\n\tresult = &v1beta2.EtcdCluster{}\n\terr = c.client.Put().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tName(etcdCluster.Name).\n\t\tSubResource(\"status\").\n\t\tBody(etcdCluster).\n\t\tDo().\n\t\tInto(result)\n\treturn\n}\n\n// Delete takes name of the etcdCluster and deletes it. Returns an error if one occurs.\nfunc (c *etcdClusters) Delete(name string, options *v1.DeleteOptions) error {\n\treturn c.client.Delete().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tName(name).\n\t\tBody(options).\n\t\tDo().\n\t\tError()\n}\n\n// DeleteCollection deletes a collection of objects.\nfunc (c *etcdClusters) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {\n\treturn c.client.Delete().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tVersionedParams(&listOptions, scheme.ParameterCodec).\n\t\tBody(options).\n\t\tDo().\n\t\tError()\n}\n\n// Patch applies the patch and returns the patched etcdCluster.\nfunc (c *etcdClusters) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta2.EtcdCluster, err error) {\n\tresult = &v1beta2.EtcdCluster{}\n\terr = c.client.Patch(pt).\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdclusters\").\n\t\tSubResource(subresources...).\n\t\tName(name).\n\t\tBody(data).\n\t\tDo().\n\t\tInto(result)\n\treturn\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/clientset/versioned/typed/etcd/v1beta2/etcdrestore.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by client-gen. DO NOT EDIT.\n\npackage v1beta2\n\nimport (\n\tv1beta2 \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\tscheme \"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned/scheme\"\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\ttypes \"k8s.io/apimachinery/pkg/types\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\trest \"k8s.io/client-go/rest\"\n)\n\n// EtcdRestoresGetter has a method to return a EtcdRestoreInterface.\n// A group's client should implement this interface.\ntype EtcdRestoresGetter interface {\n\tEtcdRestores(namespace string) EtcdRestoreInterface\n}\n\n// EtcdRestoreInterface has methods to work with EtcdRestore resources.\ntype EtcdRestoreInterface interface {\n\tCreate(*v1beta2.EtcdRestore) (*v1beta2.EtcdRestore, error)\n\tUpdate(*v1beta2.EtcdRestore) (*v1beta2.EtcdRestore, error)\n\tUpdateStatus(*v1beta2.EtcdRestore) (*v1beta2.EtcdRestore, error)\n\tDelete(name string, options *v1.DeleteOptions) error\n\tDeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error\n\tGet(name string, options v1.GetOptions) (*v1beta2.EtcdRestore, error)\n\tList(opts v1.ListOptions) (*v1beta2.EtcdRestoreList, error)\n\tWatch(opts v1.ListOptions) (watch.Interface, error)\n\tPatch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta2.EtcdRestore, err error)\n\tEtcdRestoreExpansion\n}\n\n// etcdRestores implements EtcdRestoreInterface\ntype etcdRestores struct {\n\tclient rest.Interface\n\tns     string\n}\n\n// newEtcdRestores returns a EtcdRestores\nfunc newEtcdRestores(c *EtcdV1beta2Client, namespace string) *etcdRestores {\n\treturn &etcdRestores{\n\t\tclient: c.RESTClient(),\n\t\tns:     namespace,\n\t}\n}\n\n// Get takes name of the etcdRestore, and returns the corresponding etcdRestore object, and an error if there is any.\nfunc (c *etcdRestores) Get(name string, options v1.GetOptions) (result *v1beta2.EtcdRestore, err error) {\n\tresult = &v1beta2.EtcdRestore{}\n\terr = c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdrestores\").\n\t\tName(name).\n\t\tVersionedParams(&options, scheme.ParameterCodec).\n\t\tDo().\n\t\tInto(result)\n\treturn\n}\n\n// List takes label and field selectors, and returns the list of EtcdRestores that match those selectors.\nfunc (c *etcdRestores) List(opts v1.ListOptions) (result *v1beta2.EtcdRestoreList, err error) {\n\tresult = &v1beta2.EtcdRestoreList{}\n\terr = c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdrestores\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tDo().\n\t\tInto(result)\n\treturn\n}\n\n// Watch returns a watch.Interface that watches the requested etcdRestores.\nfunc (c *etcdRestores) Watch(opts v1.ListOptions) (watch.Interface, error) {\n\topts.Watch = true\n\treturn c.client.Get().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdrestores\").\n\t\tVersionedParams(&opts, scheme.ParameterCodec).\n\t\tWatch()\n}\n\n// Create takes the representation of a etcdRestore and creates it.  Returns the server's representation of the etcdRestore, and an error, if there is any.\nfunc (c *etcdRestores) Create(etcdRestore *v1beta2.EtcdRestore) (result *v1beta2.EtcdRestore, err error) {\n\tresult = &v1beta2.EtcdRestore{}\n\terr = c.client.Post().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdrestores\").\n\t\tBody(etcdRestore).\n\t\tDo().\n\t\tInto(result)\n\treturn\n}\n\n// Update takes the representation of a etcdRestore and updates it. Returns the server's representation of the etcdRestore, and an error, if there is any.\nfunc (c *etcdRestores) Update(etcdRestore *v1beta2.EtcdRestore) (result *v1beta2.EtcdRestore, err error) {\n\tresult = &v1beta2.EtcdRestore{}\n\terr = c.client.Put().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdrestores\").\n\t\tName(etcdRestore.Name).\n\t\tBody(etcdRestore).\n\t\tDo().\n\t\tInto(result)\n\treturn\n}\n\n// UpdateStatus was generated because the type contains a Status member.\n// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().\n\nfunc (c *etcdRestores) UpdateStatus(etcdRestore *v1beta2.EtcdRestore) (result *v1beta2.EtcdRestore, err error) {\n\tresult = &v1beta2.EtcdRestore{}\n\terr = c.client.Put().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdrestores\").\n\t\tName(etcdRestore.Name).\n\t\tSubResource(\"status\").\n\t\tBody(etcdRestore).\n\t\tDo().\n\t\tInto(result)\n\treturn\n}\n\n// Delete takes name of the etcdRestore and deletes it. Returns an error if one occurs.\nfunc (c *etcdRestores) Delete(name string, options *v1.DeleteOptions) error {\n\treturn c.client.Delete().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdrestores\").\n\t\tName(name).\n\t\tBody(options).\n\t\tDo().\n\t\tError()\n}\n\n// DeleteCollection deletes a collection of objects.\nfunc (c *etcdRestores) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {\n\treturn c.client.Delete().\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdrestores\").\n\t\tVersionedParams(&listOptions, scheme.ParameterCodec).\n\t\tBody(options).\n\t\tDo().\n\t\tError()\n}\n\n// Patch applies the patch and returns the patched etcdRestore.\nfunc (c *etcdRestores) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta2.EtcdRestore, err error) {\n\tresult = &v1beta2.EtcdRestore{}\n\terr = c.client.Patch(pt).\n\t\tNamespace(c.ns).\n\t\tResource(\"etcdrestores\").\n\t\tSubResource(subresources...).\n\t\tName(name).\n\t\tBody(data).\n\t\tDo().\n\t\tInto(result)\n\treturn\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/clientset/versioned/typed/etcd/v1beta2/fake/doc.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by client-gen. DO NOT EDIT.\n\n// Package fake has the automatically generated clients.\npackage fake\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/clientset/versioned/typed/etcd/v1beta2/fake/fake_etcd_client.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by client-gen. DO NOT EDIT.\n\npackage fake\n\nimport (\n\tv1beta2 \"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned/typed/etcd/v1beta2\"\n\trest \"k8s.io/client-go/rest\"\n\ttesting \"k8s.io/client-go/testing\"\n)\n\ntype FakeEtcdV1beta2 struct {\n\t*testing.Fake\n}\n\nfunc (c *FakeEtcdV1beta2) EtcdBackups(namespace string) v1beta2.EtcdBackupInterface {\n\treturn &FakeEtcdBackups{c, namespace}\n}\n\nfunc (c *FakeEtcdV1beta2) EtcdClusters(namespace string) v1beta2.EtcdClusterInterface {\n\treturn &FakeEtcdClusters{c, namespace}\n}\n\nfunc (c *FakeEtcdV1beta2) EtcdRestores(namespace string) v1beta2.EtcdRestoreInterface {\n\treturn &FakeEtcdRestores{c, namespace}\n}\n\n// RESTClient returns a RESTClient that is used to communicate\n// with API server by this client implementation.\nfunc (c *FakeEtcdV1beta2) RESTClient() rest.Interface {\n\tvar ret *rest.RESTClient\n\treturn ret\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/clientset/versioned/typed/etcd/v1beta2/fake/fake_etcdbackup.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by client-gen. DO NOT EDIT.\n\npackage fake\n\nimport (\n\tv1beta2 \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\tlabels \"k8s.io/apimachinery/pkg/labels\"\n\tschema \"k8s.io/apimachinery/pkg/runtime/schema\"\n\ttypes \"k8s.io/apimachinery/pkg/types\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\ttesting \"k8s.io/client-go/testing\"\n)\n\n// FakeEtcdBackups implements EtcdBackupInterface\ntype FakeEtcdBackups struct {\n\tFake *FakeEtcdV1beta2\n\tns   string\n}\n\nvar etcdbackupsResource = schema.GroupVersionResource{Group: \"etcd.database.coreos.com\", Version: \"v1beta2\", Resource: \"etcdbackups\"}\n\nvar etcdbackupsKind = schema.GroupVersionKind{Group: \"etcd.database.coreos.com\", Version: \"v1beta2\", Kind: \"EtcdBackup\"}\n\n// Get takes name of the etcdBackup, and returns the corresponding etcdBackup object, and an error if there is any.\nfunc (c *FakeEtcdBackups) Get(name string, options v1.GetOptions) (result *v1beta2.EtcdBackup, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewGetAction(etcdbackupsResource, c.ns, name), &v1beta2.EtcdBackup{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1beta2.EtcdBackup), err\n}\n\n// List takes label and field selectors, and returns the list of EtcdBackups that match those selectors.\nfunc (c *FakeEtcdBackups) List(opts v1.ListOptions) (result *v1beta2.EtcdBackupList, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewListAction(etcdbackupsResource, etcdbackupsKind, c.ns, opts), &v1beta2.EtcdBackupList{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\n\tlabel, _, _ := testing.ExtractFromListOptions(opts)\n\tif label == nil {\n\t\tlabel = labels.Everything()\n\t}\n\tlist := &v1beta2.EtcdBackupList{ListMeta: obj.(*v1beta2.EtcdBackupList).ListMeta}\n\tfor _, item := range obj.(*v1beta2.EtcdBackupList).Items {\n\t\tif label.Matches(labels.Set(item.Labels)) {\n\t\t\tlist.Items = append(list.Items, item)\n\t\t}\n\t}\n\treturn list, err\n}\n\n// Watch returns a watch.Interface that watches the requested etcdBackups.\nfunc (c *FakeEtcdBackups) Watch(opts v1.ListOptions) (watch.Interface, error) {\n\treturn c.Fake.\n\t\tInvokesWatch(testing.NewWatchAction(etcdbackupsResource, c.ns, opts))\n\n}\n\n// Create takes the representation of a etcdBackup and creates it.  Returns the server's representation of the etcdBackup, and an error, if there is any.\nfunc (c *FakeEtcdBackups) Create(etcdBackup *v1beta2.EtcdBackup) (result *v1beta2.EtcdBackup, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewCreateAction(etcdbackupsResource, c.ns, etcdBackup), &v1beta2.EtcdBackup{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1beta2.EtcdBackup), err\n}\n\n// Update takes the representation of a etcdBackup and updates it. Returns the server's representation of the etcdBackup, and an error, if there is any.\nfunc (c *FakeEtcdBackups) Update(etcdBackup *v1beta2.EtcdBackup) (result *v1beta2.EtcdBackup, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewUpdateAction(etcdbackupsResource, c.ns, etcdBackup), &v1beta2.EtcdBackup{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1beta2.EtcdBackup), err\n}\n\n// UpdateStatus was generated because the type contains a Status member.\n// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().\nfunc (c *FakeEtcdBackups) UpdateStatus(etcdBackup *v1beta2.EtcdBackup) (*v1beta2.EtcdBackup, error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewUpdateSubresourceAction(etcdbackupsResource, \"status\", c.ns, etcdBackup), &v1beta2.EtcdBackup{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1beta2.EtcdBackup), err\n}\n\n// Delete takes name of the etcdBackup and deletes it. Returns an error if one occurs.\nfunc (c *FakeEtcdBackups) Delete(name string, options *v1.DeleteOptions) error {\n\t_, err := c.Fake.\n\t\tInvokes(testing.NewDeleteAction(etcdbackupsResource, c.ns, name), &v1beta2.EtcdBackup{})\n\n\treturn err\n}\n\n// DeleteCollection deletes a collection of objects.\nfunc (c *FakeEtcdBackups) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {\n\taction := testing.NewDeleteCollectionAction(etcdbackupsResource, c.ns, listOptions)\n\n\t_, err := c.Fake.Invokes(action, &v1beta2.EtcdBackupList{})\n\treturn err\n}\n\n// Patch applies the patch and returns the patched etcdBackup.\nfunc (c *FakeEtcdBackups) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta2.EtcdBackup, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewPatchSubresourceAction(etcdbackupsResource, c.ns, name, data, subresources...), &v1beta2.EtcdBackup{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1beta2.EtcdBackup), err\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/clientset/versioned/typed/etcd/v1beta2/fake/fake_etcdcluster.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by client-gen. DO NOT EDIT.\n\npackage fake\n\nimport (\n\tv1beta2 \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\tlabels \"k8s.io/apimachinery/pkg/labels\"\n\tschema \"k8s.io/apimachinery/pkg/runtime/schema\"\n\ttypes \"k8s.io/apimachinery/pkg/types\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\ttesting \"k8s.io/client-go/testing\"\n)\n\n// FakeEtcdClusters implements EtcdClusterInterface\ntype FakeEtcdClusters struct {\n\tFake *FakeEtcdV1beta2\n\tns   string\n}\n\nvar etcdclustersResource = schema.GroupVersionResource{Group: \"etcd.database.coreos.com\", Version: \"v1beta2\", Resource: \"etcdclusters\"}\n\nvar etcdclustersKind = schema.GroupVersionKind{Group: \"etcd.database.coreos.com\", Version: \"v1beta2\", Kind: \"EtcdCluster\"}\n\n// Get takes name of the etcdCluster, and returns the corresponding etcdCluster object, and an error if there is any.\nfunc (c *FakeEtcdClusters) Get(name string, options v1.GetOptions) (result *v1beta2.EtcdCluster, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewGetAction(etcdclustersResource, c.ns, name), &v1beta2.EtcdCluster{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1beta2.EtcdCluster), err\n}\n\n// List takes label and field selectors, and returns the list of EtcdClusters that match those selectors.\nfunc (c *FakeEtcdClusters) List(opts v1.ListOptions) (result *v1beta2.EtcdClusterList, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewListAction(etcdclustersResource, etcdclustersKind, c.ns, opts), &v1beta2.EtcdClusterList{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\n\tlabel, _, _ := testing.ExtractFromListOptions(opts)\n\tif label == nil {\n\t\tlabel = labels.Everything()\n\t}\n\tlist := &v1beta2.EtcdClusterList{ListMeta: obj.(*v1beta2.EtcdClusterList).ListMeta}\n\tfor _, item := range obj.(*v1beta2.EtcdClusterList).Items {\n\t\tif label.Matches(labels.Set(item.Labels)) {\n\t\t\tlist.Items = append(list.Items, item)\n\t\t}\n\t}\n\treturn list, err\n}\n\n// Watch returns a watch.Interface that watches the requested etcdClusters.\nfunc (c *FakeEtcdClusters) Watch(opts v1.ListOptions) (watch.Interface, error) {\n\treturn c.Fake.\n\t\tInvokesWatch(testing.NewWatchAction(etcdclustersResource, c.ns, opts))\n\n}\n\n// Create takes the representation of a etcdCluster and creates it.  Returns the server's representation of the etcdCluster, and an error, if there is any.\nfunc (c *FakeEtcdClusters) Create(etcdCluster *v1beta2.EtcdCluster) (result *v1beta2.EtcdCluster, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewCreateAction(etcdclustersResource, c.ns, etcdCluster), &v1beta2.EtcdCluster{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1beta2.EtcdCluster), err\n}\n\n// Update takes the representation of a etcdCluster and updates it. Returns the server's representation of the etcdCluster, and an error, if there is any.\nfunc (c *FakeEtcdClusters) Update(etcdCluster *v1beta2.EtcdCluster) (result *v1beta2.EtcdCluster, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewUpdateAction(etcdclustersResource, c.ns, etcdCluster), &v1beta2.EtcdCluster{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1beta2.EtcdCluster), err\n}\n\n// UpdateStatus was generated because the type contains a Status member.\n// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().\nfunc (c *FakeEtcdClusters) UpdateStatus(etcdCluster *v1beta2.EtcdCluster) (*v1beta2.EtcdCluster, error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewUpdateSubresourceAction(etcdclustersResource, \"status\", c.ns, etcdCluster), &v1beta2.EtcdCluster{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1beta2.EtcdCluster), err\n}\n\n// Delete takes name of the etcdCluster and deletes it. Returns an error if one occurs.\nfunc (c *FakeEtcdClusters) Delete(name string, options *v1.DeleteOptions) error {\n\t_, err := c.Fake.\n\t\tInvokes(testing.NewDeleteAction(etcdclustersResource, c.ns, name), &v1beta2.EtcdCluster{})\n\n\treturn err\n}\n\n// DeleteCollection deletes a collection of objects.\nfunc (c *FakeEtcdClusters) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {\n\taction := testing.NewDeleteCollectionAction(etcdclustersResource, c.ns, listOptions)\n\n\t_, err := c.Fake.Invokes(action, &v1beta2.EtcdClusterList{})\n\treturn err\n}\n\n// Patch applies the patch and returns the patched etcdCluster.\nfunc (c *FakeEtcdClusters) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta2.EtcdCluster, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewPatchSubresourceAction(etcdclustersResource, c.ns, name, data, subresources...), &v1beta2.EtcdCluster{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1beta2.EtcdCluster), err\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/clientset/versioned/typed/etcd/v1beta2/fake/fake_etcdrestore.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by client-gen. DO NOT EDIT.\n\npackage fake\n\nimport (\n\tv1beta2 \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\tlabels \"k8s.io/apimachinery/pkg/labels\"\n\tschema \"k8s.io/apimachinery/pkg/runtime/schema\"\n\ttypes \"k8s.io/apimachinery/pkg/types\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\ttesting \"k8s.io/client-go/testing\"\n)\n\n// FakeEtcdRestores implements EtcdRestoreInterface\ntype FakeEtcdRestores struct {\n\tFake *FakeEtcdV1beta2\n\tns   string\n}\n\nvar etcdrestoresResource = schema.GroupVersionResource{Group: \"etcd.database.coreos.com\", Version: \"v1beta2\", Resource: \"etcdrestores\"}\n\nvar etcdrestoresKind = schema.GroupVersionKind{Group: \"etcd.database.coreos.com\", Version: \"v1beta2\", Kind: \"EtcdRestore\"}\n\n// Get takes name of the etcdRestore, and returns the corresponding etcdRestore object, and an error if there is any.\nfunc (c *FakeEtcdRestores) Get(name string, options v1.GetOptions) (result *v1beta2.EtcdRestore, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewGetAction(etcdrestoresResource, c.ns, name), &v1beta2.EtcdRestore{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1beta2.EtcdRestore), err\n}\n\n// List takes label and field selectors, and returns the list of EtcdRestores that match those selectors.\nfunc (c *FakeEtcdRestores) List(opts v1.ListOptions) (result *v1beta2.EtcdRestoreList, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewListAction(etcdrestoresResource, etcdrestoresKind, c.ns, opts), &v1beta2.EtcdRestoreList{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\n\tlabel, _, _ := testing.ExtractFromListOptions(opts)\n\tif label == nil {\n\t\tlabel = labels.Everything()\n\t}\n\tlist := &v1beta2.EtcdRestoreList{ListMeta: obj.(*v1beta2.EtcdRestoreList).ListMeta}\n\tfor _, item := range obj.(*v1beta2.EtcdRestoreList).Items {\n\t\tif label.Matches(labels.Set(item.Labels)) {\n\t\t\tlist.Items = append(list.Items, item)\n\t\t}\n\t}\n\treturn list, err\n}\n\n// Watch returns a watch.Interface that watches the requested etcdRestores.\nfunc (c *FakeEtcdRestores) Watch(opts v1.ListOptions) (watch.Interface, error) {\n\treturn c.Fake.\n\t\tInvokesWatch(testing.NewWatchAction(etcdrestoresResource, c.ns, opts))\n\n}\n\n// Create takes the representation of a etcdRestore and creates it.  Returns the server's representation of the etcdRestore, and an error, if there is any.\nfunc (c *FakeEtcdRestores) Create(etcdRestore *v1beta2.EtcdRestore) (result *v1beta2.EtcdRestore, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewCreateAction(etcdrestoresResource, c.ns, etcdRestore), &v1beta2.EtcdRestore{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1beta2.EtcdRestore), err\n}\n\n// Update takes the representation of a etcdRestore and updates it. Returns the server's representation of the etcdRestore, and an error, if there is any.\nfunc (c *FakeEtcdRestores) Update(etcdRestore *v1beta2.EtcdRestore) (result *v1beta2.EtcdRestore, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewUpdateAction(etcdrestoresResource, c.ns, etcdRestore), &v1beta2.EtcdRestore{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1beta2.EtcdRestore), err\n}\n\n// UpdateStatus was generated because the type contains a Status member.\n// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().\nfunc (c *FakeEtcdRestores) UpdateStatus(etcdRestore *v1beta2.EtcdRestore) (*v1beta2.EtcdRestore, error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewUpdateSubresourceAction(etcdrestoresResource, \"status\", c.ns, etcdRestore), &v1beta2.EtcdRestore{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1beta2.EtcdRestore), err\n}\n\n// Delete takes name of the etcdRestore and deletes it. Returns an error if one occurs.\nfunc (c *FakeEtcdRestores) Delete(name string, options *v1.DeleteOptions) error {\n\t_, err := c.Fake.\n\t\tInvokes(testing.NewDeleteAction(etcdrestoresResource, c.ns, name), &v1beta2.EtcdRestore{})\n\n\treturn err\n}\n\n// DeleteCollection deletes a collection of objects.\nfunc (c *FakeEtcdRestores) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {\n\taction := testing.NewDeleteCollectionAction(etcdrestoresResource, c.ns, listOptions)\n\n\t_, err := c.Fake.Invokes(action, &v1beta2.EtcdRestoreList{})\n\treturn err\n}\n\n// Patch applies the patch and returns the patched etcdRestore.\nfunc (c *FakeEtcdRestores) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta2.EtcdRestore, err error) {\n\tobj, err := c.Fake.\n\t\tInvokes(testing.NewPatchSubresourceAction(etcdrestoresResource, c.ns, name, data, subresources...), &v1beta2.EtcdRestore{})\n\n\tif obj == nil {\n\t\treturn nil, err\n\t}\n\treturn obj.(*v1beta2.EtcdRestore), err\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/clientset/versioned/typed/etcd/v1beta2/generated_expansion.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by client-gen. DO NOT EDIT.\n\npackage v1beta2\n\ntype EtcdBackupExpansion interface{}\n\ntype EtcdClusterExpansion interface{}\n\ntype EtcdRestoreExpansion interface{}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/informers/externalversions/etcd/interface.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by informer-gen. DO NOT EDIT.\n\npackage etcd\n\nimport (\n\tv1beta2 \"github.com/coreos/etcd-operator/pkg/generated/informers/externalversions/etcd/v1beta2\"\n\tinternalinterfaces \"github.com/coreos/etcd-operator/pkg/generated/informers/externalversions/internalinterfaces\"\n)\n\n// Interface provides access to each of this group's versions.\ntype Interface interface {\n\t// V1beta2 provides access to shared informers for resources in V1beta2.\n\tV1beta2() v1beta2.Interface\n}\n\ntype group struct {\n\tfactory          internalinterfaces.SharedInformerFactory\n\tnamespace        string\n\ttweakListOptions internalinterfaces.TweakListOptionsFunc\n}\n\n// New returns a new Interface.\nfunc New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {\n\treturn &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}\n}\n\n// V1beta2 returns a new v1beta2.Interface.\nfunc (g *group) V1beta2() v1beta2.Interface {\n\treturn v1beta2.New(g.factory, g.namespace, g.tweakListOptions)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/informers/externalversions/etcd/v1beta2/etcdbackup.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by informer-gen. DO NOT EDIT.\n\npackage v1beta2\n\nimport (\n\ttime \"time\"\n\n\tetcdv1beta2 \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\tversioned \"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned\"\n\tinternalinterfaces \"github.com/coreos/etcd-operator/pkg/generated/informers/externalversions/internalinterfaces\"\n\tv1beta2 \"github.com/coreos/etcd-operator/pkg/generated/listers/etcd/v1beta2\"\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\tcache \"k8s.io/client-go/tools/cache\"\n)\n\n// EtcdBackupInformer provides access to a shared informer and lister for\n// EtcdBackups.\ntype EtcdBackupInformer interface {\n\tInformer() cache.SharedIndexInformer\n\tLister() v1beta2.EtcdBackupLister\n}\n\ntype etcdBackupInformer struct {\n\tfactory          internalinterfaces.SharedInformerFactory\n\ttweakListOptions internalinterfaces.TweakListOptionsFunc\n\tnamespace        string\n}\n\n// NewEtcdBackupInformer constructs a new informer for EtcdBackup type.\n// Always prefer using an informer factory to get a shared informer instead of getting an independent\n// one. This reduces memory footprint and number of connections to the server.\nfunc NewEtcdBackupInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {\n\treturn NewFilteredEtcdBackupInformer(client, namespace, resyncPeriod, indexers, nil)\n}\n\n// NewFilteredEtcdBackupInformer constructs a new informer for EtcdBackup type.\n// Always prefer using an informer factory to get a shared informer instead of getting an independent\n// one. This reduces memory footprint and number of connections to the server.\nfunc NewFilteredEtcdBackupInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {\n\treturn cache.NewSharedIndexInformer(\n\t\t&cache.ListWatch{\n\t\t\tListFunc: func(options v1.ListOptions) (runtime.Object, error) {\n\t\t\t\tif tweakListOptions != nil {\n\t\t\t\t\ttweakListOptions(&options)\n\t\t\t\t}\n\t\t\t\treturn client.EtcdV1beta2().EtcdBackups(namespace).List(options)\n\t\t\t},\n\t\t\tWatchFunc: func(options v1.ListOptions) (watch.Interface, error) {\n\t\t\t\tif tweakListOptions != nil {\n\t\t\t\t\ttweakListOptions(&options)\n\t\t\t\t}\n\t\t\t\treturn client.EtcdV1beta2().EtcdBackups(namespace).Watch(options)\n\t\t\t},\n\t\t},\n\t\t&etcdv1beta2.EtcdBackup{},\n\t\tresyncPeriod,\n\t\tindexers,\n\t)\n}\n\nfunc (f *etcdBackupInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {\n\treturn NewFilteredEtcdBackupInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)\n}\n\nfunc (f *etcdBackupInformer) Informer() cache.SharedIndexInformer {\n\treturn f.factory.InformerFor(&etcdv1beta2.EtcdBackup{}, f.defaultInformer)\n}\n\nfunc (f *etcdBackupInformer) Lister() v1beta2.EtcdBackupLister {\n\treturn v1beta2.NewEtcdBackupLister(f.Informer().GetIndexer())\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/informers/externalversions/etcd/v1beta2/etcdcluster.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by informer-gen. DO NOT EDIT.\n\npackage v1beta2\n\nimport (\n\ttime \"time\"\n\n\tetcdv1beta2 \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\tversioned \"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned\"\n\tinternalinterfaces \"github.com/coreos/etcd-operator/pkg/generated/informers/externalversions/internalinterfaces\"\n\tv1beta2 \"github.com/coreos/etcd-operator/pkg/generated/listers/etcd/v1beta2\"\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\tcache \"k8s.io/client-go/tools/cache\"\n)\n\n// EtcdClusterInformer provides access to a shared informer and lister for\n// EtcdClusters.\ntype EtcdClusterInformer interface {\n\tInformer() cache.SharedIndexInformer\n\tLister() v1beta2.EtcdClusterLister\n}\n\ntype etcdClusterInformer struct {\n\tfactory          internalinterfaces.SharedInformerFactory\n\ttweakListOptions internalinterfaces.TweakListOptionsFunc\n\tnamespace        string\n}\n\n// NewEtcdClusterInformer constructs a new informer for EtcdCluster type.\n// Always prefer using an informer factory to get a shared informer instead of getting an independent\n// one. This reduces memory footprint and number of connections to the server.\nfunc NewEtcdClusterInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {\n\treturn NewFilteredEtcdClusterInformer(client, namespace, resyncPeriod, indexers, nil)\n}\n\n// NewFilteredEtcdClusterInformer constructs a new informer for EtcdCluster type.\n// Always prefer using an informer factory to get a shared informer instead of getting an independent\n// one. This reduces memory footprint and number of connections to the server.\nfunc NewFilteredEtcdClusterInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {\n\treturn cache.NewSharedIndexInformer(\n\t\t&cache.ListWatch{\n\t\t\tListFunc: func(options v1.ListOptions) (runtime.Object, error) {\n\t\t\t\tif tweakListOptions != nil {\n\t\t\t\t\ttweakListOptions(&options)\n\t\t\t\t}\n\t\t\t\treturn client.EtcdV1beta2().EtcdClusters(namespace).List(options)\n\t\t\t},\n\t\t\tWatchFunc: func(options v1.ListOptions) (watch.Interface, error) {\n\t\t\t\tif tweakListOptions != nil {\n\t\t\t\t\ttweakListOptions(&options)\n\t\t\t\t}\n\t\t\t\treturn client.EtcdV1beta2().EtcdClusters(namespace).Watch(options)\n\t\t\t},\n\t\t},\n\t\t&etcdv1beta2.EtcdCluster{},\n\t\tresyncPeriod,\n\t\tindexers,\n\t)\n}\n\nfunc (f *etcdClusterInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {\n\treturn NewFilteredEtcdClusterInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)\n}\n\nfunc (f *etcdClusterInformer) Informer() cache.SharedIndexInformer {\n\treturn f.factory.InformerFor(&etcdv1beta2.EtcdCluster{}, f.defaultInformer)\n}\n\nfunc (f *etcdClusterInformer) Lister() v1beta2.EtcdClusterLister {\n\treturn v1beta2.NewEtcdClusterLister(f.Informer().GetIndexer())\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/informers/externalversions/etcd/v1beta2/etcdrestore.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by informer-gen. DO NOT EDIT.\n\npackage v1beta2\n\nimport (\n\ttime \"time\"\n\n\tetcdv1beta2 \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\tversioned \"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned\"\n\tinternalinterfaces \"github.com/coreos/etcd-operator/pkg/generated/informers/externalversions/internalinterfaces\"\n\tv1beta2 \"github.com/coreos/etcd-operator/pkg/generated/listers/etcd/v1beta2\"\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n\twatch \"k8s.io/apimachinery/pkg/watch\"\n\tcache \"k8s.io/client-go/tools/cache\"\n)\n\n// EtcdRestoreInformer provides access to a shared informer and lister for\n// EtcdRestores.\ntype EtcdRestoreInformer interface {\n\tInformer() cache.SharedIndexInformer\n\tLister() v1beta2.EtcdRestoreLister\n}\n\ntype etcdRestoreInformer struct {\n\tfactory          internalinterfaces.SharedInformerFactory\n\ttweakListOptions internalinterfaces.TweakListOptionsFunc\n\tnamespace        string\n}\n\n// NewEtcdRestoreInformer constructs a new informer for EtcdRestore type.\n// Always prefer using an informer factory to get a shared informer instead of getting an independent\n// one. This reduces memory footprint and number of connections to the server.\nfunc NewEtcdRestoreInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {\n\treturn NewFilteredEtcdRestoreInformer(client, namespace, resyncPeriod, indexers, nil)\n}\n\n// NewFilteredEtcdRestoreInformer constructs a new informer for EtcdRestore type.\n// Always prefer using an informer factory to get a shared informer instead of getting an independent\n// one. This reduces memory footprint and number of connections to the server.\nfunc NewFilteredEtcdRestoreInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {\n\treturn cache.NewSharedIndexInformer(\n\t\t&cache.ListWatch{\n\t\t\tListFunc: func(options v1.ListOptions) (runtime.Object, error) {\n\t\t\t\tif tweakListOptions != nil {\n\t\t\t\t\ttweakListOptions(&options)\n\t\t\t\t}\n\t\t\t\treturn client.EtcdV1beta2().EtcdRestores(namespace).List(options)\n\t\t\t},\n\t\t\tWatchFunc: func(options v1.ListOptions) (watch.Interface, error) {\n\t\t\t\tif tweakListOptions != nil {\n\t\t\t\t\ttweakListOptions(&options)\n\t\t\t\t}\n\t\t\t\treturn client.EtcdV1beta2().EtcdRestores(namespace).Watch(options)\n\t\t\t},\n\t\t},\n\t\t&etcdv1beta2.EtcdRestore{},\n\t\tresyncPeriod,\n\t\tindexers,\n\t)\n}\n\nfunc (f *etcdRestoreInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {\n\treturn NewFilteredEtcdRestoreInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)\n}\n\nfunc (f *etcdRestoreInformer) Informer() cache.SharedIndexInformer {\n\treturn f.factory.InformerFor(&etcdv1beta2.EtcdRestore{}, f.defaultInformer)\n}\n\nfunc (f *etcdRestoreInformer) Lister() v1beta2.EtcdRestoreLister {\n\treturn v1beta2.NewEtcdRestoreLister(f.Informer().GetIndexer())\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/informers/externalversions/etcd/v1beta2/interface.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by informer-gen. DO NOT EDIT.\n\npackage v1beta2\n\nimport (\n\tinternalinterfaces \"github.com/coreos/etcd-operator/pkg/generated/informers/externalversions/internalinterfaces\"\n)\n\n// Interface provides access to all the informers in this group version.\ntype Interface interface {\n\t// EtcdBackups returns a EtcdBackupInformer.\n\tEtcdBackups() EtcdBackupInformer\n\t// EtcdClusters returns a EtcdClusterInformer.\n\tEtcdClusters() EtcdClusterInformer\n\t// EtcdRestores returns a EtcdRestoreInformer.\n\tEtcdRestores() EtcdRestoreInformer\n}\n\ntype version struct {\n\tfactory          internalinterfaces.SharedInformerFactory\n\tnamespace        string\n\ttweakListOptions internalinterfaces.TweakListOptionsFunc\n}\n\n// New returns a new Interface.\nfunc New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {\n\treturn &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}\n}\n\n// EtcdBackups returns a EtcdBackupInformer.\nfunc (v *version) EtcdBackups() EtcdBackupInformer {\n\treturn &etcdBackupInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}\n}\n\n// EtcdClusters returns a EtcdClusterInformer.\nfunc (v *version) EtcdClusters() EtcdClusterInformer {\n\treturn &etcdClusterInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}\n}\n\n// EtcdRestores returns a EtcdRestoreInformer.\nfunc (v *version) EtcdRestores() EtcdRestoreInformer {\n\treturn &etcdRestoreInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/informers/externalversions/factory.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by informer-gen. DO NOT EDIT.\n\npackage externalversions\n\nimport (\n\treflect \"reflect\"\n\tsync \"sync\"\n\ttime \"time\"\n\n\tversioned \"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned\"\n\tetcd \"github.com/coreos/etcd-operator/pkg/generated/informers/externalversions/etcd\"\n\tinternalinterfaces \"github.com/coreos/etcd-operator/pkg/generated/informers/externalversions/internalinterfaces\"\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n\tschema \"k8s.io/apimachinery/pkg/runtime/schema\"\n\tcache \"k8s.io/client-go/tools/cache\"\n)\n\n// SharedInformerOption defines the functional option type for SharedInformerFactory.\ntype SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory\n\ntype sharedInformerFactory struct {\n\tclient           versioned.Interface\n\tnamespace        string\n\ttweakListOptions internalinterfaces.TweakListOptionsFunc\n\tlock             sync.Mutex\n\tdefaultResync    time.Duration\n\tcustomResync     map[reflect.Type]time.Duration\n\n\tinformers map[reflect.Type]cache.SharedIndexInformer\n\t// startedInformers is used for tracking which informers have been started.\n\t// This allows Start() to be called multiple times safely.\n\tstartedInformers map[reflect.Type]bool\n}\n\n// WithCustomResyncConfig sets a custom resync period for the specified informer types.\nfunc WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption {\n\treturn func(factory *sharedInformerFactory) *sharedInformerFactory {\n\t\tfor k, v := range resyncConfig {\n\t\t\tfactory.customResync[reflect.TypeOf(k)] = v\n\t\t}\n\t\treturn factory\n\t}\n}\n\n// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory.\nfunc WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption {\n\treturn func(factory *sharedInformerFactory) *sharedInformerFactory {\n\t\tfactory.tweakListOptions = tweakListOptions\n\t\treturn factory\n\t}\n}\n\n// WithNamespace limits the SharedInformerFactory to the specified namespace.\nfunc WithNamespace(namespace string) SharedInformerOption {\n\treturn func(factory *sharedInformerFactory) *sharedInformerFactory {\n\t\tfactory.namespace = namespace\n\t\treturn factory\n\t}\n}\n\n// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces.\nfunc NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory {\n\treturn NewSharedInformerFactoryWithOptions(client, defaultResync)\n}\n\n// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory.\n// Listers obtained via this SharedInformerFactory will be subject to the same filters\n// as specified here.\n// Deprecated: Please use NewSharedInformerFactoryWithOptions instead\nfunc NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory {\n\treturn NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions))\n}\n\n// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options.\nfunc NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory {\n\tfactory := &sharedInformerFactory{\n\t\tclient:           client,\n\t\tnamespace:        v1.NamespaceAll,\n\t\tdefaultResync:    defaultResync,\n\t\tinformers:        make(map[reflect.Type]cache.SharedIndexInformer),\n\t\tstartedInformers: make(map[reflect.Type]bool),\n\t\tcustomResync:     make(map[reflect.Type]time.Duration),\n\t}\n\n\t// Apply all options\n\tfor _, opt := range options {\n\t\tfactory = opt(factory)\n\t}\n\n\treturn factory\n}\n\n// Start initializes all requested informers.\nfunc (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {\n\tf.lock.Lock()\n\tdefer f.lock.Unlock()\n\n\tfor informerType, informer := range f.informers {\n\t\tif !f.startedInformers[informerType] {\n\t\t\tgo informer.Run(stopCh)\n\t\t\tf.startedInformers[informerType] = true\n\t\t}\n\t}\n}\n\n// WaitForCacheSync waits for all started informers' cache were synced.\nfunc (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool {\n\tinformers := func() map[reflect.Type]cache.SharedIndexInformer {\n\t\tf.lock.Lock()\n\t\tdefer f.lock.Unlock()\n\n\t\tinformers := map[reflect.Type]cache.SharedIndexInformer{}\n\t\tfor informerType, informer := range f.informers {\n\t\t\tif f.startedInformers[informerType] {\n\t\t\t\tinformers[informerType] = informer\n\t\t\t}\n\t\t}\n\t\treturn informers\n\t}()\n\n\tres := map[reflect.Type]bool{}\n\tfor informType, informer := range informers {\n\t\tres[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)\n\t}\n\treturn res\n}\n\n// InternalInformerFor returns the SharedIndexInformer for obj using an internal\n// client.\nfunc (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer {\n\tf.lock.Lock()\n\tdefer f.lock.Unlock()\n\n\tinformerType := reflect.TypeOf(obj)\n\tinformer, exists := f.informers[informerType]\n\tif exists {\n\t\treturn informer\n\t}\n\n\tresyncPeriod, exists := f.customResync[informerType]\n\tif !exists {\n\t\tresyncPeriod = f.defaultResync\n\t}\n\n\tinformer = newFunc(f.client, resyncPeriod)\n\tf.informers[informerType] = informer\n\n\treturn informer\n}\n\n// SharedInformerFactory provides shared informers for resources in all known\n// API group versions.\ntype SharedInformerFactory interface {\n\tinternalinterfaces.SharedInformerFactory\n\tForResource(resource schema.GroupVersionResource) (GenericInformer, error)\n\tWaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool\n\n\tEtcd() etcd.Interface\n}\n\nfunc (f *sharedInformerFactory) Etcd() etcd.Interface {\n\treturn etcd.New(f, f.namespace, f.tweakListOptions)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/informers/externalversions/generic.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by informer-gen. DO NOT EDIT.\n\npackage externalversions\n\nimport (\n\t\"fmt\"\n\n\tv1beta2 \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\tschema \"k8s.io/apimachinery/pkg/runtime/schema\"\n\tcache \"k8s.io/client-go/tools/cache\"\n)\n\n// GenericInformer is type of SharedIndexInformer which will locate and delegate to other\n// sharedInformers based on type\ntype GenericInformer interface {\n\tInformer() cache.SharedIndexInformer\n\tLister() cache.GenericLister\n}\n\ntype genericInformer struct {\n\tinformer cache.SharedIndexInformer\n\tresource schema.GroupResource\n}\n\n// Informer returns the SharedIndexInformer.\nfunc (f *genericInformer) Informer() cache.SharedIndexInformer {\n\treturn f.informer\n}\n\n// Lister returns the GenericLister.\nfunc (f *genericInformer) Lister() cache.GenericLister {\n\treturn cache.NewGenericLister(f.Informer().GetIndexer(), f.resource)\n}\n\n// ForResource gives generic access to a shared informer of the matching type\n// TODO extend this to unknown resources with a client pool\nfunc (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {\n\tswitch resource {\n\t// Group=etcd.database.coreos.com, Version=v1beta2\n\tcase v1beta2.SchemeGroupVersion.WithResource(\"etcdbackups\"):\n\t\treturn &genericInformer{resource: resource.GroupResource(), informer: f.Etcd().V1beta2().EtcdBackups().Informer()}, nil\n\tcase v1beta2.SchemeGroupVersion.WithResource(\"etcdclusters\"):\n\t\treturn &genericInformer{resource: resource.GroupResource(), informer: f.Etcd().V1beta2().EtcdClusters().Informer()}, nil\n\tcase v1beta2.SchemeGroupVersion.WithResource(\"etcdrestores\"):\n\t\treturn &genericInformer{resource: resource.GroupResource(), informer: f.Etcd().V1beta2().EtcdRestores().Informer()}, nil\n\n\t}\n\n\treturn nil, fmt.Errorf(\"no informer found for %v\", resource)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by informer-gen. DO NOT EDIT.\n\npackage internalinterfaces\n\nimport (\n\ttime \"time\"\n\n\tversioned \"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned\"\n\tv1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n\tcache \"k8s.io/client-go/tools/cache\"\n)\n\ntype NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer\n\n// SharedInformerFactory a small interface to allow for adding an informer without an import cycle\ntype SharedInformerFactory interface {\n\tStart(stopCh <-chan struct{})\n\tInformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer\n}\n\ntype TweakListOptionsFunc func(*v1.ListOptions)\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/listers/etcd/v1beta2/etcdbackup.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by lister-gen. DO NOT EDIT.\n\npackage v1beta2\n\nimport (\n\tv1beta2 \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"k8s.io/apimachinery/pkg/api/errors\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n\t\"k8s.io/client-go/tools/cache\"\n)\n\n// EtcdBackupLister helps list EtcdBackups.\ntype EtcdBackupLister interface {\n\t// List lists all EtcdBackups in the indexer.\n\tList(selector labels.Selector) (ret []*v1beta2.EtcdBackup, err error)\n\t// EtcdBackups returns an object that can list and get EtcdBackups.\n\tEtcdBackups(namespace string) EtcdBackupNamespaceLister\n\tEtcdBackupListerExpansion\n}\n\n// etcdBackupLister implements the EtcdBackupLister interface.\ntype etcdBackupLister struct {\n\tindexer cache.Indexer\n}\n\n// NewEtcdBackupLister returns a new EtcdBackupLister.\nfunc NewEtcdBackupLister(indexer cache.Indexer) EtcdBackupLister {\n\treturn &etcdBackupLister{indexer: indexer}\n}\n\n// List lists all EtcdBackups in the indexer.\nfunc (s *etcdBackupLister) List(selector labels.Selector) (ret []*v1beta2.EtcdBackup, err error) {\n\terr = cache.ListAll(s.indexer, selector, func(m interface{}) {\n\t\tret = append(ret, m.(*v1beta2.EtcdBackup))\n\t})\n\treturn ret, err\n}\n\n// EtcdBackups returns an object that can list and get EtcdBackups.\nfunc (s *etcdBackupLister) EtcdBackups(namespace string) EtcdBackupNamespaceLister {\n\treturn etcdBackupNamespaceLister{indexer: s.indexer, namespace: namespace}\n}\n\n// EtcdBackupNamespaceLister helps list and get EtcdBackups.\ntype EtcdBackupNamespaceLister interface {\n\t// List lists all EtcdBackups in the indexer for a given namespace.\n\tList(selector labels.Selector) (ret []*v1beta2.EtcdBackup, err error)\n\t// Get retrieves the EtcdBackup from the indexer for a given namespace and name.\n\tGet(name string) (*v1beta2.EtcdBackup, error)\n\tEtcdBackupNamespaceListerExpansion\n}\n\n// etcdBackupNamespaceLister implements the EtcdBackupNamespaceLister\n// interface.\ntype etcdBackupNamespaceLister struct {\n\tindexer   cache.Indexer\n\tnamespace string\n}\n\n// List lists all EtcdBackups in the indexer for a given namespace.\nfunc (s etcdBackupNamespaceLister) List(selector labels.Selector) (ret []*v1beta2.EtcdBackup, err error) {\n\terr = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {\n\t\tret = append(ret, m.(*v1beta2.EtcdBackup))\n\t})\n\treturn ret, err\n}\n\n// Get retrieves the EtcdBackup from the indexer for a given namespace and name.\nfunc (s etcdBackupNamespaceLister) Get(name string) (*v1beta2.EtcdBackup, error) {\n\tobj, exists, err := s.indexer.GetByKey(s.namespace + \"/\" + name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif !exists {\n\t\treturn nil, errors.NewNotFound(v1beta2.Resource(\"etcdbackup\"), name)\n\t}\n\treturn obj.(*v1beta2.EtcdBackup), nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/listers/etcd/v1beta2/etcdcluster.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by lister-gen. DO NOT EDIT.\n\npackage v1beta2\n\nimport (\n\tv1beta2 \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"k8s.io/apimachinery/pkg/api/errors\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n\t\"k8s.io/client-go/tools/cache\"\n)\n\n// EtcdClusterLister helps list EtcdClusters.\ntype EtcdClusterLister interface {\n\t// List lists all EtcdClusters in the indexer.\n\tList(selector labels.Selector) (ret []*v1beta2.EtcdCluster, err error)\n\t// EtcdClusters returns an object that can list and get EtcdClusters.\n\tEtcdClusters(namespace string) EtcdClusterNamespaceLister\n\tEtcdClusterListerExpansion\n}\n\n// etcdClusterLister implements the EtcdClusterLister interface.\ntype etcdClusterLister struct {\n\tindexer cache.Indexer\n}\n\n// NewEtcdClusterLister returns a new EtcdClusterLister.\nfunc NewEtcdClusterLister(indexer cache.Indexer) EtcdClusterLister {\n\treturn &etcdClusterLister{indexer: indexer}\n}\n\n// List lists all EtcdClusters in the indexer.\nfunc (s *etcdClusterLister) List(selector labels.Selector) (ret []*v1beta2.EtcdCluster, err error) {\n\terr = cache.ListAll(s.indexer, selector, func(m interface{}) {\n\t\tret = append(ret, m.(*v1beta2.EtcdCluster))\n\t})\n\treturn ret, err\n}\n\n// EtcdClusters returns an object that can list and get EtcdClusters.\nfunc (s *etcdClusterLister) EtcdClusters(namespace string) EtcdClusterNamespaceLister {\n\treturn etcdClusterNamespaceLister{indexer: s.indexer, namespace: namespace}\n}\n\n// EtcdClusterNamespaceLister helps list and get EtcdClusters.\ntype EtcdClusterNamespaceLister interface {\n\t// List lists all EtcdClusters in the indexer for a given namespace.\n\tList(selector labels.Selector) (ret []*v1beta2.EtcdCluster, err error)\n\t// Get retrieves the EtcdCluster from the indexer for a given namespace and name.\n\tGet(name string) (*v1beta2.EtcdCluster, error)\n\tEtcdClusterNamespaceListerExpansion\n}\n\n// etcdClusterNamespaceLister implements the EtcdClusterNamespaceLister\n// interface.\ntype etcdClusterNamespaceLister struct {\n\tindexer   cache.Indexer\n\tnamespace string\n}\n\n// List lists all EtcdClusters in the indexer for a given namespace.\nfunc (s etcdClusterNamespaceLister) List(selector labels.Selector) (ret []*v1beta2.EtcdCluster, err error) {\n\terr = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {\n\t\tret = append(ret, m.(*v1beta2.EtcdCluster))\n\t})\n\treturn ret, err\n}\n\n// Get retrieves the EtcdCluster from the indexer for a given namespace and name.\nfunc (s etcdClusterNamespaceLister) Get(name string) (*v1beta2.EtcdCluster, error) {\n\tobj, exists, err := s.indexer.GetByKey(s.namespace + \"/\" + name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif !exists {\n\t\treturn nil, errors.NewNotFound(v1beta2.Resource(\"etcdcluster\"), name)\n\t}\n\treturn obj.(*v1beta2.EtcdCluster), nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/listers/etcd/v1beta2/etcdrestore.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by lister-gen. DO NOT EDIT.\n\npackage v1beta2\n\nimport (\n\tv1beta2 \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"k8s.io/apimachinery/pkg/api/errors\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n\t\"k8s.io/client-go/tools/cache\"\n)\n\n// EtcdRestoreLister helps list EtcdRestores.\ntype EtcdRestoreLister interface {\n\t// List lists all EtcdRestores in the indexer.\n\tList(selector labels.Selector) (ret []*v1beta2.EtcdRestore, err error)\n\t// EtcdRestores returns an object that can list and get EtcdRestores.\n\tEtcdRestores(namespace string) EtcdRestoreNamespaceLister\n\tEtcdRestoreListerExpansion\n}\n\n// etcdRestoreLister implements the EtcdRestoreLister interface.\ntype etcdRestoreLister struct {\n\tindexer cache.Indexer\n}\n\n// NewEtcdRestoreLister returns a new EtcdRestoreLister.\nfunc NewEtcdRestoreLister(indexer cache.Indexer) EtcdRestoreLister {\n\treturn &etcdRestoreLister{indexer: indexer}\n}\n\n// List lists all EtcdRestores in the indexer.\nfunc (s *etcdRestoreLister) List(selector labels.Selector) (ret []*v1beta2.EtcdRestore, err error) {\n\terr = cache.ListAll(s.indexer, selector, func(m interface{}) {\n\t\tret = append(ret, m.(*v1beta2.EtcdRestore))\n\t})\n\treturn ret, err\n}\n\n// EtcdRestores returns an object that can list and get EtcdRestores.\nfunc (s *etcdRestoreLister) EtcdRestores(namespace string) EtcdRestoreNamespaceLister {\n\treturn etcdRestoreNamespaceLister{indexer: s.indexer, namespace: namespace}\n}\n\n// EtcdRestoreNamespaceLister helps list and get EtcdRestores.\ntype EtcdRestoreNamespaceLister interface {\n\t// List lists all EtcdRestores in the indexer for a given namespace.\n\tList(selector labels.Selector) (ret []*v1beta2.EtcdRestore, err error)\n\t// Get retrieves the EtcdRestore from the indexer for a given namespace and name.\n\tGet(name string) (*v1beta2.EtcdRestore, error)\n\tEtcdRestoreNamespaceListerExpansion\n}\n\n// etcdRestoreNamespaceLister implements the EtcdRestoreNamespaceLister\n// interface.\ntype etcdRestoreNamespaceLister struct {\n\tindexer   cache.Indexer\n\tnamespace string\n}\n\n// List lists all EtcdRestores in the indexer for a given namespace.\nfunc (s etcdRestoreNamespaceLister) List(selector labels.Selector) (ret []*v1beta2.EtcdRestore, err error) {\n\terr = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {\n\t\tret = append(ret, m.(*v1beta2.EtcdRestore))\n\t})\n\treturn ret, err\n}\n\n// Get retrieves the EtcdRestore from the indexer for a given namespace and name.\nfunc (s etcdRestoreNamespaceLister) Get(name string) (*v1beta2.EtcdRestore, error) {\n\tobj, exists, err := s.indexer.GetByKey(s.namespace + \"/\" + name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif !exists {\n\t\treturn nil, errors.NewNotFound(v1beta2.Resource(\"etcdrestore\"), name)\n\t}\n\treturn obj.(*v1beta2.EtcdRestore), nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/generated/listers/etcd/v1beta2/expansion_generated.go",
    "content": "/*\nCopyright 2019 The etcd-operator Authors\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\n// Code generated by lister-gen. DO NOT EDIT.\n\npackage v1beta2\n\n// EtcdBackupListerExpansion allows custom methods to be added to\n// EtcdBackupLister.\ntype EtcdBackupListerExpansion interface{}\n\n// EtcdBackupNamespaceListerExpansion allows custom methods to be added to\n// EtcdBackupNamespaceLister.\ntype EtcdBackupNamespaceListerExpansion interface{}\n\n// EtcdClusterListerExpansion allows custom methods to be added to\n// EtcdClusterLister.\ntype EtcdClusterListerExpansion interface{}\n\n// EtcdClusterNamespaceListerExpansion allows custom methods to be added to\n// EtcdClusterNamespaceLister.\ntype EtcdClusterNamespaceListerExpansion interface{}\n\n// EtcdRestoreListerExpansion allows custom methods to be added to\n// EtcdRestoreLister.\ntype EtcdRestoreListerExpansion interface{}\n\n// EtcdRestoreNamespaceListerExpansion allows custom methods to be added to\n// EtcdRestoreNamespaceLister.\ntype EtcdRestoreNamespaceListerExpansion interface{}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/alibabacloudutil/ossfactory/client.go",
    "content": "// Copyright 2019 The etcd-operator 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\npackage ossfactory\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/aliyun/aliyun-oss-go-sdk/oss\"\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n)\n\n// OSSClient is a wrapper of OSS client that provides cleanup functionality.\ntype OSSClient struct {\n\tOSS *oss.Client\n}\n\n// NewClientFromSecret returns a OSS client based on given k8s secret containing alibabacloud credentials.\nfunc NewClientFromSecret(kubecli kubernetes.Interface, namespace, endpoint, ossSecret string) (w *OSSClient, err error) {\n\tdefer func() {\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"new OSS client failed: %v\", err)\n\t\t}\n\t}()\n\n\tse, err := kubecli.CoreV1().Secrets(namespace).Get(ossSecret, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get k8s secret: %v\", err)\n\t}\n\n\taccessKeyID, ok := se.Data[api.AlibabaCloudSecretCredentialsAccessKeyID]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"key \\\"%s\\\" not found in secret \\\"%s\\\" in namespace \\\"%s\\\"\",\n\t\t\tapi.AlibabaCloudSecretCredentialsAccessKeyID, ossSecret, namespace)\n\t}\n\n\taccessKeySecret, ok := se.Data[api.AlibabaCloudSecretCredentialsAccessKeySecret]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"key \\\"%s\\\" not found in secret \\\"%s\\\" in namespace \\\"%s\\\"\",\n\t\t\tapi.AlibabaCloudSecretCredentialsAccessKeySecret, ossSecret, namespace)\n\t}\n\n\tclient, err := oss.New(endpoint, string(accessKeyID), string(accessKeySecret))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create OSS client: %v\", err)\n\t}\n\treturn &OSSClient{OSS: client}, nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/awsutil/s3factory/client.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage s3factory\n\nimport (\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"path\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\n\t\"github.com/aws/aws-sdk-go/aws/session\"\n\t\"github.com/aws/aws-sdk-go/service/s3\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n)\n\nconst (\n\ttmpdir = \"/tmp\"\n)\n\n// S3Client is a wrapper for S3 client that provides cleanup functionality.\ntype S3Client struct {\n\tS3        *s3.S3\n\tconfigDir string\n}\n\n// NewClientFromSecret returns a S3 client based on given k8s secret containing aws credentials.\nfunc NewClientFromSecret(kubecli kubernetes.Interface, namespace, endpoint, awsSecret string, forcePathStyle bool) (w *S3Client, err error) {\n\tdefer func() {\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"new S3 client failed: %v\", err)\n\t\t}\n\t}()\n\tw = &S3Client{}\n\tw.configDir, err = ioutil.TempDir(tmpdir, \"\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create aws config dir: (%v)\", err)\n\t}\n\tso, err := setupAWSConfig(kubecli, namespace, awsSecret, endpoint, w.configDir, forcePathStyle)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to setup aws config: (%v)\", err)\n\t}\n\tsess, err := session.NewSessionWithOptions(*so)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"new AWS session failed: %v\", err)\n\t}\n\tw.S3 = s3.New(sess)\n\treturn w, nil\n}\n\n// Close cleans up all intermediate resources for creating S3 client.\nfunc (w *S3Client) Close() {\n\tos.RemoveAll(w.configDir)\n}\n\n// setupAWSConfig setup local AWS config/credential files from Kubernetes aws secret.\nfunc setupAWSConfig(kubecli kubernetes.Interface, ns, secret, endpoint, configDir string, forcePathStyle bool) (*session.Options, error) {\n\toptions := &session.Options{}\n\toptions.SharedConfigState = session.SharedConfigEnable\n\n\t// empty string defaults to aws\n\toptions.Config.Endpoint = &endpoint\n\n\toptions.Config.S3ForcePathStyle = &forcePathStyle\n\n\tse, err := kubecli.CoreV1().Secrets(ns).Get(secret, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"setup AWS config failed: get k8s secret failed: %v\", err)\n\t}\n\n\tcreds := se.Data[api.AWSSecretCredentialsFileName]\n\tif len(creds) != 0 {\n\t\tcredsFile := path.Join(configDir, \"credentials\")\n\t\terr = ioutil.WriteFile(credsFile, creds, 0600)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"setup AWS config failed: write credentials file failed: %v\", err)\n\t\t}\n\t\toptions.SharedConfigFiles = append(options.SharedConfigFiles, credsFile)\n\t}\n\n\tconfig := se.Data[api.AWSSecretConfigFileName]\n\tif len(config) != 0 {\n\t\tconfigFile := path.Join(configDir, \"config\")\n\t\terr = ioutil.WriteFile(configFile, config, 0600)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"setup AWS config failed: write config file failed: %v\", err)\n\t\t}\n\t\toptions.SharedConfigFiles = append(options.SharedConfigFiles, configFile)\n\t}\n\n\treturn options, nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/awsutil/s3factory/client_test.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage s3factory\n\nimport (\n\t\"testing\"\n\n\t\"k8s.io/api/core/v1\"\n\t\"k8s.io/client-go/kubernetes/fake\"\n)\n\nfunc TestSetupAWSConfig(t *testing.T) {\n\tsec := &v1.Secret{\n\t\tData: map[string][]byte{},\n\t}\n\n\tclient := fake.NewSimpleClientset(sec)\n\n\te := \"example.com\"\n\topts, err := setupAWSConfig(client, \"\", \"\", e, \"\", false)\n\tif err != nil {\n\t\tt.Error(err)\n\t}\n\n\tif e != *opts.Config.Endpoint {\n\t\tt.Errorf(\"got: %s wanted: %s\", *opts.Config.Endpoint, e)\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/azureutil/absfactory/client.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage absfactory\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/Azure/azure-sdk-for-go/storage\"\n\t\"github.com/Azure/go-autorest/autorest/azure\"\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n)\n\n// ABSClient is a wrapper of ABS client that provides cleanup functionality.\ntype ABSClient struct {\n\tABS *storage.BlobStorageClient\n}\n\n// parseAzureEnvironment returns azure environment by name\nfunc parseAzureEnvironment(cloudName string) (azure.Environment, error) {\n\tif cloudName == \"\" {\n\t\treturn azure.PublicCloud, nil\n\t}\n\n\treturn azure.EnvironmentFromName(cloudName)\n}\n\n// NewClientFromSecret returns a ABS client based on given k8s secret containing azure credentials.\nfunc NewClientFromSecret(kubecli kubernetes.Interface, namespace, absSecret string) (w *ABSClient, err error) {\n\tdefer func() {\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"new ABS client failed: %v\", err)\n\t\t}\n\t}()\n\n\tse, err := kubecli.CoreV1().Secrets(namespace).Get(absSecret, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get k8s secret: %v\", err)\n\t}\n\n\tstorageAccount := se.Data[api.AzureSecretStorageAccount]\n\tstorageKey := se.Data[api.AzureSecretStorageKey]\n\tcloudName := se.Data[api.AzureCloudKey]\n\n\tcloud, err := parseAzureEnvironment(string(cloudName))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tbc, err := storage.NewBasicClientOnSovereignCloud(\n\t\tstring(storageAccount),\n\t\tstring(storageKey),\n\t\tcloud)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create Azure storage client: %v\", err)\n\t}\n\n\tabs := bc.GetBlobService()\n\treturn &ABSClient{ABS: &abs}, nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/constants/constants.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage constants\n\nimport \"time\"\n\nconst (\n\tDefaultDialTimeout    = 5 * time.Second\n\tDefaultRequestTimeout = 5 * time.Second\n\t// DefaultBackupTimeout is the default maximal allowed time of the entire backup process.\n\tDefaultBackupTimeout    = 1 * time.Minute\n\tDefaultSnapshotInterval = 1800 * time.Second\n\n\tDefaultBackupPodHTTPPort = 19999\n\n\tOperatorRoot   = \"/var/tmp/etcd-operator\"\n\tBackupMountDir = \"/var/etcd-backup\"\n\n\tEnvOperatorPodName        = \"MY_POD_NAME\"\n\tEnvOperatorPodNamespace   = \"MY_POD_NAMESPACE\"\n\tEnvOperatorWatchNamespace = \"WATCH_NAMESPACE\"\n)\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/etcdutil/etcdutil.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage etcdutil\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"fmt\"\n\n\t\"github.com/coreos/etcd-operator/pkg/util/constants\"\n\t\"github.com/coreos/etcd/clientv3\"\n)\n\nfunc ListMembers(clientURLs []string, tc *tls.Config) (*clientv3.MemberListResponse, error) {\n\tcfg := clientv3.Config{\n\t\tEndpoints:   clientURLs,\n\t\tDialTimeout: constants.DefaultDialTimeout,\n\t\tTLS:         tc,\n\t}\n\tetcdcli, err := clientv3.New(cfg)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"list members failed: creating etcd client failed: %v\", err)\n\t}\n\n\tctx, cancel := context.WithTimeout(context.Background(), constants.DefaultRequestTimeout)\n\tresp, err := etcdcli.MemberList(ctx)\n\tcancel()\n\tetcdcli.Close()\n\treturn resp, err\n}\n\nfunc RemoveMember(clientURLs []string, tc *tls.Config, id uint64) error {\n\tcfg := clientv3.Config{\n\t\tEndpoints:   clientURLs,\n\t\tDialTimeout: constants.DefaultDialTimeout,\n\t\tTLS:         tc,\n\t}\n\tetcdcli, err := clientv3.New(cfg)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer etcdcli.Close()\n\n\tctx, cancel := context.WithTimeout(context.Background(), constants.DefaultRequestTimeout)\n\t_, err = etcdcli.Cluster.MemberRemove(ctx, id)\n\tcancel()\n\treturn err\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/etcdutil/etcdutil_test.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage etcdutil\n\nimport \"testing\"\n\nfunc TestMemberNameFromPeerURL(t *testing.T) {\n\ttests := []struct {\n\t\tpurl  string\n\t\twName string\n\t\twErr  bool\n\t}{{\n\t\tpurl:  \"http://test-cluster:2379\",\n\t\twName: \"test-cluster\",\n\t}, {\n\t\tpurl:  \"https://test-cluster:2379\",\n\t\twName: \"test-cluster\",\n\t}, {\n\t\tpurl:  \"http://test-cluster\",\n\t\twName: \"test-cluster\",\n\t}, {\n\t\tpurl: \"test-cluster\",\n\t\twErr: true,\n\t}, {\n\t\tpurl: \"test-cluster:2379\",\n\t\twErr: true,\n\t}, {\n\t\tpurl: \"\",\n\t\twErr: true,\n\t}, {\n\t\tpurl: \"http://\",\n\t\twErr: true,\n\t}, {\n\t\tpurl: \"http://a:a\",\n\t\twErr: true,\n\t}}\n\n\tfor i, tt := range tests {\n\t\tget, err := MemberNameFromPeerURL(tt.purl)\n\t\tif tt.wErr {\n\t\t\tif err == nil {\n\t\t\t\tt.Errorf(\"#%d: should be error case\", i)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"#%d: want err = nil, got %v\", i, err)\n\t\t}\n\t\tif get != tt.wName {\n\t\t\tt.Errorf(\"#%d: member name get=%s, want=%s\", i, get, tt.wName)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/etcdutil/member.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage etcdutil\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"net/url\"\n\t\"regexp\"\n\t\"strings\"\n)\n\ntype Member struct {\n\tName string\n\t// Kubernetes namespace this member runs in.\n\tNamespace string\n\t// ID field can be 0, which is unknown ID.\n\t// We know the ID of a member when we get the member information from etcd,\n\t// but not from Kubernetes pod list.\n\tID uint64\n\n\tSecurePeer   bool\n\tSecureClient bool\n\n\t// ClusterDomain is the DNS name of the cluster. E.g. .cluster.local.\n\tClusterDomain string\n}\n\nfunc (m *Member) Addr() string {\n\treturn fmt.Sprintf(\"%s.%s.%s.svc%s\", m.Name, clusterNameFromMemberName(m.Name), m.Namespace, m.ClusterDomain)\n}\n\n// ClientURL is the client URL for this member\nfunc (m *Member) ClientURL() string {\n\treturn fmt.Sprintf(\"%s://%s:2379\", m.clientScheme(), m.Addr())\n}\n\nfunc (m *Member) clientScheme() string {\n\tif m.SecureClient {\n\t\treturn \"https\"\n\t}\n\treturn \"http\"\n}\n\nfunc (m *Member) peerScheme() string {\n\tif m.SecurePeer {\n\t\treturn \"https\"\n\t}\n\treturn \"http\"\n}\n\nfunc (m *Member) ListenClientURL() string {\n\treturn fmt.Sprintf(\"%s://0.0.0.0:2379\", m.clientScheme())\n}\nfunc (m *Member) ListenPeerURL() string {\n\treturn fmt.Sprintf(\"%s://0.0.0.0:2380\", m.peerScheme())\n}\n\nfunc (m *Member) PeerURL() string {\n\treturn fmt.Sprintf(\"%s://%s:2380\", m.peerScheme(), m.Addr())\n}\n\ntype MemberSet map[string]*Member\n\nfunc NewMemberSet(ms ...*Member) MemberSet {\n\tres := MemberSet{}\n\tfor _, m := range ms {\n\t\tres[m.Name] = m\n\t}\n\treturn res\n}\n\n// the set of all members of s1 that are not members of s2\nfunc (ms MemberSet) Diff(other MemberSet) MemberSet {\n\tdiff := MemberSet{}\n\tfor n, m := range ms {\n\t\tif _, ok := other[n]; !ok {\n\t\t\tdiff[n] = m\n\t\t}\n\t}\n\treturn diff\n}\n\n// IsEqual tells whether two member sets are equal by checking\n// - they have the same set of members and member equality are judged by Name only.\nfunc (ms MemberSet) IsEqual(other MemberSet) bool {\n\tif ms.Size() != other.Size() {\n\t\treturn false\n\t}\n\tfor n := range ms {\n\t\tif _, ok := other[n]; !ok {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfunc (ms MemberSet) Size() int {\n\treturn len(ms)\n}\n\nfunc (ms MemberSet) String() string {\n\tvar mstring []string\n\n\tfor m := range ms {\n\t\tmstring = append(mstring, m)\n\t}\n\treturn strings.Join(mstring, \",\")\n}\n\nfunc (ms MemberSet) PickOne() *Member {\n\tfor _, m := range ms {\n\t\treturn m\n\t}\n\tpanic(\"empty\")\n}\n\nfunc (ms MemberSet) PeerURLPairs() []string {\n\tps := make([]string, 0)\n\tfor _, m := range ms {\n\t\tps = append(ps, fmt.Sprintf(\"%s=%s\", m.Name, m.PeerURL()))\n\t}\n\treturn ps\n}\n\nfunc (ms MemberSet) Add(m *Member) {\n\tms[m.Name] = m\n}\n\nfunc (ms MemberSet) Remove(name string) {\n\tdelete(ms, name)\n}\n\nfunc (ms MemberSet) ClientURLs() []string {\n\tendpoints := make([]string, 0, len(ms))\n\tfor _, m := range ms {\n\t\tendpoints = append(endpoints, m.ClientURL())\n\t}\n\treturn endpoints\n}\n\nvar validPeerURL = regexp.MustCompile(`^\\w+:\\/\\/[\\w\\.\\-]+(:\\d+)?$`)\n\nfunc MemberNameFromPeerURL(pu string) (string, error) {\n\t// url.Parse has very loose validation. We do our own validation.\n\tif !validPeerURL.MatchString(pu) {\n\t\treturn \"\", errors.New(\"invalid PeerURL format\")\n\t}\n\tu, err := url.Parse(pu)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tpath := strings.Split(u.Host, \":\")[0]\n\tname := strings.Split(path, \".\")[0]\n\treturn name, err\n}\n\nfunc clusterNameFromMemberName(mn string) string {\n\ti := strings.LastIndex(mn, \"-\")\n\tif i == -1 {\n\t\tpanic(fmt.Sprintf(\"unexpected member name: %s\", mn))\n\t}\n\treturn mn[:i]\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/etcdutil/member_test.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage etcdutil\n\nimport \"testing\"\n\nfunc TestMemberSetIsEqual(t *testing.T) {\n\tma := &Member{Name: \"a\"}\n\tmb := &Member{Name: \"b\"}\n\ttests := []struct {\n\t\tms1, ms2 MemberSet\n\t\twEqual   bool\n\t}{{\n\t\tms1:    NewMemberSet(ma, mb),\n\t\tms2:    NewMemberSet(ma, mb),\n\t\twEqual: true,\n\t}, {\n\t\tms1:    NewMemberSet(ma, mb),\n\t\tms2:    NewMemberSet(ma),\n\t\twEqual: false,\n\t}, {\n\t\tms1:    NewMemberSet(ma),\n\t\tms2:    NewMemberSet(ma, mb),\n\t\twEqual: false,\n\t}, {\n\t\tms1:    NewMemberSet(),\n\t\tms2:    NewMemberSet(),\n\t\twEqual: true,\n\t}, {\n\t\tms1:    NewMemberSet(),\n\t\tms2:    NewMemberSet(ma),\n\t\twEqual: false,\n\t}, {\n\t\tms1:    NewMemberSet(ma),\n\t\tms2:    NewMemberSet(),\n\t\twEqual: false,\n\t}}\n\tfor i, tt := range tests {\n\t\teq := tt.ms1.IsEqual(tt.ms2)\n\t\tif eq != tt.wEqual {\n\t\t\tt.Errorf(\"#%d: equal get=%v, want=%v, sets: %v, %v\", i, eq, tt.wEqual, tt.ms1, tt.ms2)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/etcdutil/tls.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage etcdutil\n\nimport (\n\t\"crypto/tls\"\n\t\"io/ioutil\"\n\t\"path/filepath\"\n\n\t\"github.com/coreos/etcd/pkg/transport\"\n)\n\n\nconst (\n\tDefaultCliCertFile = \"client.crt\"\n\tDefaultCliKeyFile  = \"client.key\"\n\tDefaultCliCAFile   = \"client-ca.crt\"\n)\n\nvar (\n\tCliCertFile = \"client.crt\"\n\tCliKeyFile  = \"client.key\"\n\tCliCAFile   = \"client-ca.crt\"\n)\n\nfunc InitEtcdTLSConfig(cert,key,ca string) {\n\tCliCertFile = cert\n\tCliKeyFile = key\n\tCliCAFile = ca\n}\n\nfunc NewTLSConfig(certData, keyData, caData []byte) (*tls.Config, error) {\n\t// TODO: Need cleanup these temp dirs\n\tdir, err := ioutil.TempDir(\"\", \"etcd-operator-cluster-tls\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tcertFile, err := writeFile(dir, CliCertFile, certData)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tkeyFile, err := writeFile(dir, CliKeyFile, keyData)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcaFile, err := writeFile(dir, CliCAFile, caData)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\ttlsInfo := transport.TLSInfo{\n\t\tCertFile:      certFile,\n\t\tKeyFile:       keyFile,\n\t\tTrustedCAFile: caFile,\n\t}\n\ttlsConfig, err := tlsInfo.ClientConfig()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn tlsConfig, nil\n}\n\nfunc writeFile(dir, file string, data []byte) (string, error) {\n\tp := filepath.Join(dir, file)\n\treturn p, ioutil.WriteFile(p, data, 0600)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/gcputil/gcsfactory/client.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage gcsfactory\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"cloud.google.com/go/storage\"\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"golang.org/x/oauth2\"\n\t\"google.golang.org/api/option\"\n\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n)\n\n// GCSClient is a wrapper of GCS client that provides cleanup functionality.\ntype GCSClient struct {\n\tGCS *storage.Client\n}\n\n// NewClientFromSecret returns a GCS client based on given k8s secret containing azure credentials.\nfunc NewClientFromSecret(ctx context.Context, kubecli kubernetes.Interface, namespace, gcsSecret string) (w *GCSClient, err error) {\n\tdefer func() {\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"new GCS client failed: %v\", err)\n\t\t}\n\t}()\n\n\tvar authOptions []option.ClientOption\n\tif se, err := kubecli.CoreV1().Secrets(namespace).Get(gcsSecret, metav1.GetOptions{}); err == nil {\n\t\tif accessToken, ok := se.Data[api.GCPAccessToken]; ok {\n\t\t\tauthOptions = append(authOptions, option.WithTokenSource(oauth2.StaticTokenSource(&oauth2.Token{AccessToken: string(accessToken)})))\n\t\t} else if credentialsJson, ok := se.Data[api.GCPCredentialsJson]; ok {\n\t\t\tauthOptions = append(authOptions, option.WithCredentialsJSON(credentialsJson))\n\t\t}\n\t}\n\n\tgcs, err := storage.NewClient(ctx, authOptions...)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create client: %v\", err)\n\t}\n\n\treturn &GCSClient{GCS: gcs}, nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/k8sutil/crd.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage k8sutil\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"time\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/util/retryutil\"\n\n\tapiextensionsv1beta1 \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1\"\n\tapiextensionsclient \"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/client-go/rest\"\n)\n\n// TODO: replace this package with Operator client\n\n// EtcdClusterCRUpdateFunc is a function to be used when atomically\n// updating a Cluster CR.\ntype EtcdClusterCRUpdateFunc func(*api.EtcdCluster)\n\nfunc GetClusterList(restcli rest.Interface, ns string) (*api.EtcdClusterList, error) {\n\tb, err := restcli.Get().RequestURI(listClustersURI(ns)).DoRaw()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tclusters := &api.EtcdClusterList{}\n\tif err := json.Unmarshal(b, clusters); err != nil {\n\t\treturn nil, err\n\t}\n\treturn clusters, nil\n}\n\nfunc listClustersURI(ns string) string {\n\treturn fmt.Sprintf(\"/apis/%s/namespaces/%s/%s\", api.SchemeGroupVersion.String(), ns, api.EtcdClusterResourcePlural)\n}\n\nfunc CreateCRD(clientset apiextensionsclient.Interface, crdName, rkind, rplural, shortName string) error {\n\tcrd := &apiextensionsv1beta1.CustomResourceDefinition{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName: crdName,\n\t\t},\n\t\tSpec: apiextensionsv1beta1.CustomResourceDefinitionSpec{\n\t\t\tGroup:   api.SchemeGroupVersion.Group,\n\t\t\tVersion: api.SchemeGroupVersion.Version,\n\t\t\tScope:   apiextensionsv1beta1.NamespaceScoped,\n\t\t\tNames: apiextensionsv1beta1.CustomResourceDefinitionNames{\n\t\t\t\tPlural: rplural,\n\t\t\t\tKind:   rkind,\n\t\t\t},\n\t\t},\n\t}\n\tif len(shortName) != 0 {\n\t\tcrd.Spec.Names.ShortNames = []string{shortName}\n\t}\n\t_, err := clientset.ApiextensionsV1beta1().CustomResourceDefinitions().Create(crd)\n\tif err != nil && !IsKubernetesResourceAlreadyExistError(err) {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc WaitCRDReady(clientset apiextensionsclient.Interface, crdName string) error {\n\terr := retryutil.Retry(5*time.Second, 20, func() (bool, error) {\n\t\tcrd, err := clientset.ApiextensionsV1beta1().CustomResourceDefinitions().Get(crdName, metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\tfor _, cond := range crd.Status.Conditions {\n\t\t\tswitch cond.Type {\n\t\t\tcase apiextensionsv1beta1.Established:\n\t\t\t\tif cond.Status == apiextensionsv1beta1.ConditionTrue {\n\t\t\t\t\treturn true, nil\n\t\t\t\t}\n\t\t\tcase apiextensionsv1beta1.NamesAccepted:\n\t\t\t\tif cond.Status == apiextensionsv1beta1.ConditionFalse {\n\t\t\t\t\treturn false, fmt.Errorf(\"Name conflict: %v\", cond.Reason)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false, nil\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"wait CRD created failed: %v\", err)\n\t}\n\treturn nil\n}\n\nfunc MustNewKubeExtClient() apiextensionsclient.Interface {\n\tcfg, err := InClusterConfig()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn apiextensionsclient.NewForConfigOrDie(cfg)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/k8sutil/events_util.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage k8sutil\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"time\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/util/constants\"\n\n\t\"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\nfunc NewMemberAddEvent(memberName string, cl *api.EtcdCluster) *v1.Event {\n\tevent := newClusterEvent(cl)\n\tevent.Type = v1.EventTypeNormal\n\tevent.Reason = \"New Member Added\"\n\tevent.Message = fmt.Sprintf(\"New member %s added to cluster\", memberName)\n\treturn event\n}\n\nfunc MemberRemoveEvent(memberName string, cl *api.EtcdCluster) *v1.Event {\n\tevent := newClusterEvent(cl)\n\tevent.Type = v1.EventTypeNormal\n\tevent.Reason = \"Member Removed\"\n\tevent.Message = fmt.Sprintf(\"Existing member %s removed from the cluster\", memberName)\n\treturn event\n}\n\nfunc ReplacingDeadMemberEvent(memberName string, cl *api.EtcdCluster) *v1.Event {\n\tevent := newClusterEvent(cl)\n\tevent.Type = v1.EventTypeNormal\n\tevent.Reason = \"Replacing Dead Member\"\n\tevent.Message = fmt.Sprintf(\"The dead member %s is being replaced\", memberName)\n\treturn event\n}\n\nfunc MemberUpgradedEvent(memberName, oldVersion, newVersion string, cl *api.EtcdCluster) *v1.Event {\n\tevent := newClusterEvent(cl)\n\tevent.Type = v1.EventTypeNormal\n\tevent.Reason = \"Member Upgraded\"\n\tevent.Message = fmt.Sprintf(\"Member %s upgraded from %s to %s \", memberName, oldVersion, newVersion)\n\treturn event\n}\n\nfunc newClusterEvent(cl *api.EtcdCluster) *v1.Event {\n\tt := time.Now()\n\treturn &v1.Event{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tGenerateName: cl.Name + \"-\",\n\t\t\tNamespace:    cl.Namespace,\n\t\t},\n\t\tInvolvedObject: v1.ObjectReference{\n\t\t\tAPIVersion:      api.SchemeGroupVersion.String(),\n\t\t\tKind:            api.EtcdClusterResourceKind,\n\t\t\tName:            cl.Name,\n\t\t\tNamespace:       cl.Namespace,\n\t\t\tUID:             cl.UID,\n\t\t\tResourceVersion: cl.ResourceVersion,\n\t\t},\n\t\tSource: v1.EventSource{\n\t\t\tComponent: os.Getenv(constants.EnvOperatorPodName),\n\t\t},\n\t\t// Each cluster event is unique so it should not be collapsed with other events\n\t\tFirstTimestamp: metav1.Time{Time: t},\n\t\tLastTimestamp:  metav1.Time{Time: t},\n\t\tCount:          int32(1),\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/k8sutil/k8sutil.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage k8sutil\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net\"\n\t\"net/url\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/coreos/etcd-operator/pkg/util/etcdutil\"\n\t\"github.com/coreos/etcd-operator/pkg/util/retryutil\"\n\t\"github.com/pborman/uuid\"\n\t\"k8s.io/api/core/v1\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\t\"k8s.io/apimachinery/pkg/util/intstr\"\n\t\"k8s.io/apimachinery/pkg/util/strategicpatch\"\n\t\"k8s.io/client-go/kubernetes\"\n\t_ \"k8s.io/client-go/plugin/pkg/client/auth/gcp\" // for gcp auth\n\t\"k8s.io/client-go/rest\"\n\t\"k8s.io/client-go/tools/clientcmd\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\tappsv1beta1 \"k8s.io/api/apps/v1beta1\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\tutilrand \"k8s.io/apimachinery/pkg/util/rand\"\n)\n\nconst (\n\t// EtcdClientPort is the client port on client service and etcd nodes.\n\tEtcdClientPort = 2379\n\n\tetcdVolumeMountDir       = \"/var/etcd\"\n\tdataDir                  = etcdVolumeMountDir + \"/data\"\n\tbackupFile               = \"/var/etcd/latest.backup\"\n\tetcdVersionAnnotationKey = \"etcd.version\"\n\tpeerTLSDir               = \"/etc/etcdtls/member/peer-tls\"\n\tpeerTLSVolume            = \"member-peer-tls\"\n\tserverTLSDir             = \"/etc/etcdtls/member/server-tls\"\n\tserverTLSVolume          = \"member-server-tls\"\n\toperatorEtcdTLSDir       = \"/etc/etcdtls/operator/etcd-tls\"\n\toperatorEtcdTLSVolume    = \"etcd-client-tls\"\n\n\trandomSuffixLength = 10\n\t// k8s object name has a maximum length\n\tMaxNameLength = 63 - randomSuffixLength - 1\n\n\tdefaultBusyboxImage = \"busybox:1.28.0-glibc\"\n\n\t// AnnotationScope annotation name for defining instance scope. Used for specifying cluster wide clusters.\n\tAnnotationScope = \"etcd.database.coreos.com/scope\"\n\t//AnnotationClusterWide annotation value for cluster wide clusters.\n\tAnnotationClusterWide = \"clusterwide\"\n\n\t// defaultDNSTimeout is the default maximum allowed time for the init container of the etcd pod\n\t// to reverse DNS lookup its IP. The default behavior is to wait forever and has a value of 0.\n\tdefaultDNSTimeout = int64(0)\n)\n\nconst TolerateUnreadyEndpointsAnnotation = \"service.alpha.kubernetes.io/tolerate-unready-endpoints\"\n\nfunc GetEtcdVersion(pod *v1.Pod) string {\n\treturn pod.Annotations[etcdVersionAnnotationKey]\n}\n\nfunc SetEtcdVersion(pod *v1.Pod, version string) {\n\tpod.Annotations[etcdVersionAnnotationKey] = version\n}\n\nfunc GetPodNames(pods []*v1.Pod) []string {\n\tif len(pods) == 0 {\n\t\treturn nil\n\t}\n\tres := []string{}\n\tfor _, p := range pods {\n\t\tres = append(res, p.Name)\n\t}\n\treturn res\n}\n\n// PVCNameFromMember the way we get PVC name from the member name\nfunc PVCNameFromMember(memberName string) string {\n\treturn memberName\n}\n\nfunc makeRestoreInitContainers(backupURL *url.URL, token, repo, version string, m *etcdutil.Member) []v1.Container {\n\treturn []v1.Container{\n\t\t{\n\t\t\tName:  \"fetch-backup\",\n\t\t\tImage: \"tutum/curl\",\n\t\t\tCommand: []string{\n\t\t\t\t\"/bin/bash\", \"-ec\",\n\t\t\t\tfmt.Sprintf(`\nhttpcode=$(curl --write-out %%\\{http_code\\} --silent --output %[1]s %[2]s)\nif [[ \"$httpcode\" != \"200\" ]]; then\n\techo \"http status code: ${httpcode}\" >> /dev/termination-log\n\tcat %[1]s >> /dev/termination-log\n\texit 1\nfi\n\t\t\t\t\t`, backupFile, backupURL.String()),\n\t\t\t},\n\t\t\tVolumeMounts: etcdVolumeMounts(),\n\t\t},\n\t\t{\n\t\t\tName:  \"restore-datadir\",\n\t\t\tImage: ImageName(repo, version),\n\t\t\tCommand: []string{\n\t\t\t\t\"/bin/sh\", \"-ec\",\n\t\t\t\tfmt.Sprintf(\"ETCDCTL_API=3 etcdctl snapshot restore %[1]s\"+\n\t\t\t\t\t\" --name %[2]s\"+\n\t\t\t\t\t\" --initial-cluster %[2]s=%[3]s\"+\n\t\t\t\t\t\" --initial-cluster-token %[4]s\"+\n\t\t\t\t\t\" --initial-advertise-peer-urls %[3]s\"+\n\t\t\t\t\t\" --data-dir %[5]s 2>/dev/termination-log\", backupFile, m.Name, m.PeerURL(), token, dataDir),\n\t\t\t},\n\t\t\tVolumeMounts: etcdVolumeMounts(),\n\t\t},\n\t}\n}\n\nfunc ImageName(repo, version string) string {\n\treturn fmt.Sprintf(\"%s:v%v\", repo, version)\n}\n\n// imageNameBusybox returns the default image for busybox init container, or the image specified in the PodPolicy\nfunc imageNameBusybox(policy *api.PodPolicy) string {\n\tif policy != nil && len(policy.BusyboxImage) > 0 {\n\t\treturn policy.BusyboxImage\n\t}\n\treturn defaultBusyboxImage\n}\n\nfunc PodWithNodeSelector(p *v1.Pod, ns map[string]string) *v1.Pod {\n\tp.Spec.NodeSelector = ns\n\treturn p\n}\n\nfunc CreateClientService(kubecli kubernetes.Interface, clusterName, ns string, owner metav1.OwnerReference) error {\n\tports := []v1.ServicePort{{\n\t\tName:       \"client\",\n\t\tPort:       EtcdClientPort,\n\t\tTargetPort: intstr.FromInt(EtcdClientPort),\n\t\tProtocol:   v1.ProtocolTCP,\n\t}}\n\treturn createService(kubecli, ClientServiceName(clusterName), clusterName, ns, \"\", ports, owner, false)\n}\n\nfunc ClientServiceName(clusterName string) string {\n\treturn clusterName + \"-client\"\n}\n\nfunc CreatePeerService(kubecli kubernetes.Interface, clusterName, ns string, owner metav1.OwnerReference) error {\n\tports := []v1.ServicePort{{\n\t\tName:       \"client\",\n\t\tPort:       EtcdClientPort,\n\t\tTargetPort: intstr.FromInt(EtcdClientPort),\n\t\tProtocol:   v1.ProtocolTCP,\n\t}, {\n\t\tName:       \"peer\",\n\t\tPort:       2380,\n\t\tTargetPort: intstr.FromInt(2380),\n\t\tProtocol:   v1.ProtocolTCP,\n\t}}\n\n\treturn createService(kubecli, clusterName, clusterName, ns, v1.ClusterIPNone, ports, owner, true)\n}\n\nfunc createService(kubecli kubernetes.Interface, svcName, clusterName, ns, clusterIP string, ports []v1.ServicePort, owner metav1.OwnerReference, publishNotReadyAddresses bool) error {\n\tsvc := newEtcdServiceManifest(svcName, clusterName, clusterIP, ports, publishNotReadyAddresses)\n\taddOwnerRefToObject(svc.GetObjectMeta(), owner)\n\t_, err := kubecli.CoreV1().Services(ns).Create(svc)\n\tif err != nil && !apierrors.IsAlreadyExists(err) {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// CreateAndWaitPod creates a pod and waits until it is running\nfunc CreateAndWaitPod(kubecli kubernetes.Interface, ns string, pod *v1.Pod, timeout time.Duration) (*v1.Pod, error) {\n\t_, err := kubecli.CoreV1().Pods(ns).Create(pod)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tinterval := 5 * time.Second\n\tvar retPod *v1.Pod\n\terr = retryutil.Retry(interval, int(timeout/(interval)), func() (bool, error) {\n\t\tretPod, err = kubecli.CoreV1().Pods(ns).Get(pod.Name, metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\tswitch retPod.Status.Phase {\n\t\tcase v1.PodRunning:\n\t\t\treturn true, nil\n\t\tcase v1.PodPending:\n\t\t\treturn false, nil\n\t\tdefault:\n\t\t\treturn false, fmt.Errorf(\"unexpected pod status.phase: %v\", retPod.Status.Phase)\n\t\t}\n\t})\n\n\tif err != nil {\n\t\tif retryutil.IsRetryFailure(err) {\n\t\t\treturn nil, fmt.Errorf(\"failed to wait pod running, it is still pending: %v\", err)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"failed to wait pod running: %v\", err)\n\t}\n\n\treturn retPod, nil\n}\n\nfunc newEtcdServiceManifest(svcName, clusterName, clusterIP string, ports []v1.ServicePort, publishNotReadyAddresses bool) *v1.Service {\n\tlabels := LabelsForCluster(clusterName)\n\tsvc := &v1.Service{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:   svcName,\n\t\t\tLabels: labels,\n\t\t\tAnnotations: map[string]string{\n\t\t\t\tTolerateUnreadyEndpointsAnnotation: strconv.FormatBool(publishNotReadyAddresses),\n\t\t\t},\n\t\t},\n\t\tSpec: v1.ServiceSpec{\n\t\t\tPorts:     ports,\n\t\t\tSelector:  labels,\n\t\t\tClusterIP: clusterIP,\n\t\t\t// PublishNotReadyAddresses: publishNotReadyAddresses, // TODO(ckoehn): Activate once TolerateUnreadyEndpointsAnnotation is deprecated.\n\t\t},\n\t}\n\treturn svc\n}\n\n// AddEtcdVolumeToPod abstract the process of appending volume spec to pod spec\nfunc AddEtcdVolumeToPod(pod *v1.Pod, pvc *v1.PersistentVolumeClaim) {\n\tvol := v1.Volume{Name: etcdVolumeName}\n\tif pvc != nil {\n\t\tvol.VolumeSource = v1.VolumeSource{\n\t\t\tPersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ClaimName: pvc.Name},\n\t\t}\n\t} else {\n\t\tvol.VolumeSource = v1.VolumeSource{EmptyDir: &v1.EmptyDirVolumeSource{}}\n\t}\n\tpod.Spec.Volumes = append(pod.Spec.Volumes, vol)\n}\n\nfunc addRecoveryToPod(pod *v1.Pod, token string, m *etcdutil.Member, cs api.ClusterSpec, backupURL *url.URL) {\n\tpod.Spec.InitContainers = append(pod.Spec.InitContainers,\n\t\tmakeRestoreInitContainers(backupURL, token, cs.Repository, cs.Version, m)...)\n}\n\nfunc addOwnerRefToObject(o metav1.Object, r metav1.OwnerReference) {\n\to.SetOwnerReferences(append(o.GetOwnerReferences(), r))\n}\n\n// NewSeedMemberPod returns a Pod manifest for a seed member.\n// It's special that it has new token, and might need recovery init containers\nfunc NewSeedMemberPod(clusterName string, ms etcdutil.MemberSet, m *etcdutil.Member, cs api.ClusterSpec, owner metav1.OwnerReference, backupURL *url.URL) *v1.Pod {\n\ttoken := uuid.New()\n\tpod := newEtcdPod(m, ms.PeerURLPairs(), clusterName, \"new\", token, cs)\n\t// TODO: PVC datadir support for restore process\n\tAddEtcdVolumeToPod(pod, nil)\n\tif backupURL != nil {\n\t\taddRecoveryToPod(pod, token, m, cs, backupURL)\n\t}\n\tapplyPodPolicy(clusterName, pod, cs.Pod)\n\taddOwnerRefToObject(pod.GetObjectMeta(), owner)\n\treturn pod\n}\n\n// NewEtcdPodPVC create PVC object from etcd pod's PVC spec\nfunc NewEtcdPodPVC(m *etcdutil.Member, pvcSpec v1.PersistentVolumeClaimSpec, clusterName, namespace string, owner metav1.OwnerReference) *v1.PersistentVolumeClaim {\n\tpvc := &v1.PersistentVolumeClaim{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      PVCNameFromMember(m.Name),\n\t\t\tNamespace: namespace,\n\t\t\tLabels:    LabelsForCluster(clusterName),\n\t\t},\n\t\tSpec: pvcSpec,\n\t}\n\taddOwnerRefToObject(pvc.GetObjectMeta(), owner)\n\treturn pvc\n}\n\nfunc newEtcdPod(m *etcdutil.Member, initialCluster []string, clusterName, state, token string, cs api.ClusterSpec) *v1.Pod {\n\tcommands := fmt.Sprintf(\"/usr/local/bin/etcd --data-dir=%s --name=%s --initial-advertise-peer-urls=%s \"+\n\t\t\"--listen-peer-urls=%s --listen-client-urls=%s --advertise-client-urls=%s \"+\n\t\t\"--initial-cluster=%s --initial-cluster-state=%s\",\n\t\tdataDir, m.Name, m.PeerURL(), m.ListenPeerURL(), m.ListenClientURL(), m.ClientURL(), strings.Join(initialCluster, \",\"), state)\n\tif m.SecurePeer {\n\t\tcommands += fmt.Sprintf(\" --peer-client-cert-auth=true --peer-trusted-ca-file=%[1]s/peer-ca.crt --peer-cert-file=%[1]s/peer.crt --peer-key-file=%[1]s/peer.key\", peerTLSDir)\n\t}\n\tif m.SecureClient {\n\t\tcommands += fmt.Sprintf(\" --client-cert-auth=true --trusted-ca-file=%[1]s/server-ca.crt --cert-file=%[1]s/server.crt --key-file=%[1]s/server.key\", serverTLSDir)\n\t}\n\tif state == \"new\" {\n\t\tcommands = fmt.Sprintf(\"%s --initial-cluster-token=%s\", commands, token)\n\t}\n\n\tlabels := map[string]string{\n\t\t\"app\":          \"etcd\",\n\t\t\"etcd_node\":    m.Name,\n\t\t\"etcd_cluster\": clusterName,\n\t}\n\n\tlivenessProbe := newEtcdProbe(cs.TLS.IsSecureClient())\n\treadinessProbe := newEtcdProbe(cs.TLS.IsSecureClient())\n\treadinessProbe.InitialDelaySeconds = 1\n\treadinessProbe.TimeoutSeconds = 5\n\treadinessProbe.PeriodSeconds = 5\n\treadinessProbe.FailureThreshold = 3\n\n\tcontainer := containerWithProbes(\n\t\tetcdContainer(strings.Split(commands, \" \"), cs.Repository, cs.Version),\n\t\tlivenessProbe,\n\t\treadinessProbe)\n\n\tvolumes := []v1.Volume{}\n\n\tif m.SecurePeer {\n\t\tcontainer.VolumeMounts = append(container.VolumeMounts, v1.VolumeMount{\n\t\t\tMountPath: peerTLSDir,\n\t\t\tName:      peerTLSVolume,\n\t\t})\n\t\tvolumes = append(volumes, v1.Volume{Name: peerTLSVolume, VolumeSource: v1.VolumeSource{\n\t\t\tSecret: &v1.SecretVolumeSource{SecretName: cs.TLS.Static.Member.PeerSecret},\n\t\t}})\n\t}\n\tif m.SecureClient {\n\t\tcontainer.VolumeMounts = append(container.VolumeMounts, v1.VolumeMount{\n\t\t\tMountPath: serverTLSDir,\n\t\t\tName:      serverTLSVolume,\n\t\t}, v1.VolumeMount{\n\t\t\tMountPath: operatorEtcdTLSDir,\n\t\t\tName:      operatorEtcdTLSVolume,\n\t\t})\n\t\tvolumes = append(volumes, v1.Volume{Name: serverTLSVolume, VolumeSource: v1.VolumeSource{\n\t\t\tSecret: &v1.SecretVolumeSource{SecretName: cs.TLS.Static.Member.ServerSecret},\n\t\t}}, v1.Volume{Name: operatorEtcdTLSVolume, VolumeSource: v1.VolumeSource{\n\t\t\tSecret: &v1.SecretVolumeSource{SecretName: cs.TLS.Static.OperatorSecret},\n\t\t}})\n\t}\n\n\tDNSTimeout := defaultDNSTimeout\n\tif cs.Pod != nil {\n\t\tDNSTimeout = cs.Pod.DNSTimeoutInSecond\n\t}\n\tpod := &v1.Pod{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:        m.Name,\n\t\t\tLabels:      labels,\n\t\t\tAnnotations: map[string]string{},\n\t\t},\n\t\tSpec: v1.PodSpec{\n\t\t\tInitContainers: []v1.Container{{\n\t\t\t\t// busybox:latest uses uclibc which contains a bug that sometimes prevents name resolution\n\t\t\t\t// More info: https://github.com/docker-library/busybox/issues/27\n\t\t\t\t//Image default: \"busybox:1.28.0-glibc\",\n\t\t\t\tImage: imageNameBusybox(cs.Pod),\n\t\t\t\tName:  \"check-dns\",\n\t\t\t\t// In etcd 3.2, TLS listener will do a reverse-DNS lookup for pod IP -> hostname.\n\t\t\t\t// If DNS entry is not warmed up, it will return empty result and peer connection will be rejected.\n\t\t\t\t// In some cases the DNS is not created correctly so we need to time out after a given period.\n\t\t\t\tCommand: []string{\"/bin/sh\", \"-c\", fmt.Sprintf(`\n\t\t\t\t\tTIMEOUT_READY=%d\n\t\t\t\t\twhile ( ! nslookup %s )\n\t\t\t\t\tdo\n\t\t\t\t\t\t# If TIMEOUT_READY is 0 we should never time out and exit \n\t\t\t\t\t\tTIMEOUT_READY=$(( TIMEOUT_READY-1 ))\n                        if [ $TIMEOUT_READY -eq 0 ];\n\t\t\t\t        then\n\t\t\t\t            echo \"Timed out waiting for DNS entry\"\n\t\t\t\t            exit 1\n\t\t\t\t        fi\n\t\t\t\t\t\tsleep 1\n\t\t\t\t\tdone`, DNSTimeout, m.Addr())},\n\t\t\t}},\n\t\t\tContainers:    []v1.Container{container},\n\t\t\tRestartPolicy: v1.RestartPolicyNever,\n\t\t\tVolumes:       volumes,\n\t\t\t// DNS A record: `[m.Name].[clusterName].Namespace.svc`\n\t\t\t// For example, etcd-795649v9kq in default namesapce will have DNS name\n\t\t\t// `etcd-795649v9kq.etcd.default.svc`.\n\t\t\tHostname:                     m.Name,\n\t\t\tSubdomain:                    clusterName,\n\t\t\tAutomountServiceAccountToken: func(b bool) *bool { return &b }(false),\n\t\t\tSecurityContext:              podSecurityContext(cs.Pod),\n\t\t},\n\t}\n\tSetEtcdVersion(pod, cs.Version)\n\treturn pod\n}\n\nfunc podSecurityContext(podPolicy *api.PodPolicy) *v1.PodSecurityContext {\n\tif podPolicy == nil {\n\t\treturn nil\n\t}\n\treturn podPolicy.SecurityContext\n}\n\nfunc NewEtcdPod(m *etcdutil.Member, initialCluster []string, clusterName, state, token string, cs api.ClusterSpec, owner metav1.OwnerReference) *v1.Pod {\n\tpod := newEtcdPod(m, initialCluster, clusterName, state, token, cs)\n\tapplyPodPolicy(clusterName, pod, cs.Pod)\n\taddOwnerRefToObject(pod.GetObjectMeta(), owner)\n\treturn pod\n}\n\nfunc MustNewKubeClient() kubernetes.Interface {\n\tcfg, err := InClusterConfig()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn kubernetes.NewForConfigOrDie(cfg)\n}\n\nfunc InClusterConfig() (*rest.Config, error) {\n\t// Work around https://github.com/kubernetes/kubernetes/issues/40973\n\t// See https://github.com/coreos/etcd-operator/issues/731#issuecomment-283804819\n\tif len(os.Getenv(\"KUBERNETES_SERVICE_HOST\")) == 0 {\n\t\taddrs, err := net.LookupHost(\"kubernetes.default.svc\")\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tos.Setenv(\"KUBERNETES_SERVICE_HOST\", addrs[0])\n\t}\n\tif len(os.Getenv(\"KUBERNETES_SERVICE_PORT\")) == 0 {\n\t\tos.Setenv(\"KUBERNETES_SERVICE_PORT\", \"443\")\n\t}\n\tcfg, err := clientcmd.BuildConfigFromFlags(\"\", \"\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn cfg, nil\n}\n\nfunc IsKubernetesResourceAlreadyExistError(err error) bool {\n\treturn apierrors.IsAlreadyExists(err)\n}\n\nfunc IsKubernetesResourceNotFoundError(err error) bool {\n\treturn apierrors.IsNotFound(err)\n}\n\n// We are using internal api types for cluster related.\nfunc ClusterListOpt(clusterName string) metav1.ListOptions {\n\treturn metav1.ListOptions{\n\t\tLabelSelector: labels.SelectorFromSet(LabelsForCluster(clusterName)).String(),\n\t}\n}\n\nfunc LabelsForCluster(clusterName string) map[string]string {\n\treturn map[string]string{\n\t\t\"etcd_cluster\": clusterName,\n\t\t\"app\":          \"etcd\",\n\t}\n}\n\nfunc CreatePatch(o, n, datastruct interface{}) ([]byte, error) {\n\toldData, err := json.Marshal(o)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tnewData, err := json.Marshal(n)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn strategicpatch.CreateTwoWayMergePatch(oldData, newData, datastruct)\n}\n\nfunc PatchDeployment(kubecli kubernetes.Interface, namespace, name string, updateFunc func(*appsv1beta1.Deployment)) error {\n\tod, err := kubecli.AppsV1beta1().Deployments(namespace).Get(name, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn err\n\t}\n\tnd := od.DeepCopy()\n\tupdateFunc(nd)\n\tpatchData, err := CreatePatch(od, nd, appsv1beta1.Deployment{})\n\tif err != nil {\n\t\treturn err\n\t}\n\t_, err = kubecli.AppsV1beta1().Deployments(namespace).Patch(name, types.StrategicMergePatchType, patchData)\n\treturn err\n}\n\nfunc CascadeDeleteOptions(gracePeriodSeconds int64) *metav1.DeleteOptions {\n\treturn &metav1.DeleteOptions{\n\t\tGracePeriodSeconds: func(t int64) *int64 { return &t }(gracePeriodSeconds),\n\t\tPropagationPolicy: func() *metav1.DeletionPropagation {\n\t\t\tforeground := metav1.DeletePropagationForeground\n\t\t\treturn &foreground\n\t\t}(),\n\t}\n}\n\n// mergeLabels merges l2 into l1. Conflicting label will be skipped.\nfunc mergeLabels(l1, l2 map[string]string) {\n\tfor k, v := range l2 {\n\t\tif _, ok := l1[k]; ok {\n\t\t\tcontinue\n\t\t}\n\t\tl1[k] = v\n\t}\n}\n\nfunc UniqueMemberName(clusterName string) string {\n\tsuffix := utilrand.String(randomSuffixLength)\n\tif len(clusterName) > MaxNameLength {\n\t\tclusterName = clusterName[:MaxNameLength]\n\t}\n\treturn clusterName + \"-\" + suffix\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/k8sutil/k8sutils_test.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage k8sutil\n\nimport (\n\t\"testing\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n)\n\nfunc TestDefaultBusyboxImageName(t *testing.T) {\n\tpolicy := &api.PodPolicy{}\n\timage := imageNameBusybox(policy)\n\texpected := defaultBusyboxImage\n\tif image != expected {\n\t\tt.Errorf(\"expect image=%s, get=%s\", expected, image)\n\t}\n}\n\nfunc TestDefaultNilBusyboxImageName(t *testing.T) {\n\timage := imageNameBusybox(nil)\n\texpected := defaultBusyboxImage\n\tif image != expected {\n\t\tt.Errorf(\"expect image=%s, get=%s\", expected, image)\n\t}\n}\n\nfunc TestSetBusyboxImageName(t *testing.T) {\n\tpolicy := &api.PodPolicy{\n\t\tBusyboxImage: \"myRepo/busybox:1.3.2\",\n\t}\n\timage := imageNameBusybox(policy)\n\texpected := \"myRepo/busybox:1.3.2\"\n\tif image != expected {\n\t\tt.Errorf(\"expect image=%s, get=%s\", expected, image)\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/k8sutil/node_util.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage k8sutil\n\nimport (\n\t\"k8s.io/api/core/v1\"\n)\n\n// IsNodeReady checks if the Node condition is ready.\nfunc IsNodeReady(n v1.Node) bool {\n\tfor _, cd := range n.Status.Conditions {\n\t\tif cd.Type == v1.NodeReady {\n\t\t\treturn cd.Status == v1.ConditionTrue\n\t\t}\n\t}\n\n\treturn false\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/k8sutil/pod_util.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage k8sutil\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/util/etcdutil\"\n\n\t\"k8s.io/api/core/v1\"\n)\n\nconst (\n\tetcdVolumeName = \"etcd-data\"\n)\n\nfunc etcdVolumeMounts() []v1.VolumeMount {\n\treturn []v1.VolumeMount{\n\t\t{Name: etcdVolumeName, MountPath: etcdVolumeMountDir},\n\t}\n}\n\nfunc etcdContainer(cmd []string, repo, version string) v1.Container {\n\tc := v1.Container{\n\t\tCommand: cmd,\n\t\tName:    \"etcd\",\n\t\tImage:   ImageName(repo, version),\n\t\tPorts: []v1.ContainerPort{\n\t\t\t{\n\t\t\t\tName:          \"server\",\n\t\t\t\tContainerPort: int32(2380),\n\t\t\t\tProtocol:      v1.ProtocolTCP,\n\t\t\t},\n\t\t\t{\n\t\t\t\tName:          \"client\",\n\t\t\t\tContainerPort: int32(EtcdClientPort),\n\t\t\t\tProtocol:      v1.ProtocolTCP,\n\t\t\t},\n\t\t},\n\t\tVolumeMounts: etcdVolumeMounts(),\n\t}\n\n\treturn c\n}\n\nfunc containerWithProbes(c v1.Container, lp *v1.Probe, rp *v1.Probe) v1.Container {\n\tc.LivenessProbe = lp\n\tc.ReadinessProbe = rp\n\treturn c\n}\n\nfunc containerWithRequirements(c v1.Container, r v1.ResourceRequirements) v1.Container {\n\tc.Resources = r\n\treturn c\n}\n\nfunc newEtcdProbe(isSecure bool) *v1.Probe {\n\t// etcd pod is healthy only if it can participate in consensus\n\tcmd := \"ETCDCTL_API=3 etcdctl endpoint status\"\n\tif isSecure {\n\t\ttlsFlags := fmt.Sprintf(\"--cert=%[1]s/%[2]s --key=%[1]s/%[3]s --cacert=%[1]s/%[4]s\", operatorEtcdTLSDir, etcdutil.CliCertFile, etcdutil.CliKeyFile, etcdutil.CliCAFile)\n\t\tcmd = fmt.Sprintf(\"ETCDCTL_API=3 etcdctl --endpoints=https://localhost:%d %s endpoint status\", EtcdClientPort, tlsFlags)\n\t}\n\treturn &v1.Probe{\n\t\tHandler: v1.Handler{\n\t\t\tExec: &v1.ExecAction{\n\t\t\t\tCommand: []string{\"/bin/sh\", \"-ec\", cmd},\n\t\t\t},\n\t\t},\n\t\tInitialDelaySeconds: 10,\n\t\tTimeoutSeconds:      10,\n\t\tPeriodSeconds:       60,\n\t\tFailureThreshold:    3,\n\t}\n}\n\nfunc applyPodPolicy(clusterName string, pod *v1.Pod, policy *api.PodPolicy) {\n\tif policy == nil {\n\t\treturn\n\t}\n\n\tif policy.Affinity != nil {\n\t\tpod.Spec.Affinity = policy.Affinity\n\t}\n\n\tif len(policy.NodeSelector) != 0 {\n\t\tpod = PodWithNodeSelector(pod, policy.NodeSelector)\n\t}\n\tif len(policy.Tolerations) != 0 {\n\t\tpod.Spec.Tolerations = policy.Tolerations\n\t}\n\n\tmergeLabels(pod.Labels, policy.Labels)\n\n\tfor i := range pod.Spec.Containers {\n\t\tpod.Spec.Containers[i] = containerWithRequirements(pod.Spec.Containers[i], policy.Resources)\n\t\tif pod.Spec.Containers[i].Name == \"etcd\" {\n\t\t\tpod.Spec.Containers[i].Env = append(pod.Spec.Containers[i].Env, policy.EtcdEnv...)\n\t\t}\n\t}\n\n\tfor i := range pod.Spec.InitContainers {\n\t\tpod.Spec.InitContainers[i] = containerWithRequirements(pod.Spec.InitContainers[i], policy.Resources)\n\t}\n\n\tfor key, value := range policy.Annotations {\n\t\tpod.ObjectMeta.Annotations[key] = value\n\t}\n}\n\n// IsPodReady returns false if the Pod Status is nil\nfunc IsPodReady(pod *v1.Pod) bool {\n\tcondition := getPodReadyCondition(&pod.Status)\n\treturn condition != nil && condition.Status == v1.ConditionTrue\n}\n\nfunc getPodReadyCondition(status *v1.PodStatus) *v1.PodCondition {\n\tfor i := range status.Conditions {\n\t\tif status.Conditions[i].Type == v1.PodReady {\n\t\t\treturn &status.Conditions[i]\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc PodSpecToPrettyJSON(pod *v1.Pod) (string, error) {\n\tbytes, err := json.MarshalIndent(pod.Spec, \"\", \"    \")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn string(bytes), nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/k8sutil/tls.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage k8sutil\n\nimport (\n\t\"github.com/coreos/etcd-operator/pkg/util/etcdutil\"\n\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n)\n\ntype TLSData struct {\n\tCertData []byte\n\tKeyData  []byte\n\tCAData   []byte\n}\n\n// GetTLSDataFromSecret retrives the kubernete secret that contain etcd tls certs and put them into TLSData.\nfunc GetTLSDataFromSecret(kubecli kubernetes.Interface, ns, se string) (*TLSData, error) {\n\tsecret, err := kubecli.CoreV1().Secrets(ns).Get(se, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &TLSData{\n\t\tCertData: secret.Data[etcdutil.CliCertFile],\n\t\tKeyData:  secret.Data[etcdutil.CliKeyFile],\n\t\tCAData:   secret.Data[etcdutil.CliCAFile],\n\t}, nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/probe/readyz.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage probe\n\nimport (\n\t\"net/http\"\n\t\"sync\"\n)\n\nconst (\n\tHTTPReadyzEndpoint = \"/readyz\"\n)\n\nvar (\n\tmu    sync.Mutex\n\tready = false\n)\n\nfunc SetReady() {\n\tmu.Lock()\n\tready = true\n\tmu.Unlock()\n}\n\n// ReadyzHandler writes back the HTTP status code 200 if the operator is ready, and 500 otherwise\nfunc ReadyzHandler(w http.ResponseWriter, r *http.Request) {\n\tmu.Lock()\n\tisReady := ready\n\tmu.Unlock()\n\tif isReady {\n\t\tw.WriteHeader(http.StatusOK)\n\t} else {\n\t\tw.WriteHeader(http.StatusInternalServerError)\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/retryutil/retry_util.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage retryutil\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\ntype RetryError struct {\n\tn int\n}\n\nfunc (e *RetryError) Error() string {\n\treturn fmt.Sprintf(\"still failing after %d retries\", e.n)\n}\n\nfunc IsRetryFailure(err error) bool {\n\t_, ok := err.(*RetryError)\n\treturn ok\n}\n\ntype ConditionFunc func() (bool, error)\n\n// Retry retries f every interval until after maxRetries.\n// The interval won't be affected by how long f takes.\n// For example, if interval is 3s, f takes 1s, another f will be called 2s later.\n// However, if f takes longer than interval, it will be delayed.\nfunc Retry(interval time.Duration, maxRetries int, f ConditionFunc) error {\n\tif maxRetries <= 0 {\n\t\treturn fmt.Errorf(\"maxRetries (%d) should be > 0\", maxRetries)\n\t}\n\ttick := time.NewTicker(interval)\n\tdefer tick.Stop()\n\n\tfor i := 0; ; i++ {\n\t\tok, err := f()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif ok {\n\t\t\treturn nil\n\t\t}\n\t\tif i == maxRetries {\n\t\t\tbreak\n\t\t}\n\t\t<-tick.C\n\t}\n\treturn &RetryError{maxRetries}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/tencentcloudutil/cosfactory/client.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage cosfactory\n\nimport (\n\t\"fmt\"\n\t\"github.com/coreos/etcd-operator/pkg/util/tencentcloudutil/metadata/credential\"\n\t\"net/http\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\n\tcos \"github.com/tencentyun/cos-go-sdk-v5\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n)\n\n// COSClient is a wrapper for COS client that provides cleanup functionality.\ntype COSClient struct {\n\tCOS *cos.Client\n}\n\n// NewClientFromSecret returns a COS client based on given k8s secret containing cos credentials.\nfunc NewClientFromSecret(kubecli kubernetes.Interface, namespace, cosSecret string) (w *COSClient, err error) {\n\tdefer func() {\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"new COS client failed: %v\", err)\n\t\t}\n\t}()\n\tw = &COSClient{}\n\tse, err := kubecli.CoreV1().Secrets(namespace).Get(cosSecret, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"setup COS config failed: get k8s secret(%s) failed: %v\", namespace, err)\n\t}\n\tsecretId, exist := se.Data[api.COSSecretId]\n\tif !exist {\n\t\treturn nil, fmt.Errorf(\"Get SecretId failed: %v\", err)\n\t}\n\tsecretKey, exist := se.Data[api.COSSecretKey]\n\tif !exist {\n\t\treturn nil, fmt.Errorf(\"Get SecretKey failed: %v\", err)\n\t}\n\tw.COS = cos.NewClient(nil, &http.Client{\n\t\tTransport: &cos.AuthorizationTransport{\n\t\t\tSecretID:  string(secretId),\n\t\t\tSecretKey: string(secretKey),\n\t\t},\n\t})\n\treturn w, nil\n}\n\nfunc NewClientFromMetadata(role string) (w *COSClient, err error) {\n\tcred := credential.NewCredential(role)\n\tsecretId, secretKey, token, err := cred.GetSecret()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &COSClient{\n\t\tCOS: cos.NewClient(nil, &http.Client{\n\t\t\tTransport: &cos.AuthorizationTransport{\n\t\t\t\tSecretID:     secretId,\n\t\t\t\tSecretKey:    secretKey,\n\t\t\t\tSessionToken: token,\n\t\t\t},\n\t\t}),\n\t}, nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/tencentcloudutil/metadata/credential/secret.go",
    "content": "package credential\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n)\n\ntype metadataResponse struct {\n\tTmpSecretId  string\n\tTmpSecretKey string\n\tToken        string\n\tExpiredTime  int64\n\tCode         string\n}\n\ntype Credential struct {\n\tsync.Mutex\n\texpiredTime int64\n\tid          string\n\tkey         string\n\ttoken       string\n\trole        string\n}\n\nfunc NewCredential(role string) *Credential {\n\treturn &Credential{\n\t\trole: role,\n\t}\n}\n\nfunc (c *Credential) GetSecret() (string, string, string, error) {\n\tc.Lock()\n\tdefer c.Unlock()\n\n\tif time.Now().Unix() > c.expiredTime {\n\t\tif err := c.refresh(); err != nil {\n\t\t\treturn \"\", \"\", \"\", err\n\t\t}\n\t}\n\treturn c.id, c.key, c.token, nil\n}\n\nfunc (c *Credential) refresh() error {\n\tres, err := http.Get(fmt.Sprintf(\"http://metadata.tencentyun.com/meta-data/cam/service-role-security-credentials/%s\", c.role))\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"http get failed\")\n\t}\n\n\tif res.StatusCode != 200 {\n\t\t_ = res.Body.Close()\n\t\tres, err = http.Get(fmt.Sprintf(\"http://metadata.tencentyun.com/meta-data/cam/security-credentials/%s\", c.role))\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"http get failed\")\n\t\t}\n\t\tif res.StatusCode != 200 {\n\t\t\treturn fmt.Errorf(\"status code is %d\", res.StatusCode)\n\t\t}\n\t}\n\n\tdefer func() { _ = res.Body.Close() }()\n\n\tdata, err := ioutil.ReadAll(res.Body)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"read data failed\")\n\t}\n\n\tmetaData := &metadataResponse{}\n\tif err := json.Unmarshal(data, metaData); err != nil {\n\t\treturn errors.Wrapf(err, \"unmarshal failed\")\n\t}\n\n\tif metaData.Code != \"Success\" {\n\t\treturn fmt.Errorf(\"get Code is %s\", metaData.Code)\n\t}\n\n\tc.id = metaData.TmpSecretId\n\tc.key = metaData.TmpSecretKey\n\tc.token = metaData.Token\n\tc.expiredTime = metaData.ExpiredTime\n\treturn nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/pkg/util/util.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage util\n\n// PresentIn returns true if the given string is part of an array of strings\nfunc PresentIn(a string, list []string) bool {\n\tfor _, l := range list {\n\t\tif a == l {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/container/Dockerfile",
    "content": "# golang:X-alpine can't be used since it does not support the race detector flag which assumes a glibc based system, whereas alpine linux uses musl libc\n# https://github.com/golang/go/issues/14481\nFROM golang:1.11.5\n\nRUN curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.8.2/bin/linux/amd64/kubectl \\\n    && chmod +x ./kubectl \\\n    && mv ./kubectl /usr/local/bin/kubectl\n\nADD ./ /go/src/github.com/coreos/etcd-operator\n\nADD ./_test/aws /aws\n\nWORKDIR /go/src/github.com/coreos/etcd-operator\n\nRUN rm -rf _output _test .git .gitignore\n\nENTRYPOINT [\"./test/container/run\"]\n"
  },
  {
    "path": "third_party/etcd-operator/test/container/docker_push",
    "content": "#!/usr/bin/env bash\n\n# This script builds and pushes the test-container image\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nif ! which docker > /dev/null; then\n\techo \"docker needs to be installed\"\n\texit 1\nfi\n\n: ${TEST_IMAGE:?\"Need to set TEST_IMAGE\"}\n\necho \"building test-container image...\"\ndocker build --tag \"${TEST_IMAGE}\" -f test/container/Dockerfile . 1>/dev/null\n\n# For gcr users, do \"gcloud docker -a\" to have access.\necho \"pushing test-container image...\"\ndocker push \"${TEST_IMAGE}\" 1>/dev/null\n"
  },
  {
    "path": "third_party/etcd-operator/test/container/run",
    "content": "#!/usr/bin/env bash\n\nset -o errexit\nset -o pipefail\n\nKUBECONFIG=${KUBECONFIG:-\"/kubeconfig\"}\n\nexport OPERATOR_IMAGE=\"quay.io/coreos/etcd-operator:dev\"\n\n# Create test namespace\nexport TEST_NAMESPACE=$(cat <<EOF | kubectl create -f - | awk '{print $2}' | tr -d '\"'\napiVersion: v1\nkind: Namespace\nmetadata:\n  generateName: etcd-operator-test-\nEOF\n)\n\necho \"TEST_NAMESPACE: ${TEST_NAMESPACE}\"\necho \"OPERATOR_IMAGE: ${OPERATOR_IMAGE}\"\n\nexport TEST_AWS_SECRET=\"aws\"\nAWS_DIR=${AWS_DIR:-\"/aws\"}\n\nsource hack/ci/rbac_utils.sh\n# Cleanup namespace and rbac\nfunction finish {\n\tkubectl delete namespace $TEST_NAMESPACE || :\n\trbac_cleanup || :\n}\ntrap finish EXIT\n\n# Setup rbac\nif rbac_setup ; then\n    echo \"RBAC setup success! ===\"\nelse\n    echo \"RBAC setup fail! ===\"\n    exit 1\nfi\n\n# Create aws secret\nkubectl -n $TEST_NAMESPACE create secret generic $TEST_AWS_SECRET --from-file=$AWS_DIR/credentials --from-file=$AWS_DIR/config\nkubectl get nodes\n\n# Run e2e tests\nexport PASSES=\"e2e e2eslow\"\nexport TEST_S3_BUCKET=\"jenkins-testing-operator\"\n\n# Save test logs at /out\nmkdir -p /out\nhack/test 2>&1 | tee /out/e2e-testing.log\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/README.md",
    "content": "# E2E Testing\n\nEnd-to-end (e2e) testing is automated testing for real user scenarios.\n\n## Build and run test\n\nPrerequisites:\n- a running k8s cluster and kube config. We will need to pass kube config as arguments.\n- Have kubeconfig file ready.\n- Have etcd operator image ready.\n\ne2e tests are written as go test. All go test techniques applies, e.g. picking what to run, timeout length.\nLet's say I want to run all tests in \"test/e2e/\":\n```\n$ go test -v ./test/e2e/ --kubeconfig \"$HOME/.kube/config\" --operator-image=gcr.io/coreos-k8s-scale-testing/etcd-operator\n```\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/basic_test.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage e2e\n\nimport (\n\t\"os\"\n\t\"testing\"\n\t\"time\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/test/e2e/e2eutil\"\n\t\"github.com/coreos/etcd-operator/test/e2e/framework\"\n)\n\nfunc TestCreateCluster(t *testing.T) {\n\tif os.Getenv(envParallelTest) == envParallelTestTrue {\n\t\tt.Parallel()\n\t}\n\tf := framework.Global\n\ttestEtcd, err := e2eutil.CreateCluster(t, f.CRClient, f.Namespace, e2eutil.NewCluster(\"test-etcd-\", 3))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tdefer func() {\n\t\tif err := e2eutil.DeleteCluster(t, f.CRClient, f.KubeClient, testEtcd); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\tif _, err := e2eutil.WaitUntilSizeReached(t, f.CRClient, 3, 6, testEtcd); err != nil {\n\t\tt.Fatalf(\"failed to create 3 members etcd cluster: %v\", err)\n\t}\n}\n\n// TestPauseControl tests the user can pause the operator from controlling\n// an etcd cluster.\nfunc TestPauseControl(t *testing.T) {\n\tif os.Getenv(envParallelTest) == envParallelTestTrue {\n\t\tt.Parallel()\n\t}\n\n\tf := framework.Global\n\ttestEtcd, err := e2eutil.CreateCluster(t, f.CRClient, f.Namespace, e2eutil.NewCluster(\"test-etcd-\", 3))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\tif err := e2eutil.DeleteCluster(t, f.CRClient, f.KubeClient, testEtcd); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\tnames, err := e2eutil.WaitUntilSizeReached(t, f.CRClient, 3, 6, testEtcd)\n\tif err != nil {\n\t\tt.Fatalf(\"failed to create 3 members etcd cluster: %v\", err)\n\t}\n\n\tupdateFunc := func(cl *api.EtcdCluster) {\n\t\tcl.Spec.Paused = true\n\t}\n\tif testEtcd, err = e2eutil.UpdateCluster(f.CRClient, testEtcd, 10, updateFunc); err != nil {\n\t\tt.Fatalf(\"failed to pause control: %v\", err)\n\t}\n\n\t// TODO: this is used to wait for the CR to be updated.\n\t// TODO: make this wait for reliable\n\ttime.Sleep(5 * time.Second)\n\n\tif err := e2eutil.KillMembers(f.KubeClient, f.Namespace, names[0]); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif _, err := e2eutil.WaitUntilPodSizeReached(t, f.KubeClient, 2, 1, testEtcd); err != nil {\n\t\tt.Fatalf(\"failed to wait for killed member to die: %v\", err)\n\t}\n\tif _, err := e2eutil.WaitUntilPodSizeReached(t, f.KubeClient, 3, 1, testEtcd); err == nil {\n\t\tt.Fatalf(\"cluster should not be recovered: control is paused\")\n\t}\n\n\tupdateFunc = func(cl *api.EtcdCluster) {\n\t\tcl.Spec.Paused = false\n\t}\n\tif testEtcd, err = e2eutil.UpdateCluster(f.CRClient, testEtcd, 10, updateFunc); err != nil {\n\t\tt.Fatalf(\"failed to resume control: %v\", err)\n\t}\n\n\tif _, err := e2eutil.WaitUntilSizeReached(t, f.CRClient, 3, 6, testEtcd); err != nil {\n\t\tt.Fatalf(\"failed to resize to 3 members etcd cluster: %v\", err)\n\t}\n}\n\nfunc TestEtcdUpgrade(t *testing.T) {\n\tif os.Getenv(envParallelTest) == envParallelTestTrue {\n\t\tt.Parallel()\n\t}\n\tf := framework.Global\n\torigEtcd := e2eutil.NewCluster(\"test-etcd-\", 3)\n\torigEtcd = e2eutil.ClusterWithVersion(origEtcd, \"3.1.10\")\n\torigEtcd.Spec.Repository = \"quay.io/coreos/etcd\"\n\ttestEtcd, err := e2eutil.CreateCluster(t, f.CRClient, f.Namespace, origEtcd)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tdefer func() {\n\t\tif err := e2eutil.DeleteCluster(t, f.CRClient, f.KubeClient, testEtcd); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\terr = e2eutil.WaitSizeAndVersionReached(t, f.KubeClient, \"3.1.10\", 3, 6, testEtcd)\n\tif err != nil {\n\t\tt.Fatalf(\"failed to create 3 members etcd cluster: %v\", err)\n\t}\n\n\ttargetVersion := \"3.2.13\"\n\tupdateFunc := func(cl *api.EtcdCluster) {\n\t\tcl = e2eutil.ClusterWithVersion(cl, targetVersion)\n\t}\n\t_, err = e2eutil.UpdateCluster(f.CRClient, testEtcd, 10, updateFunc)\n\tif err != nil {\n\t\tt.Fatalf(\"fail to update cluster version: %v\", err)\n\t}\n\n\t// We have seen in k8s 1.7.1 env it took 35s for the pod to restart with the new image.\n\terr = e2eutil.WaitSizeAndVersionReached(t, f.KubeClient, targetVersion, 3, 10, testEtcd)\n\tif err != nil {\n\t\tt.Fatalf(\"failed to wait new version etcd cluster: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/cluster_status_test.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage e2e\n\nimport (\n\t\"os\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/coreos/etcd-operator/pkg/util/retryutil\"\n\t\"github.com/coreos/etcd-operator/test/e2e/e2eutil\"\n\t\"github.com/coreos/etcd-operator/test/e2e/framework\"\n\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\nfunc TestReadyMembersStatus(t *testing.T) {\n\tif os.Getenv(envParallelTest) == envParallelTestTrue {\n\t\tt.Parallel()\n\t}\n\tf := framework.Global\n\tsize := 1\n\ttestEtcd, err := e2eutil.CreateCluster(t, f.CRClient, f.Namespace, e2eutil.NewCluster(\"test-etcd-\", size))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tdefer func() {\n\t\tif err := e2eutil.DeleteCluster(t, f.CRClient, f.KubeClient, testEtcd); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\tif _, err := e2eutil.WaitUntilSizeReached(t, f.CRClient, size, 3, testEtcd); err != nil {\n\t\tt.Fatalf(\"failed to create %d members etcd cluster: %v\", size, err)\n\t}\n\n\terr = retryutil.Retry(5*time.Second, 3, func() (done bool, err error) {\n\t\tcurrEtcd, err := f.CRClient.EtcdV1beta2().EtcdClusters(f.Namespace).Get(testEtcd.Name, metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\te2eutil.LogfWithTimestamp(t, \"failed to get updated cluster object: %v\", err)\n\t\t\treturn false, nil\n\t\t}\n\t\tif len(currEtcd.Status.Members.Ready) != size {\n\t\t\te2eutil.LogfWithTimestamp(t, \"size of ready members want = %d, get = %d ReadyMembers(%v) UnreadyMembers(%v). Will retry checking ReadyMembers\", size, len(currEtcd.Status.Members.Ready), currEtcd.Status.Members.Ready, currEtcd.Status.Members.Unready)\n\t\t\treturn false, nil\n\t\t}\n\t\treturn true, nil\n\t})\n\tif err != nil {\n\t\tt.Fatalf(\"failed to get size of ReadyMembers to reach %d : %v\", size, err)\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/e2eslow/backup_restore_test.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage e2eslow\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"math/rand\"\n\t\"os\"\n\t\"path\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/backup/writer\"\n\t\"github.com/coreos/etcd-operator/pkg/util/awsutil/s3factory\"\n\t\"github.com/coreos/etcd-operator/pkg/util/etcdutil\"\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\t\"github.com/coreos/etcd-operator/pkg/util/retryutil\"\n\t\"github.com/coreos/etcd-operator/test/e2e/e2eutil\"\n\t\"github.com/coreos/etcd-operator/test/e2e/framework\"\n\n\t\"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n)\n\nfunc init() {\n\trand.Seed(time.Now().UTC().UnixNano())\n}\n\n// TestBackupAndRestore runs the backup test first, and only runs the restore test after if the backup test succeeds and sets the S3 path\nfunc TestBackupAndRestore(t *testing.T) {\n\tif err := verifyAWSEnvVars(); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Create cluster with TLS\n\tf := framework.Global\n\tsuffix := fmt.Sprintf(\"%d\", rand.Uint64())\n\tclusterName := \"test-etcd-backup-restore-\" + suffix\n\tmemberPeerTLSSecret := \"etcd-peer-tls-\" + suffix\n\tmemberClientTLSSecret := \"etcd-server-tls-\" + suffix\n\toperatorClientTLSSecret := \"etcd-client-tls-\" + suffix\n\terr := e2eutil.PrepareTLS(clusterName, f.Namespace, memberPeerTLSSecret, memberClientTLSSecret, operatorClientTLSSecret)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\terr := e2eutil.DeleteSecrets(f.KubeClient, f.Namespace, memberPeerTLSSecret, memberClientTLSSecret, operatorClientTLSSecret)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\tc := e2eutil.NewCluster(\"\", 3)\n\tc.Name = clusterName\n\te2eutil.ClusterCRWithTLS(c, memberPeerTLSSecret, memberClientTLSSecret, operatorClientTLSSecret)\n\ttestEtcd, err := e2eutil.CreateCluster(t, f.CRClient, f.Namespace, c)\n\tdefer func() {\n\t\tif err := e2eutil.DeleteCluster(t, f.CRClient, f.KubeClient, testEtcd); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\tif _, err := e2eutil.WaitUntilSizeReached(t, f.CRClient, 3, 6, testEtcd); err != nil {\n\t\tt.Fatalf(\"failed to create 3 members etcd cluster: %v\", err)\n\t}\n\n\ts3Path := path.Join(os.Getenv(\"TEST_S3_BUCKET\"), \"jenkins\", suffix, time.Now().Format(time.RFC3339), \"etcd.backup\")\n\n\t// Backup then restore tests\n\ttestEtcdBackupOperatorForS3Backup(t, clusterName, operatorClientTLSSecret, s3Path)\n\ttestEtcdRestoreOperatorForS3Source(t, clusterName, s3Path)\n\t// Periodic backup test\n\ttestEtcdBackupOperatorForPeriodicS3Backup(t, clusterName, operatorClientTLSSecret, s3Path)\n}\n\nfunc verifyAWSEnvVars() error {\n\tif len(os.Getenv(\"TEST_S3_BUCKET\")) == 0 {\n\t\treturn fmt.Errorf(\"TEST_S3_BUCKET not set\")\n\t}\n\tif len(os.Getenv(\"TEST_AWS_SECRET\")) == 0 {\n\t\treturn fmt.Errorf(\"TEST_AWS_SECRET not set\")\n\t}\n\treturn nil\n}\n\nfunc getEndpoints(kubeClient kubernetes.Interface, secureClient bool, namespace, clusterName string) ([]string, error) {\n\tpodList, err := kubeClient.Core().Pods(namespace).List(k8sutil.ClusterListOpt(clusterName))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar pods []*v1.Pod\n\tfor i := range podList.Items {\n\t\tpod := &podList.Items[i]\n\t\tif pod.Status.Phase == v1.PodRunning {\n\t\t\tpods = append(pods, pod)\n\t\t}\n\t}\n\n\tif len(pods) == 0 {\n\t\treturn nil, errors.New(\"no running etcd pods found\")\n\t}\n\n\tendpoints := make([]string, len(pods))\n\tfor i, pod := range pods {\n\t\tm := &etcdutil.Member{\n\t\t\tName:         pod.Name,\n\t\t\tNamespace:    pod.Namespace,\n\t\t\tSecureClient: secureClient,\n\t\t}\n\t\tendpoints[i] = m.ClientURL()\n\t}\n\treturn endpoints, nil\n}\n\n// testEtcdBackupOperatorForS3Backup tests if etcd backup operator can save etcd backup to S3.\n// It returns the full S3 path where the backup is saved.\nfunc testEtcdBackupOperatorForS3Backup(t *testing.T, clusterName, operatorClientTLSSecret, s3Path string) {\n\tf := framework.Global\n\n\tendpoints, err := getEndpoints(f.KubeClient, true, f.Namespace, clusterName)\n\tif err != nil {\n\t\tt.Fatalf(\"failed to get endpoints: %v\", err)\n\t}\n\tbackupCR := e2eutil.NewS3Backup(endpoints, clusterName, s3Path, os.Getenv(\"TEST_AWS_SECRET\"), operatorClientTLSSecret)\n\teb, err := f.CRClient.EtcdV1beta2().EtcdBackups(f.Namespace).Create(backupCR)\n\tif err != nil {\n\t\tt.Fatalf(\"failed to create etcd backup cr: %v\", err)\n\t}\n\tdefer func() {\n\t\tif err := f.CRClient.EtcdV1beta2().EtcdBackups(f.Namespace).Delete(eb.Name, nil); err != nil {\n\t\t\tt.Fatalf(\"failed to delete etcd backup cr: %v\", err)\n\t\t}\n\t}()\n\n\t// local testing shows that it takes around 1 - 2 seconds from creating backup cr to verifying the backup from s3.\n\t// 4 seconds timeout via retry is enough; duration longer than that may indicate internal issues and\n\t// is worthy of investigation.\n\terr = retryutil.Retry(time.Second, 4, func() (bool, error) {\n\t\treb, err := f.CRClient.EtcdV1beta2().EtcdBackups(f.Namespace).Get(eb.Name, metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\treturn false, fmt.Errorf(\"failed to retrieve backup CR: %v\", err)\n\t\t}\n\t\tif reb.Status.Succeeded {\n\t\t\tif reb.Status.EtcdVersion == api.DefaultEtcdVersion && reb.Status.EtcdRevision == 1 {\n\t\t\t\treturn true, nil\n\t\t\t}\n\t\t\treturn false, fmt.Errorf(\"expect EtcdVersion==%v and EtcdRevision==1, but got EtcdVersion==%v and EtcdRevision==%v\", api.DefaultEtcdVersion, reb.Status.EtcdVersion, reb.Status.EtcdRevision)\n\t\t}\n\t\tif len(reb.Status.Reason) != 0 {\n\t\t\treturn false, fmt.Errorf(\"backup failed with reason: %v \", reb.Status.Reason)\n\t\t}\n\t\treturn false, nil\n\t})\n\tif err != nil {\n\t\tt.Fatalf(\"failed to verify backup: %v\", err)\n\t}\n\tt.Logf(\"backup for cluster (%s) has been saved\", clusterName)\n}\n\n// testEtcdBackupOperatorForPeriodicS3Backup test if etcd backup operator can periodically backup and upload to s3.\n// This e2e test would check basic function of periodic backup and MaxBackup functionality\nfunc testEtcdBackupOperatorForPeriodicS3Backup(t *testing.T, clusterName, operatorClientTLSSecret, s3Path string) {\n\tf := framework.Global\n\n\tendpoints, err := getEndpoints(f.KubeClient, true, f.Namespace, clusterName)\n\tif err != nil {\n\t\tt.Fatalf(\"failed to get endpoints: %v\", err)\n\t}\n\tbackupCR := e2eutil.NewS3Backup(endpoints, clusterName, s3Path, os.Getenv(\"TEST_AWS_SECRET\"), operatorClientTLSSecret)\n\t// enable periodic backup\n\tbackupCR.Spec.BackupPolicy = &api.BackupPolicy{BackupIntervalInSecond: 5, MaxBackups: 2}\n\tbackupS3Source := backupCR.Spec.BackupSource.S3\n\n\t// initialize s3 client\n\ts3cli, err := s3factory.NewClientFromSecret(\n\t\tf.KubeClient, f.Namespace, backupS3Source.Endpoint, backupS3Source.AWSSecret, backupS3Source.ForcePathStyle)\n\tif err != nil {\n\t\tt.Fatalf(\"failed to initialize s3client: %v\", err)\n\t}\n\twr := writer.NewS3Writer(s3cli.S3)\n\n\t// check if there is existing backup file\n\tallBackups, err := wr.List(context.Background(), backupS3Source.Path)\n\tif err != nil {\n\t\tt.Fatalf(\"failed to list backup files: %v\", err)\n\t}\n\tif len(allBackups) > 0 {\n\t\tt.Logf(\"existing backup file is detected: %s\", strings.Join(allBackups, \",\"))\n\t\t// try to delete all existing backup files\n\t\tif err := e2eutil.DeleteBackupFiles(wr, allBackups); err != nil {\n\t\t\tt.Fatalf(\"failed to delete existing backup: %v\", err)\n\t\t}\n\t\t// make sure no exisiting backups\n\t\t// will wait for 10 sec until deleting operation completed\n\t\tif err := e2eutil.WaitUntilNoBackupFiles(wr, backupS3Source.Path, 10); err != nil {\n\t\t\tt.Fatalf(\"failed to make sure no old backup: %v\", err)\n\t\t}\n\t}\n\n\t// create etcdbackup resource\n\teb, err := f.CRClient.EtcdV1beta2().EtcdBackups(f.Namespace).Create(backupCR)\n\tif err != nil {\n\t\tt.Fatalf(\"failed to create etcd back cr: %v\", err)\n\t}\n\tdefer func() {\n\t\tif err := f.CRClient.EtcdV1beta2().EtcdBackups(f.Namespace).Delete(eb.Name, nil); err != nil {\n\t\t\tt.Fatalf(\"failed to delete etcd backup cr: %v\", err)\n\t\t}\n\t\t// cleanup backup files\n\t\tallBackups, err = wr.List(context.Background(), backupS3Source.Path)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"failed to list backup files: %v\", err)\n\t\t}\n\t\tif err := e2eutil.DeleteBackupFiles(wr, allBackups); err != nil {\n\t\t\tt.Fatalf(\"failed to cleanup backup files: %v\", err)\n\t\t}\n\t}()\n\n\tvar firstBackup string\n\tvar periodicBackup, maxBackup bool\n\t// Check if periodic backup is correctly performed\n\t// Check if maxBackup is correctly performed\n\terr = retryutil.Retry(time.Second, 20, func() (bool, error) {\n\t\tallBackups, err = wr.List(context.Background(), backupS3Source.Path)\n\t\tsort.Strings(allBackups)\n\t\tif err != nil {\n\t\t\treturn false, fmt.Errorf(\"failed to list backup files: %v\", err)\n\t\t}\n\t\tif len(allBackups) > 0 {\n\t\t\tif firstBackup == \"\" {\n\t\t\t\tfirstBackup = allBackups[0]\n\t\t\t}\n\t\t\t// Check if firt seen backup file is deleted or not\n\t\t\tif firstBackup != allBackups[0] {\n\t\t\t\tmaxBackup = true\n\t\t\t}\n\t\t\tif len(allBackups) > 1 {\n\t\t\t\tperiodicBackup = true\n\t\t\t}\n\t\t}\n\t\tif periodicBackup && maxBackup {\n\t\t\treturn true, nil\n\t\t}\n\t\treturn false, nil\n\t})\n\tif err != nil {\n\t\tt.Fatalf(\"failed to verify periodic bakcup: %v\", err)\n\t}\n}\n\n// testEtcdRestoreOperatorForS3Source tests if the restore-operator can restore an etcd cluster from an S3 restore source\nfunc testEtcdRestoreOperatorForS3Source(t *testing.T, clusterName, s3Path string) {\n\tf := framework.Global\n\n\trestoreSource := api.RestoreSource{S3: e2eutil.NewS3RestoreSource(s3Path, os.Getenv(\"TEST_AWS_SECRET\"))}\n\ter := e2eutil.NewEtcdRestore(clusterName, 3, restoreSource, api.BackupStorageTypeS3)\n\ter, err := f.CRClient.EtcdV1beta2().EtcdRestores(f.Namespace).Create(er)\n\tif err != nil {\n\t\tt.Fatalf(\"failed to create etcd restore cr: %v\", err)\n\t}\n\tdefer func() {\n\t\tif err := f.CRClient.EtcdV1beta2().EtcdRestores(f.Namespace).Delete(er.Name, nil); err != nil {\n\t\t\tt.Fatalf(\"failed to delete etcd restore cr: %v\", err)\n\t\t}\n\t}()\n\n\terr = retryutil.Retry(10*time.Second, 1, func() (bool, error) {\n\t\ter, err := f.CRClient.EtcdV1beta2().EtcdRestores(f.Namespace).Get(er.Name, metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\treturn false, fmt.Errorf(\"failed to retrieve restore CR: %v\", err)\n\t\t}\n\t\tif er.Status.Succeeded {\n\t\t\treturn true, nil\n\t\t} else if len(er.Status.Reason) != 0 {\n\t\t\treturn false, fmt.Errorf(\"restore failed with reason: %v \", er.Status.Reason)\n\t\t}\n\t\treturn false, nil\n\t})\n\tif err != nil {\n\t\tt.Fatalf(\"failed to verify restore succeeded: %v\", err)\n\t}\n\n\t// Verify that the restored etcd cluster scales to 3 ready members\n\trestoredCluster := &api.EtcdCluster{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      clusterName,\n\t\t\tNamespace: f.Namespace,\n\t\t},\n\t\tSpec: api.ClusterSpec{\n\t\t\tSize: 3,\n\t\t},\n\t}\n\tif _, err := e2eutil.WaitUntilSizeReached(t, f.CRClient, 3, 6, restoredCluster); err != nil {\n\t\tt.Fatalf(\"failed to see restored etcd cluster(%v) reach 3 members: %v\", restoredCluster.Name, err)\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/e2eslow/disruptive_test.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage e2eslow\n\nimport (\n\t\"testing\"\n\n\t\"github.com/coreos/etcd-operator/test/e2e/e2eutil\"\n\t\"github.com/coreos/etcd-operator/test/e2e/framework\"\n)\n\n// restart operator should resume cluster\nfunc TestRestartOperator(t *testing.T) {\n\tf := framework.Global\n\ttestEtcd, err := e2eutil.CreateCluster(t, f.CRClient, f.Namespace, e2eutil.NewCluster(\"test-etcd-\", 3))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\tif err := e2eutil.DeleteCluster(t, f.CRClient, f.KubeClient, testEtcd); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\tnames, err := e2eutil.WaitUntilSizeReached(t, f.CRClient, 3, 6, testEtcd)\n\tif err != nil {\n\t\tt.Fatalf(\"failed to create 3 members etcd cluster: %v\", err)\n\t}\n\n\tif err := f.DeleteEtcdOperatorCompletely(); err != nil {\n\t\tt.Fatalf(\"fail to delete etcd operator pod: %v\", err)\n\t}\n\n\tif err := e2eutil.KillMembers(f.KubeClient, f.Namespace, names[0]); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif _, err := e2eutil.WaitUntilPodSizeReached(t, f.KubeClient, 2, 1, testEtcd); err != nil {\n\t\tt.Fatalf(\"failed to wait for killed member to die: %v\", err)\n\t}\n\tif _, err := e2eutil.WaitUntilPodSizeReached(t, f.KubeClient, 3, 1, testEtcd); err == nil {\n\t\tt.Fatalf(\"cluster should not be recovered: operator is deleted\")\n\t}\n\n\tif err := f.SetupEtcdOperator(); err != nil {\n\t\tt.Fatalf(\"fail to restart etcd operator: %v\", err)\n\t}\n\n\tif _, err := e2eutil.WaitUntilSizeReached(t, f.CRClient, 3, 6, testEtcd); err != nil {\n\t\tt.Fatalf(\"failed to resize to 3 members etcd cluster: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/e2eslow/main_test.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage e2eslow\n\nimport (\n\t\"testing\"\n\n\t\"github.com/coreos/etcd-operator/test/e2e/framework\"\n)\n\nfunc TestMain(m *testing.M) {\n\tframework.MainEntry(m)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/e2eutil/crd_util.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage e2eutil\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned\"\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\t\"github.com/coreos/etcd-operator/pkg/util/retryutil\"\n\n\t\"github.com/aws/aws-sdk-go/service/s3\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n)\n\ntype StorageCheckerOptions struct {\n\tS3Cli          *s3.S3\n\tS3Bucket       string\n\tDeletedFromAPI bool\n}\n\nfunc CreateCluster(t *testing.T, crClient versioned.Interface, namespace string, cl *api.EtcdCluster) (*api.EtcdCluster, error) {\n\tcl.Namespace = namespace\n\tres, err := crClient.EtcdV1beta2().EtcdClusters(namespace).Create(cl)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tt.Logf(\"creating etcd cluster: %s\", res.Name)\n\n\treturn res, nil\n}\n\nfunc UpdateCluster(crClient versioned.Interface, cl *api.EtcdCluster, maxRetries int, updateFunc k8sutil.EtcdClusterCRUpdateFunc) (*api.EtcdCluster, error) {\n\treturn AtomicUpdateClusterCR(crClient, cl.Name, cl.Namespace, maxRetries, updateFunc)\n}\n\nfunc AtomicUpdateClusterCR(crClient versioned.Interface, name, namespace string, maxRetries int, updateFunc k8sutil.EtcdClusterCRUpdateFunc) (*api.EtcdCluster, error) {\n\tresult := &api.EtcdCluster{}\n\terr := retryutil.Retry(1*time.Second, maxRetries, func() (done bool, err error) {\n\t\tetcdCluster, err := crClient.EtcdV1beta2().EtcdClusters(namespace).Get(name, metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\n\t\tupdateFunc(etcdCluster)\n\n\t\tresult, err = crClient.EtcdV1beta2().EtcdClusters(namespace).Update(etcdCluster)\n\t\tif err != nil {\n\t\t\tif apierrors.IsConflict(err) {\n\t\t\t\treturn false, nil\n\t\t\t}\n\t\t\treturn false, err\n\t\t}\n\t\treturn true, nil\n\t})\n\treturn result, err\n}\n\nfunc DeleteCluster(t *testing.T, crClient versioned.Interface, kubeClient kubernetes.Interface, cl *api.EtcdCluster) error {\n\tt.Logf(\"deleting etcd cluster: %v\", cl.Name)\n\terr := crClient.EtcdV1beta2().EtcdClusters(cl.Namespace).Delete(cl.Name, nil)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn waitResourcesDeleted(t, kubeClient, cl)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/e2eutil/etcd_util.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage e2eutil\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t\"github.com/coreos/etcd-operator/pkg/util/constants\"\n\t\"github.com/coreos/etcd/clientv3\"\n)\n\nconst (\n\tetcdKeyFoo = \"foo\"\n\tetcdValBar = \"bar\"\n)\n\nfunc PutDataToEtcd(url string) error {\n\tetcdcli, err := createEtcdClient(url)\n\tif err != nil {\n\t\treturn err\n\t}\n\tctx, cancel := context.WithTimeout(context.Background(), constants.DefaultRequestTimeout)\n\t_, err = etcdcli.Put(ctx, etcdKeyFoo, etcdValBar)\n\tcancel()\n\tetcdcli.Close()\n\treturn err\n}\n\nfunc CheckEtcdData(t *testing.T, url string) {\n\tetcdcli, err := createEtcdClient(url)\n\tif err != nil {\n\t\tt.Fatalf(\"failed to create etcd client:%v\", err)\n\t}\n\tctx, cancel := context.WithTimeout(context.Background(), constants.DefaultRequestTimeout)\n\tresp, err := etcdcli.Get(ctx, etcdKeyFoo)\n\tcancel()\n\tetcdcli.Close()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(resp.Kvs) != 1 {\n\t\tt.Errorf(\"want only 1 key result, get %d\", len(resp.Kvs))\n\t} else {\n\t\tval := string(resp.Kvs[0].Value)\n\t\tif val != etcdValBar {\n\t\t\tt.Errorf(\"value want = '%s', get = '%s'\", etcdValBar, val)\n\t\t}\n\t}\n}\n\nfunc createEtcdClient(addr string) (*clientv3.Client, error) {\n\tcfg := clientv3.Config{\n\t\tEndpoints:   []string{addr},\n\t\tDialTimeout: constants.DefaultDialTimeout,\n\t}\n\tc, err := clientv3.New(cfg)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn c, nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/e2eutil/spec_util.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage e2eutil\n\nimport (\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\nfunc NewCluster(genName string, size int) *api.EtcdCluster {\n\treturn &api.EtcdCluster{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tKind:       api.EtcdClusterResourceKind,\n\t\t\tAPIVersion: api.SchemeGroupVersion.String(),\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tGenerateName: genName,\n\t\t},\n\t\tSpec: api.ClusterSpec{\n\t\t\tSize: size,\n\t\t},\n\t}\n}\n\n// NewS3Backup creates a EtcdBackup object using clusterName.\nfunc NewS3Backup(endpoints []string, clusterName, path, secret, clientTLSSecret string) *api.EtcdBackup {\n\treturn &api.EtcdBackup{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tKind:       api.EtcdBackupResourceKind,\n\t\t\tAPIVersion: api.SchemeGroupVersion.String(),\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tGenerateName: clusterName,\n\t\t},\n\t\tSpec: api.BackupSpec{\n\t\t\tEtcdEndpoints:   endpoints,\n\t\t\tStorageType:     api.BackupStorageTypeS3,\n\t\t\tClientTLSSecret: clientTLSSecret,\n\t\t\tBackupSource: api.BackupSource{\n\t\t\t\tS3: &api.S3BackupSource{\n\t\t\t\t\tPath:           path,\n\t\t\t\t\tAWSSecret:      secret,\n\t\t\t\t\tForcePathStyle: false,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n}\n\n// NewS3RestoreSource returns an S3RestoreSource with the specified path and secret\nfunc NewS3RestoreSource(path, awsSecret string) *api.S3RestoreSource {\n\treturn &api.S3RestoreSource{\n\t\tPath:      path,\n\t\tAWSSecret: awsSecret,\n\t}\n}\n\n// NewEtcdRestore returns an EtcdRestore CR with the specified RestoreSource\nfunc NewEtcdRestore(clusterName string, size int, restoreSource api.RestoreSource, backupStorageType api.BackupStorageType) *api.EtcdRestore {\n\treturn &api.EtcdRestore{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tKind:       api.EtcdRestoreResourceKind,\n\t\t\tAPIVersion: api.SchemeGroupVersion.String(),\n\t\t},\n\t\t// The EtcdRestore CR name must be the same as the EtcdClusterRef name\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName: clusterName,\n\t\t},\n\t\tSpec: api.RestoreSpec{\n\t\t\tEtcdCluster: api.EtcdClusterRef{\n\t\t\t\tName: clusterName,\n\t\t\t},\n\t\t\tBackupStorageType: backupStorageType,\n\t\t\tRestoreSource:     restoreSource,\n\t\t},\n\t}\n}\n\n// ClusterCRWithTLS adds TLSPolicy to the passing in cluster CR.\nfunc ClusterCRWithTLS(cl *api.EtcdCluster, memberPeerTLSSecret, memberServerTLSSecret, operatorClientTLSSecret string) {\n\tcl.Spec.TLS = &api.TLSPolicy{\n\t\tStatic: &api.StaticTLS{\n\t\t\tMember: &api.MemberSecret{\n\t\t\t\tPeerSecret:   memberPeerTLSSecret,\n\t\t\t\tServerSecret: memberServerTLSSecret,\n\t\t\t},\n\t\t\tOperatorSecret: operatorClientTLSSecret,\n\t\t},\n\t}\n}\n\nfunc ClusterWithVersion(cl *api.EtcdCluster, version string) *api.EtcdCluster {\n\tcl.Spec.Version = version\n\treturn cl\n}\n\n// NameLabelSelector returns a label selector of the form name=<name>\nfunc NameLabelSelector(name string) map[string]string {\n\treturn map[string]string{\"name\": name}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/e2eutil/tls.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Generate a self-signed X.509 certificate for a TLS server. Outputs to\n// 'cert.pem' and 'key.pem' and will overwrite existing files.\n\npackage e2eutil\n\nimport (\n\t\"crypto/ecdsa\"\n\t\"crypto/rand\"\n\t\"crypto/rsa\"\n\t\"crypto/x509\"\n\t\"crypto/x509/pkix\"\n\t\"encoding/pem\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"math/big\"\n\t\"net\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"time\"\n\n\t\"github.com/sirupsen/logrus\"\n)\n\n// PrepareTLS creates all the required tls certs for a given clusterName.\nfunc PrepareTLS(clusterName, namespace, memberPeerTLSSecret, memberClientTLSSecret, operatorClientTLSSecret string) error {\n\terr := PreparePeerTLSSecret(clusterName, namespace, memberPeerTLSSecret)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to prepare peer TLS secret: %v\", err)\n\t}\n\tcertsDir, err := ioutil.TempDir(\"\", \"etcd-operator-tls-\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer os.RemoveAll(certsDir)\n\terr = PrepareClientTLSSecret(certsDir, clusterName, namespace, memberClientTLSSecret, operatorClientTLSSecret)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to prepare client TLS secret: %v\", err)\n\t}\n\treturn nil\n}\n\nfunc PreparePeerTLSSecret(clusterName, ns, secretName string) error {\n\tdir, err := ioutil.TempDir(\"\", \"etcd-operator-tls-\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer os.RemoveAll(dir)\n\n\tcertPath := filepath.Join(dir, \"peer.crt\")\n\tkeyPath := filepath.Join(dir, \"peer.key\")\n\tcaPath := filepath.Join(dir, \"peer-ca.crt\")\n\thosts := []string{\n\t\tfmt.Sprintf(\"*.%s.%s.svc\", clusterName, ns),\n\t\t// Due to issue https://github.com/coreos/etcd/issues/8797,\n\t\t// we need to provide FQDN in certs at the moment.\n\t\tfmt.Sprintf(\"*.%s.%s.svc.cluster.local\", clusterName, ns),\n\t}\n\n\terr = prepareTLSCerts(certPath, keyPath, caPath, hosts)\n\tif err != nil {\n\t\treturn err\n\t}\n\tcmd := exec.Command(\"kubectl\", \"-n\", ns, \"create\", \"secret\", \"generic\", secretName,\n\t\tfmt.Sprintf(\"--from-file=%s\", caPath),\n\t\tfmt.Sprintf(\"--from-file=%s\", certPath),\n\t\tfmt.Sprintf(\"--from-file=%s\", keyPath),\n\t)\n\tstdoutStderr, err := cmd.CombinedOutput()\n\tif err != nil {\n\t\tlogrus.Errorf(\"failed to create tls secret. stdout/stderr: %s\", stdoutStderr)\n\t\treturn fmt.Errorf(\"failed to create tls secret: %v\", err)\n\t}\n\treturn nil\n}\n\nfunc PrepareClientTLSSecret(dir, clusterName, ns, mSecret, oSecret string) error {\n\tmCertPath := filepath.Join(dir, \"server.crt\")\n\tmKeyPath := filepath.Join(dir, \"server.key\")\n\toCAPath := filepath.Join(dir, \"etcd-client-ca.crt\")\n\tmHosts := []string{\n\t\tfmt.Sprintf(\"*.%s.%s.svc\", clusterName, ns),\n\t\tfmt.Sprintf(\"%s-client.%s.svc\", clusterName, ns),\n\t\t\"localhost\",\n\t}\n\n\terr := prepareTLSCerts(mCertPath, mKeyPath, oCAPath, mHosts)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\toCertPath := filepath.Join(dir, \"etcd-client.crt\")\n\toKeyPath := filepath.Join(dir, \"etcd-client.key\")\n\tmCAPath := filepath.Join(dir, \"server-ca.crt\")\n\toHosts := []string{\"\"}\n\n\terr = prepareTLSCerts(oCertPath, oKeyPath, mCAPath, oHosts)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tcmd := exec.Command(\"kubectl\", \"-n\", ns, \"create\", \"secret\", \"generic\", mSecret,\n\t\tfmt.Sprintf(\"--from-file=%s\", mCAPath),\n\t\tfmt.Sprintf(\"--from-file=%s\", mCertPath),\n\t\tfmt.Sprintf(\"--from-file=%s\", mKeyPath),\n\t)\n\tstdoutStderr, err := cmd.CombinedOutput()\n\tif err != nil {\n\t\tlogrus.Errorf(\"failed to create tls secret. stdout/stderr: %s\", stdoutStderr)\n\t\treturn fmt.Errorf(\"failed to create tls secret: %v\", err)\n\t}\n\n\tcmd = exec.Command(\"kubectl\", \"-n\", ns, \"create\", \"secret\", \"generic\", oSecret,\n\t\tfmt.Sprintf(\"--from-file=%s\", oCAPath),\n\t\tfmt.Sprintf(\"--from-file=%s\", oCertPath),\n\t\tfmt.Sprintf(\"--from-file=%s\", oKeyPath),\n\t)\n\tstdoutStderr, err = cmd.CombinedOutput()\n\tif err != nil {\n\t\tlogrus.Errorf(\"failed to create tls secret. stdout/stderr: %s\", stdoutStderr)\n\t\treturn fmt.Errorf(\"failed to create tls secret: %v\", err)\n\t}\n\treturn nil\n}\n\nfunc prepareTLSCerts(certPath, keyPath, caPath string, hosts []string) error {\n\terr := prepareKeyAndCert(certPath, keyPath, hosts)\n\tif err != nil {\n\t\treturn err\n\t}\n\tb, err := ioutil.ReadFile(certPath)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn ioutil.WriteFile(caPath, b, 0644)\n}\n\n// prepareKeyAndCert creates self-signed self-CA x509 key and cert file.\n// The files are written as given certPath and keyPath respectively.\n// hosts: Comma-separated hostnames and IPs to generate a certificate for.\nfunc prepareKeyAndCert(certPath, keyPath string, hosts []string) error {\n\tpriv, err := rsa.GenerateKey(rand.Reader, 2048)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to generate private key: %v\", err)\n\t}\n\n\tnotBefore := time.Now()\n\tnotAfter := notBefore.Add(2 * time.Hour)\n\n\tserialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)\n\tserialNumber, err := rand.Int(rand.Reader, serialNumberLimit)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to generate serial number: %v\", err)\n\t}\n\n\ttemplate := x509.Certificate{\n\t\tSerialNumber: serialNumber,\n\t\tSubject: pkix.Name{\n\t\t\tOrganization: []string{\"Etcd Operator Example\"},\n\t\t},\n\t\tNotBefore: notBefore,\n\t\tNotAfter:  notAfter,\n\n\t\tIsCA:                  true,\n\t\tKeyUsage:              x509.KeyUsageCertSign | x509.KeyUsageDigitalSignature,\n\t\tExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},\n\t\tBasicConstraintsValid: true,\n\t}\n\n\tfor _, h := range hosts {\n\t\tif ip := net.ParseIP(h); ip != nil {\n\t\t\ttemplate.IPAddresses = append(template.IPAddresses, ip)\n\t\t} else {\n\t\t\ttemplate.DNSNames = append(template.DNSNames, h)\n\t\t}\n\t}\n\n\tderBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"Failed to create certificate: %v\", err)\n\t}\n\n\tcertOut, err := os.Create(certPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to open cert.pem for writing: %v\", err)\n\t}\n\tpem.Encode(certOut, &pem.Block{Type: \"CERTIFICATE\", Bytes: derBytes})\n\tcertOut.Close()\n\n\tkeyOut, err := os.OpenFile(keyPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to open key.pem for writing: %v\", err)\n\t}\n\tpb, err := pemBlockForKey(priv)\n\tif err != nil {\n\t\treturn err\n\t}\n\tpem.Encode(keyOut, pb)\n\tkeyOut.Close()\n\treturn nil\n}\n\nfunc publicKey(priv interface{}) interface{} {\n\tswitch k := priv.(type) {\n\tcase *rsa.PrivateKey:\n\t\treturn &k.PublicKey\n\tcase *ecdsa.PrivateKey:\n\t\treturn &k.PublicKey\n\tdefault:\n\t\treturn nil\n\t}\n}\n\nfunc pemBlockForKey(priv interface{}) (*pem.Block, error) {\n\tswitch k := priv.(type) {\n\tcase *rsa.PrivateKey:\n\t\treturn &pem.Block{Type: \"RSA PRIVATE KEY\", Bytes: x509.MarshalPKCS1PrivateKey(k)}, nil\n\tcase *ecdsa.PrivateKey:\n\t\tb, err := x509.MarshalECPrivateKey(k)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"Unable to marshal ECDSA private key: %v\", err)\n\t\t}\n\t\treturn &pem.Block{Type: \"EC PRIVATE KEY\", Bytes: b}, nil\n\tdefault:\n\t\treturn nil, errors.New(\"unknown private key type\")\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/e2eutil/util.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage e2eutil\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/coreos/etcd-operator/pkg/backup/writer\"\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\n\t\"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/client-go/kubernetes\"\n)\n\nfunc DeleteSecrets(kubecli kubernetes.Interface, namespace string, secretNames ...string) error {\n\tvar retErr error\n\tfor _, sname := range secretNames {\n\t\terr := kubecli.CoreV1().Secrets(namespace).Delete(sname, metav1.NewDeleteOptions(0))\n\t\tif err != nil {\n\t\t\tretErr = fmt.Errorf(\"failed to delete secret (%s): %v; %v\", sname, err, retErr)\n\t\t}\n\t}\n\treturn retErr\n}\n\nfunc KillMembers(kubecli kubernetes.Interface, namespace string, names ...string) error {\n\tfor _, name := range names {\n\t\terr := kubecli.CoreV1().Pods(namespace).Delete(name, metav1.NewDeleteOptions(0))\n\t\tif err != nil && !k8sutil.IsKubernetesResourceNotFoundError(err) {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc LogfWithTimestamp(t *testing.T, format string, args ...interface{}) {\n\tt.Log(time.Now(), fmt.Sprintf(format, args...))\n}\n\nfunc printContainerStatus(buf *bytes.Buffer, ss []v1.ContainerStatus) {\n\tfor _, s := range ss {\n\t\tif s.State.Waiting != nil {\n\t\t\tbuf.WriteString(fmt.Sprintf(\"%s: Waiting: message (%s) reason (%s)\\n\", s.Name, s.State.Waiting.Message, s.State.Waiting.Reason))\n\t\t}\n\t\tif s.State.Terminated != nil {\n\t\t\tbuf.WriteString(fmt.Sprintf(\"%s: Terminated: message (%s) reason (%s)\\n\", s.Name, s.State.Terminated.Message, s.State.Terminated.Reason))\n\t\t}\n\t}\n}\n\nfunc DeleteBackupFiles(wr writer.Writer, files []string) error {\n\tfor _, v := range files {\n\t\tif err := wr.Delete(context.Background(), v); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/e2eutil/wait_util.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage e2eutil\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/pkg/backup/writer\"\n\t\"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned\"\n\t\"github.com/coreos/etcd-operator/pkg/util\"\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\t\"github.com/coreos/etcd-operator/pkg/util/retryutil\"\n\n\t\"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/client-go/kubernetes\"\n)\n\nvar retryInterval = 10 * time.Second\n\ntype acceptFunc func(*api.EtcdCluster) bool\ntype filterFunc func(*v1.Pod) bool\n\nfunc CalculateRestoreWaitTime(needDataClone bool) int {\n\twaitTime := 24\n\tif needDataClone {\n\t\t// Take additional time to clone the data.\n\t\twaitTime += 6\n\t}\n\treturn waitTime\n}\n\nfunc WaitUntilPodSizeReached(t *testing.T, kubeClient kubernetes.Interface, size, retries int, cl *api.EtcdCluster) ([]string, error) {\n\tvar names []string\n\terr := retryutil.Retry(retryInterval, retries, func() (done bool, err error) {\n\t\tpodList, err := kubeClient.Core().Pods(cl.Namespace).List(k8sutil.ClusterListOpt(cl.Name))\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\tnames = nil\n\t\tvar nodeNames []string\n\t\tfor i := range podList.Items {\n\t\t\tpod := &podList.Items[i]\n\t\t\tif pod.Status.Phase != v1.PodRunning {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tnames = append(names, pod.Name)\n\t\t\tnodeNames = append(nodeNames, pod.Spec.NodeName)\n\t\t}\n\t\tLogfWithTimestamp(t, \"waiting size (%d), etcd pods: names (%v), nodes (%v)\", size, names, nodeNames)\n\t\tif len(names) != size {\n\t\t\treturn false, nil\n\t\t}\n\t\treturn true, nil\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn names, nil\n}\n\nfunc WaitUntilSizeReached(t *testing.T, crClient versioned.Interface, size, retries int, cl *api.EtcdCluster) ([]string, error) {\n\treturn waitSizeReachedWithAccept(t, crClient, size, retries, cl)\n}\n\nfunc WaitSizeAndVersionReached(t *testing.T, kubeClient kubernetes.Interface, version string, size, retries int, cl *api.EtcdCluster) error {\n\treturn retryutil.Retry(retryInterval, retries, func() (done bool, err error) {\n\t\tvar names []string\n\t\tpodList, err := kubeClient.Core().Pods(cl.Namespace).List(k8sutil.ClusterListOpt(cl.Name))\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\tnames = nil\n\t\tvar nodeNames []string\n\t\tfor i := range podList.Items {\n\t\t\tpod := &podList.Items[i]\n\t\t\tif pod.Status.Phase != v1.PodRunning {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tcontainerVersion := getVersionFromImage(pod.Status.ContainerStatuses[0].Image)\n\t\t\tif containerVersion != version {\n\t\t\t\tLogfWithTimestamp(t, \"pod(%v): expected version(%v) current version(%v)\", pod.Name, version, containerVersion)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tnames = append(names, pod.Name)\n\t\t\tnodeNames = append(nodeNames, pod.Spec.NodeName)\n\t\t}\n\t\tLogfWithTimestamp(t, \"waiting size (%d), etcd pods: names (%v), nodes (%v)\", size, names, nodeNames)\n\t\tif len(names) != size {\n\t\t\treturn false, nil\n\t\t}\n\t\treturn true, nil\n\t})\n}\n\nfunc getVersionFromImage(image string) string {\n\treturn strings.Split(image, \":v\")[1]\n}\n\nfunc waitSizeReachedWithAccept(t *testing.T, crClient versioned.Interface, size, retries int, cl *api.EtcdCluster, accepts ...acceptFunc) ([]string, error) {\n\tvar names []string\n\terr := retryutil.Retry(retryInterval, retries, func() (done bool, err error) {\n\t\tcurrCluster, err := crClient.EtcdV1beta2().EtcdClusters(cl.Namespace).Get(cl.Name, metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\n\t\tfor _, accept := range accepts {\n\t\t\tif !accept(currCluster) {\n\t\t\t\treturn false, nil\n\t\t\t}\n\t\t}\n\n\t\tnames = currCluster.Status.Members.Ready\n\t\tLogfWithTimestamp(t, \"waiting size (%d), healthy etcd members: names (%v)\", size, names)\n\t\tif len(names) != size {\n\t\t\treturn false, nil\n\t\t}\n\t\treturn true, nil\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn names, nil\n}\n\nfunc WaitUntilMembersWithNamesDeleted(t *testing.T, crClient versioned.Interface, retries int, cl *api.EtcdCluster, targetNames ...string) ([]string, error) {\n\tvar remaining []string\n\terr := retryutil.Retry(retryInterval, retries, func() (done bool, err error) {\n\t\tcurrCluster, err := crClient.EtcdV1beta2().EtcdClusters(cl.Namespace).Get(cl.Name, metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\n\t\treadyMembers := currCluster.Status.Members.Ready\n\t\tremaining = nil\n\t\tfor _, name := range targetNames {\n\t\t\tif util.PresentIn(name, readyMembers) {\n\t\t\t\tremaining = append(remaining, name)\n\t\t\t}\n\t\t}\n\n\t\tLogfWithTimestamp(t, \"waiting on members (%v) to be deleted\", remaining)\n\t\tif len(remaining) != 0 {\n\t\t\treturn false, nil\n\t\t}\n\t\treturn true, nil\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn remaining, nil\n}\n\nfunc waitResourcesDeleted(t *testing.T, kubeClient kubernetes.Interface, cl *api.EtcdCluster) error {\n\tundeletedPods, err := WaitPodsDeleted(kubeClient, cl.Namespace, 3, k8sutil.ClusterListOpt(cl.Name))\n\tif err != nil {\n\t\tif retryutil.IsRetryFailure(err) && len(undeletedPods) > 0 {\n\t\t\tp := undeletedPods[0]\n\t\t\tLogfWithTimestamp(t, \"waiting pod (%s) to be deleted.\", p.Name)\n\n\t\t\tbuf := bytes.NewBuffer(nil)\n\t\t\tbuf.WriteString(\"init container status:\\n\")\n\t\t\tprintContainerStatus(buf, p.Status.InitContainerStatuses)\n\t\t\tbuf.WriteString(\"container status:\\n\")\n\t\t\tprintContainerStatus(buf, p.Status.ContainerStatuses)\n\t\t\tt.Logf(\"pod (%s) status.phase is (%s): %v\", p.Name, p.Status.Phase, buf.String())\n\t\t}\n\n\t\treturn fmt.Errorf(\"fail to wait pods deleted: %v\", err)\n\t}\n\n\terr = retryutil.Retry(retryInterval, 3, func() (done bool, err error) {\n\t\tlist, err := kubeClient.CoreV1().Services(cl.Namespace).List(k8sutil.ClusterListOpt(cl.Name))\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\tif len(list.Items) > 0 {\n\t\t\tLogfWithTimestamp(t, \"waiting service (%s) to be deleted\", list.Items[0].Name)\n\t\t\treturn false, nil\n\t\t}\n\t\treturn true, nil\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"fail to wait services deleted: %v\", err)\n\t}\n\treturn nil\n}\n\nfunc WaitPodsWithImageDeleted(kubecli kubernetes.Interface, namespace, image string, retries int, lo metav1.ListOptions) ([]*v1.Pod, error) {\n\treturn waitPodsDeleted(kubecli, namespace, retries, lo, func(p *v1.Pod) bool {\n\t\tfor _, c := range p.Spec.Containers {\n\t\t\tif c.Image == image {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n}\n\nfunc WaitPodsDeleted(kubecli kubernetes.Interface, namespace string, retries int, lo metav1.ListOptions) ([]*v1.Pod, error) {\n\tf := func(p *v1.Pod) bool { return p.DeletionTimestamp != nil }\n\treturn waitPodsDeleted(kubecli, namespace, retries, lo, f)\n}\n\nfunc WaitPodsDeletedCompletely(kubecli kubernetes.Interface, namespace string, retries int, lo metav1.ListOptions) ([]*v1.Pod, error) {\n\treturn waitPodsDeleted(kubecli, namespace, retries, lo)\n}\n\nfunc waitPodsDeleted(kubecli kubernetes.Interface, namespace string, retries int, lo metav1.ListOptions, filters ...filterFunc) ([]*v1.Pod, error) {\n\tvar pods []*v1.Pod\n\terr := retryutil.Retry(retryInterval, retries, func() (bool, error) {\n\t\tpodList, err := kubecli.CoreV1().Pods(namespace).List(lo)\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\tpods = nil\n\t\tfor i := range podList.Items {\n\t\t\tp := &podList.Items[i]\n\t\t\tfiltered := false\n\t\t\tfor _, filter := range filters {\n\t\t\t\tif filter(p) {\n\t\t\t\t\tfiltered = true\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !filtered {\n\t\t\t\tpods = append(pods, p)\n\t\t\t}\n\t\t}\n\t\treturn len(pods) == 0, nil\n\t})\n\treturn pods, err\n}\n\n// WaitUntilOperatorReady will wait until the first pod selected for the label name=etcd-operator is ready.\nfunc WaitUntilOperatorReady(kubecli kubernetes.Interface, namespace, name string) error {\n\tvar podName string\n\tlo := metav1.ListOptions{\n\t\tLabelSelector: labels.SelectorFromSet(NameLabelSelector(name)).String(),\n\t}\n\terr := retryutil.Retry(10*time.Second, 6, func() (bool, error) {\n\t\tpodList, err := kubecli.CoreV1().Pods(namespace).List(lo)\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\tif len(podList.Items) > 0 {\n\t\t\tpodName = podList.Items[0].Name\n\t\t\tif k8sutil.IsPodReady(&podList.Items[0]) {\n\t\t\t\treturn true, nil\n\t\t\t}\n\t\t}\n\t\treturn false, nil\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to wait for pod (%v) to become ready: %v\", podName, err)\n\t}\n\treturn nil\n}\n\nfunc WaitUntilNoBackupFiles(wr writer.Writer, path string, timeout int) error {\n\treturn retryutil.Retry(time.Second, timeout, func() (bool, error) {\n\t\tallBackups, err := wr.List(context.Background(), path)\n\t\tif err != nil {\n\t\t\treturn false, fmt.Errorf(\"failed to list backup files: %v\", err)\n\t\t}\n\t\tif len(allBackups) > 0 {\n\t\t\treturn false, fmt.Errorf(\"%d existing backup files are detected\", len(allBackups))\n\t\t}\n\t\treturn true, nil\n\t})\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/framework/framework.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage framework\n\nimport (\n\t\"bytes\"\n\t\"flag\"\n\t\"fmt\"\n\t\"os/exec\"\n\t\"time\"\n\n\t\"github.com/coreos/etcd-operator/pkg/client\"\n\t\"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned\"\n\t\"github.com/coreos/etcd-operator/pkg/util/constants\"\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\t\"github.com/coreos/etcd-operator/pkg/util/probe\"\n\t\"github.com/coreos/etcd-operator/pkg/util/retryutil\"\n\t\"github.com/coreos/etcd-operator/test/e2e/e2eutil\"\n\t\"github.com/sirupsen/logrus\"\n\tv1 \"k8s.io/api/core/v1\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/util/intstr\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/client-go/tools/clientcmd\"\n)\n\nvar Global *Framework\n\nconst (\n\tetcdBackupOperatorName         = \"etcd-backup-operator\"\n\tetcdRestoreOperatorName        = \"etcd-restore-operator\"\n\tetcdRestoreOperatorServiceName = \"etcd-restore-operator\"\n\tetcdRestoreServicePort         = 19999\n)\n\ntype Framework struct {\n\topImage    string\n\tKubeClient kubernetes.Interface\n\tCRClient   versioned.Interface\n\tNamespace  string\n}\n\n// Setup setups a test framework and points \"Global\" to it.\nfunc setup() error {\n\tkubeconfig := flag.String(\"kubeconfig\", \"\", \"kube config path, e.g. $HOME/.kube/config\")\n\topImage := flag.String(\"operator-image\", \"\", \"operator image, e.g. gcr.io/coreos-k8s-scale-testing/etcd-operator\")\n\tns := flag.String(\"namespace\", \"default\", \"e2e test namespace\")\n\tflag.Parse()\n\n\tconfig, err := clientcmd.BuildConfigFromFlags(\"\", *kubeconfig)\n\tif err != nil {\n\t\treturn err\n\t}\n\tcli, err := kubernetes.NewForConfig(config)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tGlobal = &Framework{\n\t\tKubeClient: cli,\n\t\tCRClient:   client.MustNew(config),\n\t\tNamespace:  *ns,\n\t\topImage:    *opImage,\n\t}\n\n\t// Skip the etcd-operator deployment setup if the operator image was not specified\n\tif len(Global.opImage) == 0 {\n\t\treturn nil\n\t}\n\n\treturn Global.setup()\n}\n\nfunc teardown() error {\n\t// Skip the etcd-operator teardown if the operator image was not specified\n\tif len(Global.opImage) == 0 {\n\t\treturn nil\n\t}\n\n\terr := Global.deleteOperatorCompletely(\"etcd-operator\")\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = Global.KubeClient.CoreV1().Services(Global.Namespace).Delete(etcdRestoreOperatorServiceName, metav1.NewDeleteOptions(1))\n\tif err != nil && !apierrors.IsNotFound(err) {\n\t\treturn fmt.Errorf(\"failed to delete etcd restore operator service: %v\", err)\n\t}\n\tGlobal = nil\n\tlogrus.Info(\"e2e teardown successfully\")\n\treturn nil\n}\n\nfunc (f *Framework) setup() error {\n\terr := f.SetupEtcdOperator()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to setup etcd operator: %v\", err)\n\t}\n\tlogrus.Info(\"etcd operator created successfully\")\n\n\tlogrus.Info(\"e2e setup successfully\")\n\treturn nil\n}\n\nfunc (f *Framework) SetupEtcdOperator() error {\n\tpod := &v1.Pod{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:   \"etcd-operator\",\n\t\t\tLabels: map[string]string{\"name\": \"etcd-operator\"},\n\t\t},\n\t\tSpec: v1.PodSpec{\n\t\t\tContainers: []v1.Container{{\n\t\t\t\tName:            \"etcd-operator\",\n\t\t\t\tImage:           f.opImage,\n\t\t\t\tImagePullPolicy: v1.PullAlways,\n\t\t\t\tCommand:         []string{\"/usr/local/bin/etcd-operator\"},\n\t\t\t\tEnv: []v1.EnvVar{\n\t\t\t\t\t{\n\t\t\t\t\t\tName:      constants.EnvOperatorPodNamespace,\n\t\t\t\t\t\tValueFrom: &v1.EnvVarSource{FieldRef: &v1.ObjectFieldSelector{FieldPath: \"metadata.namespace\"}},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tName:      constants.EnvOperatorPodName,\n\t\t\t\t\t\tValueFrom: &v1.EnvVarSource{FieldRef: &v1.ObjectFieldSelector{FieldPath: \"metadata.name\"}},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tReadinessProbe: &v1.Probe{\n\t\t\t\t\tHandler: v1.Handler{\n\t\t\t\t\t\tHTTPGet: &v1.HTTPGetAction{\n\t\t\t\t\t\t\tPath: probe.HTTPReadyzEndpoint,\n\t\t\t\t\t\t\tPort: intstr.IntOrString{Type: intstr.Int, IntVal: 8080},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tInitialDelaySeconds: 3,\n\t\t\t\t\tPeriodSeconds:       3,\n\t\t\t\t\tFailureThreshold:    3,\n\t\t\t\t},\n\t\t\t}, {\n\t\t\t\tName:            etcdBackupOperatorName,\n\t\t\t\tImage:           f.opImage,\n\t\t\t\tImagePullPolicy: v1.PullAlways,\n\t\t\t\tCommand:         []string{\"/usr/local/bin/etcd-backup-operator\"},\n\t\t\t\tEnv: []v1.EnvVar{\n\t\t\t\t\t{\n\t\t\t\t\t\tName:      constants.EnvOperatorPodNamespace,\n\t\t\t\t\t\tValueFrom: &v1.EnvVarSource{FieldRef: &v1.ObjectFieldSelector{FieldPath: \"metadata.namespace\"}},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tName:      constants.EnvOperatorPodName,\n\t\t\t\t\t\tValueFrom: &v1.EnvVarSource{FieldRef: &v1.ObjectFieldSelector{FieldPath: \"metadata.name\"}},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}, {\n\t\t\t\tName:            etcdRestoreOperatorName,\n\t\t\t\tImage:           f.opImage,\n\t\t\t\tImagePullPolicy: v1.PullAlways,\n\t\t\t\tCommand:         []string{\"/usr/local/bin/etcd-restore-operator\"},\n\t\t\t\tEnv: []v1.EnvVar{\n\t\t\t\t\t{\n\t\t\t\t\t\tName:      constants.EnvOperatorPodNamespace,\n\t\t\t\t\t\tValueFrom: &v1.EnvVarSource{FieldRef: &v1.ObjectFieldSelector{FieldPath: \"metadata.namespace\"}},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tName:      constants.EnvOperatorPodName,\n\t\t\t\t\t\tValueFrom: &v1.EnvVarSource{FieldRef: &v1.ObjectFieldSelector{FieldPath: \"metadata.name\"}},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}},\n\t\t\tRestartPolicy: v1.RestartPolicyNever,\n\t\t},\n\t}\n\n\tp, err := k8sutil.CreateAndWaitPod(f.KubeClient, f.Namespace, pod, 60*time.Second)\n\tif err != nil {\n\t\tdescribePod(f.Namespace, \"etcd-operator\")\n\t\treturn err\n\t}\n\tlogrus.Infof(\"etcd operator pod is running on node (%s)\", p.Spec.NodeName)\n\n\treturn e2eutil.WaitUntilOperatorReady(f.KubeClient, f.Namespace, \"etcd-operator\")\n}\n\nfunc describePod(ns, name string) {\n\t// assuming `kubectl` installed on $PATH\n\tcmd := exec.Command(\"kubectl\", \"-n\", ns, \"describe\", \"pod\", name)\n\tvar out bytes.Buffer\n\tcmd.Stdout = &out\n\tcmd.Run() // Just ignore the error...\n\tlogrus.Infof(\"describing %s pod: %s\", name, out.String())\n}\n\nfunc (f *Framework) DeleteEtcdOperatorCompletely() error {\n\treturn f.deleteOperatorCompletely(\"etcd-operator\")\n}\n\nfunc (f *Framework) deleteOperatorCompletely(name string) error {\n\terr := f.KubeClient.CoreV1().Pods(f.Namespace).Delete(name, metav1.NewDeleteOptions(1))\n\tif err != nil {\n\t\treturn err\n\t}\n\t// Grace period isn't exactly accurate. It took ~10s for operator pod to completely disappear.\n\t// We work around by increasing the wait time. Revisit this later.\n\terr = retryutil.Retry(5*time.Second, 6, func() (bool, error) {\n\t\t_, err := f.KubeClient.CoreV1().Pods(f.Namespace).Get(name, metav1.GetOptions{})\n\t\tif err == nil {\n\t\t\treturn false, nil\n\t\t}\n\t\tif k8sutil.IsKubernetesResourceNotFoundError(err) {\n\t\t\treturn true, nil\n\t\t}\n\t\treturn false, err\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"fail to wait operator (%s) pod gone from API: %v\", name, err)\n\t}\n\treturn nil\n}\n\n// SetupEtcdRestoreOperatorService creates restore operator service that is used by etcd pod to retrieve backup.\nfunc (f *Framework) SetupEtcdRestoreOperatorService() error {\n\tsvc := &v1.Service{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName: etcdRestoreOperatorServiceName,\n\t\t},\n\t\tSpec: v1.ServiceSpec{\n\t\t\tSelector: map[string]string{\"name\": \"etcd-operator\"},\n\t\t\tPorts: []v1.ServicePort{{\n\t\t\t\tProtocol: v1.ProtocolTCP,\n\t\t\t\tPort:     etcdRestoreServicePort,\n\t\t\t}},\n\t\t},\n\t}\n\t_, err := f.KubeClient.CoreV1().Services(f.Namespace).Create(svc)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create restore-operator service failed: %v\", err)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/framework/main_entry.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage framework\n\nimport (\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/sirupsen/logrus\"\n)\n\nfunc MainEntry(m *testing.M) {\n\tif err := setup(); err != nil {\n\t\tlogrus.Errorf(\"fail to setup framework: %v\", err)\n\t\tos.Exit(1)\n\t}\n\n\tcode := m.Run()\n\n\tif err := teardown(); err != nil {\n\t\tlogrus.Errorf(\"fail to teardown framework: %v\", err)\n\t\tos.Exit(1)\n\t}\n\tos.Exit(code)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/main_test.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage e2e\n\nimport (\n\t\"testing\"\n\n\t\"github.com/coreos/etcd-operator/test/e2e/framework\"\n)\n\nfunc TestMain(m *testing.M) {\n\tframework.MainEntry(m)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/pv_test.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage e2e\n\nimport (\n\t\"os\"\n\t\"testing\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"k8s.io/api/core/v1\"\n\t\"k8s.io/apimachinery/pkg/api/resource\"\n\n\t\"github.com/coreos/etcd-operator/test/e2e/e2eutil\"\n\t\"github.com/coreos/etcd-operator/test/e2e/framework\"\n)\n\nfunc TestCreateClusterWithPV(t *testing.T) {\n\tif os.Getenv(envParallelTest) == envParallelTestTrue {\n\t\tt.Parallel()\n\t}\n\tf := framework.Global\n\tc := e2eutil.NewCluster(\"test-etcd-\", 3)\n\tc.Spec.Pod = &api.PodPolicy{\n\t\tPersistentVolumeClaimSpec: &v1.PersistentVolumeClaimSpec{\n\t\t\tAccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},\n\t\t\tResources: v1.ResourceRequirements{\n\t\t\t\tRequests: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse(\"512Mi\")},\n\t\t\t},\n\t\t\tStorageClassName: func(s string) *string { return &s }(\"standard\"),\n\t\t},\n\t}\n\n\ttestEtcd, err := e2eutil.CreateCluster(t, f.CRClient, f.Namespace, c)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tdefer func() {\n\t\tif err := e2eutil.DeleteCluster(t, f.CRClient, f.KubeClient, testEtcd); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\tif _, err := e2eutil.WaitUntilSizeReached(t, f.CRClient, 3, 30, testEtcd); err != nil {\n\t\tt.Fatalf(\"failed to create 3 members etcd cluster: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/recovery_test.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage e2e\n\nimport (\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/coreos/etcd-operator/test/e2e/e2eutil\"\n\t\"github.com/coreos/etcd-operator/test/e2e/framework\"\n)\n\nfunc TestOneMemberRecovery(t *testing.T) {\n\tif os.Getenv(envParallelTest) == envParallelTestTrue {\n\t\tt.Parallel()\n\t}\n\n\tf := framework.Global\n\ttestEtcd, err := e2eutil.CreateCluster(t, f.CRClient, f.Namespace, e2eutil.NewCluster(\"test-etcd-\", 3))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\terr := e2eutil.DeleteCluster(t, f.CRClient, f.KubeClient, testEtcd)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\tnames, err := e2eutil.WaitUntilSizeReached(t, f.CRClient, 3, 6, testEtcd)\n\tif err != nil {\n\t\tt.Fatalf(\"failed to create 3 members etcd cluster: %v\", err)\n\t}\n\tt.Log(\"reached to 3 members cluster\")\n\n\t// The last pod could have not come up serving yet. If we are not killing the last pod, we should wait.\n\tif err := e2eutil.KillMembers(f.KubeClient, f.Namespace, names[2]); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif _, err := e2eutil.WaitUntilPodSizeReached(t, f.KubeClient, 3, 6, testEtcd); err != nil {\n\t\tt.Fatalf(\"failed to resize to 3 members etcd cluster: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/resize_test.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage e2e\n\nimport (\n\t\"os\"\n\t\"testing\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/test/e2e/e2eutil\"\n\t\"github.com/coreos/etcd-operator/test/e2e/framework\"\n)\n\nfunc TestResizeCluster3to5(t *testing.T) {\n\tif os.Getenv(envParallelTest) == envParallelTestTrue {\n\t\tt.Parallel()\n\t}\n\tf := framework.Global\n\ttestEtcd, err := e2eutil.CreateCluster(t, f.CRClient, f.Namespace, e2eutil.NewCluster(\"test-etcd-\", 3))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tdefer func() {\n\t\tif err := e2eutil.DeleteCluster(t, f.CRClient, f.KubeClient, testEtcd); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\tif _, err := e2eutil.WaitUntilSizeReached(t, f.CRClient, 3, 6, testEtcd); err != nil {\n\t\tt.Fatalf(\"failed to create 3 members etcd cluster: %v\", err)\n\t}\n\tt.Log(\"reached to 3 members cluster\")\n\n\tupdateFunc := func(cl *api.EtcdCluster) {\n\t\tcl.Spec.Size = 5\n\t}\n\tif _, err := e2eutil.UpdateCluster(f.CRClient, testEtcd, 10, updateFunc); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif _, err := e2eutil.WaitUntilSizeReached(t, f.CRClient, 5, 6, testEtcd); err != nil {\n\t\tt.Fatalf(\"failed to resize to 5 members etcd cluster: %v\", err)\n\t}\n}\n\nfunc TestResizeCluster5to3(t *testing.T) {\n\tif os.Getenv(envParallelTest) == envParallelTestTrue {\n\t\tt.Parallel()\n\t}\n\tf := framework.Global\n\ttestEtcd, err := e2eutil.CreateCluster(t, f.CRClient, f.Namespace, e2eutil.NewCluster(\"test-etcd-\", 5))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tdefer func() {\n\t\tif err := e2eutil.DeleteCluster(t, f.CRClient, f.KubeClient, testEtcd); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\tif _, err := e2eutil.WaitUntilSizeReached(t, f.CRClient, 5, 9, testEtcd); err != nil {\n\t\tt.Fatalf(\"failed to create 5 members etcd cluster: %v\", err)\n\t}\n\tt.Log(\"reached to 5 members cluster\")\n\n\tupdateFunc := func(cl *api.EtcdCluster) {\n\t\tcl.Spec.Size = 3\n\t}\n\tif _, err := e2eutil.UpdateCluster(f.CRClient, testEtcd, 10, updateFunc); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif _, err := e2eutil.WaitUntilSizeReached(t, f.CRClient, 3, 6, testEtcd); err != nil {\n\t\tt.Fatalf(\"failed to resize to 3 members etcd cluster: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/tls_test.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage e2e\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\t\"os\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/coreos/etcd-operator/test/e2e/e2eutil\"\n\t\"github.com/coreos/etcd-operator/test/e2e/framework\"\n)\n\nfunc init() {\n\trand.Seed(time.Now().UTC().UnixNano())\n}\n\nfunc TestTLS(t *testing.T) {\n\tif os.Getenv(envParallelTest) == envParallelTestTrue {\n\t\tt.Parallel()\n\t}\n\tf := framework.Global\n\tsuffix := fmt.Sprintf(\"-%d\", rand.Uint64())\n\tclusterName := \"tls-test\" + suffix\n\tmemberPeerTLSSecret := \"etcd-peer-tls\" + suffix\n\tmemberClientTLSSecret := \"etcd-server-tls\" + suffix\n\toperatorClientTLSSecret := \"etcd-client-tls\" + suffix\n\n\terr := e2eutil.PrepareTLS(clusterName, f.Namespace, memberPeerTLSSecret, memberClientTLSSecret, operatorClientTLSSecret)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tdefer func() {\n\t\terr := e2eutil.DeleteSecrets(f.KubeClient, f.Namespace, memberPeerTLSSecret, memberClientTLSSecret, operatorClientTLSSecret)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\tc := e2eutil.NewCluster(\"\", 3)\n\tc.Name = clusterName\n\te2eutil.ClusterCRWithTLS(c, memberPeerTLSSecret, memberClientTLSSecret, operatorClientTLSSecret)\n\tc, err = e2eutil.CreateCluster(t, f.CRClient, f.Namespace, c)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tdefer func() {\n\t\tif err := e2eutil.DeleteCluster(t, f.CRClient, f.KubeClient, c); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\t_, err = e2eutil.WaitUntilSizeReached(t, f.CRClient, 3, 6, c)\n\tif err != nil {\n\t\tt.Fatalf(\"failed to create 3 members etcd cluster: %v\", err)\n\t}\n\t// TODO: use client key/certs to talk to secure etcd cluster.\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/upgradetest/README.md",
    "content": "# Operator Upgrade Test\n\n## How to run\n\nFrom operator root dir, run:\n```\n$ go test ./test/e2e/upgradetest/ --kubeconfig=... --kube-ns=... --old-image=... --new-image=...\n```\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/upgradetest/framework/framework.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage framework\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/coreos/etcd-operator/pkg/client\"\n\t\"github.com/coreos/etcd-operator/pkg/generated/clientset/versioned\"\n\t\"github.com/coreos/etcd-operator/pkg/util/constants\"\n\t\"github.com/coreos/etcd-operator/pkg/util/k8sutil\"\n\t\"github.com/coreos/etcd-operator/pkg/util/probe\"\n\t\"github.com/coreos/etcd-operator/test/e2e/e2eutil\"\n\n\tappsv1beta1 \"k8s.io/api/apps/v1beta1\"\n\t\"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/util/intstr\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/client-go/tools/clientcmd\"\n)\n\ntype Config struct {\n\t// program flags\n\tKubeConfig string\n\tKubeNS     string\n\tOldImage   string\n\tNewImage   string\n}\n\ntype Framework struct {\n\tConfig\n\t// global var\n\tKubeCli  kubernetes.Interface\n\tCRClient versioned.Interface\n}\n\nfunc New(fc Config) (*Framework, error) {\n\tkc, err := clientcmd.BuildConfigFromFlags(\"\", fc.KubeConfig)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tkubecli, err := kubernetes.NewForConfig(kc)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tf := &Framework{\n\t\tConfig:   fc,\n\t\tKubeCli:  kubecli,\n\t\tCRClient: client.MustNew(kc),\n\t}\n\treturn f, nil\n}\n\nfunc (f *Framework) CreateOperator(name string) error {\n\tcmd := []string{\"/usr/local/bin/etcd-operator\"}\n\timage := f.OldImage\n\td := &appsv1beta1.Deployment{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      name,\n\t\t\tNamespace: f.KubeNS,\n\t\t},\n\t\tSpec: appsv1beta1.DeploymentSpec{\n\t\t\tStrategy: appsv1beta1.DeploymentStrategy{\n\t\t\t\tType: appsv1beta1.RollingUpdateDeploymentStrategyType,\n\t\t\t\tRollingUpdate: &appsv1beta1.RollingUpdateDeployment{\n\t\t\t\t\tMaxUnavailable: &intstr.IntOrString{Type: intstr.Int, IntVal: 1},\n\t\t\t\t\tMaxSurge:       &intstr.IntOrString{Type: intstr.Int, IntVal: 1},\n\t\t\t\t},\n\t\t\t},\n\t\t\tSelector: &metav1.LabelSelector{MatchLabels: operatorLabelSelector(name)},\n\t\t\tTemplate: v1.PodTemplateSpec{\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\tLabels: operatorLabelSelector(name),\n\t\t\t\t},\n\t\t\t\tSpec: v1.PodSpec{\n\t\t\t\t\tContainers: []v1.Container{{\n\t\t\t\t\t\tName:            name,\n\t\t\t\t\t\tImage:           image,\n\t\t\t\t\t\tImagePullPolicy: v1.PullAlways,\n\t\t\t\t\t\tCommand:         cmd,\n\t\t\t\t\t\tEnv: []v1.EnvVar{\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tName:      constants.EnvOperatorPodNamespace,\n\t\t\t\t\t\t\t\tValueFrom: &v1.EnvVarSource{FieldRef: &v1.ObjectFieldSelector{FieldPath: \"metadata.namespace\"}},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tName:      constants.EnvOperatorPodName,\n\t\t\t\t\t\t\t\tValueFrom: &v1.EnvVarSource{FieldRef: &v1.ObjectFieldSelector{FieldPath: \"metadata.name\"}},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tReadinessProbe: &v1.Probe{\n\t\t\t\t\t\t\tHandler: v1.Handler{\n\t\t\t\t\t\t\t\tHTTPGet: &v1.HTTPGetAction{\n\t\t\t\t\t\t\t\t\tPath: probe.HTTPReadyzEndpoint,\n\t\t\t\t\t\t\t\t\tPort: intstr.IntOrString{Type: intstr.Int, IntVal: 8080},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tInitialDelaySeconds: 3,\n\t\t\t\t\t\t\tPeriodSeconds:       3,\n\t\t\t\t\t\t\tFailureThreshold:    3,\n\t\t\t\t\t\t},\n\t\t\t\t\t}},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\t_, err := f.KubeCli.AppsV1beta1().Deployments(f.KubeNS).Create(d)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create deployment: %v\", err)\n\t}\n\treturn nil\n}\n\nfunc (f *Framework) DeleteOperator(name string) error {\n\terr := f.KubeCli.AppsV1beta1().Deployments(f.KubeNS).Delete(name, k8sutil.CascadeDeleteOptions(0))\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Wait until the etcd-operator pod is actually gone and not just terminating.\n\t// In upgrade tests, the next test shouldn't see any etcd operator pod.\n\tlo := metav1.ListOptions{\n\t\tLabelSelector: labels.SelectorFromSet(operatorLabelSelector(name)).String(),\n\t}\n\t_, err = e2eutil.WaitPodsDeletedCompletely(f.KubeCli, f.KubeNS, 3, lo)\n\tif err != nil {\n\t\treturn err\n\t}\n\t// The deleted operator will not actively release the Endpoints lock causing a non-leader candidate to timeout for the lease duration: 15s\n\t// Deleting the Endpoints resource simulates the leader actively releasing the lock so that the next candidate avoids the timeout.\n\t// TODO: change this if we change to use another kind of lock, e.g. configmap.\n\treturn f.KubeCli.CoreV1().Endpoints(f.KubeNS).Delete(\"etcd-operator\", metav1.NewDeleteOptions(0))\n}\n\nfunc (f *Framework) UpgradeOperator(name string) error {\n\tuf := func(d *appsv1beta1.Deployment) {\n\t\td.Spec.Template.Spec.Containers[0].Image = f.NewImage\n\t}\n\terr := k8sutil.PatchDeployment(f.KubeCli, f.KubeNS, name, uf)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tlo := metav1.ListOptions{\n\t\tLabelSelector: labels.SelectorFromSet(operatorLabelSelector(name)).String(),\n\t}\n\t_, err = e2eutil.WaitPodsWithImageDeleted(f.KubeCli, f.KubeNS, f.OldImage, 3, lo)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to wait for pod with old image to get deleted: %v\", err)\n\t}\n\terr = e2eutil.WaitUntilOperatorReady(f.KubeCli, f.KubeNS, name)\n\treturn err\n}\n\nfunc operatorLabelSelector(name string) map[string]string {\n\treturn e2eutil.NameLabelSelector(name)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/upgradetest/main_test.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage upgradetest\n\nimport (\n\t\"flag\"\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/coreos/etcd-operator/test/e2e/upgradetest/framework\"\n\n\t\"github.com/sirupsen/logrus\"\n)\n\nvar testF *framework.Framework\n\nfunc TestMain(m *testing.M) {\n\tkubeconfig := flag.String(\"kubeconfig\", \"\", \"kube config path, e.g. $HOME/.kube/config\")\n\tkubeNS := flag.String(\"kube-ns\", \"default\", \"upgrade test namespace\")\n\toldImage := flag.String(\"old-image\", \"\", \"\")\n\tnewImage := flag.String(\"new-image\", \"\", \"\")\n\tflag.Parse()\n\n\tcfg := framework.Config{\n\t\tKubeConfig: *kubeconfig,\n\t\tKubeNS:     *kubeNS,\n\t\tOldImage:   *oldImage,\n\t\tNewImage:   *newImage,\n\t}\n\tvar err error\n\ttestF, err = framework.New(cfg)\n\tif err != nil {\n\t\tlogrus.Fatalf(\"failed to create test framework: %v\", err)\n\t}\n\n\tcode := m.Run()\n\tos.Exit(code)\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/upgradetest/upgrade_test.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage upgradetest\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\t\"testing\"\n\n\tapi \"github.com/coreos/etcd-operator/pkg/apis/etcd/v1beta2\"\n\t\"github.com/coreos/etcd-operator/test/e2e/e2eutil\"\n\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\nfunc newOperatorName() string {\n\tsuffix := fmt.Sprintf(\"-%d\", rand.Uint64())\n\treturn \"etcd-operator\" + suffix\n}\n\nfunc TestResize(t *testing.T) {\n\tname := newOperatorName()\n\terr := testF.CreateOperator(name)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\terr := testF.DeleteOperator(name)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\terr = e2eutil.WaitUntilOperatorReady(testF.KubeCli, testF.KubeNS, name)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\ttestClus, err := e2eutil.CreateCluster(t, testF.CRClient, testF.KubeNS, e2eutil.NewCluster(\"upgrade-test-\", 3))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\tif err := e2eutil.DeleteCluster(t, testF.CRClient, testF.KubeCli, testClus); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\t_, err = e2eutil.WaitUntilSizeReached(t, testF.CRClient, 3, 6, testClus)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\terr = testF.UpgradeOperator(name)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\ttestClus, err = testF.CRClient.EtcdV1beta2().EtcdClusters(testF.KubeNS).Get(testClus.Name, metav1.GetOptions{})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tupdateFunc := func(cl *api.EtcdCluster) {\n\t\tcl.Spec.Size = 5\n\t}\n\t_, err = e2eutil.UpdateCluster(testF.CRClient, testClus, 10, updateFunc)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t_, err = e2eutil.WaitUntilSizeReached(t, testF.CRClient, 5, 6, testClus)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n}\n\nfunc TestHealOneMemberForOldCluster(t *testing.T) {\n\tname := newOperatorName()\n\terr := testF.CreateOperator(name)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\terr := testF.DeleteOperator(name)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\terr = e2eutil.WaitUntilOperatorReady(testF.KubeCli, testF.KubeNS, name)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\ttestEtcd, err := e2eutil.CreateCluster(t, testF.CRClient, testF.KubeNS, e2eutil.NewCluster(\"upgrade-test-\", 3))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\tif err := e2eutil.DeleteCluster(t, testF.CRClient, testF.KubeCli, testEtcd); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\tnames, err := e2eutil.WaitUntilSizeReached(t, testF.CRClient, 3, 6, testEtcd)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\terr = testF.UpgradeOperator(name)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\terr = e2eutil.KillMembers(testF.KubeCli, testF.KubeNS, names[2])\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tremaining, err := e2eutil.WaitUntilMembersWithNamesDeleted(t, testF.CRClient, 3, testEtcd, names[2])\n\tif err != nil {\n\t\tt.Fatalf(\"failed to see members (%v) be deleted in time: %v\", remaining, err)\n\t}\n\n\t_, err = e2eutil.WaitUntilSizeReached(t, testF.CRClient, 3, 6, testEtcd)\n\tif err != nil {\n\t\tt.Fatalf(\"failed to heal one member: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/e2e/util.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage e2e\n\nconst (\n\tenvParallelTest     = \"PARALLEL_TEST\"\n\tenvParallelTestTrue = \"true\"\n)\n"
  },
  {
    "path": "third_party/etcd-operator/test/logcollector/main.go",
    "content": "// Copyright 2017 The etcd-operator 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\npackage main\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"flag\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"time\"\n\n\t\"github.com/sirupsen/logrus\"\n\tv1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/fields\"\n\t\"k8s.io/apimachinery/pkg/util/wait\"\n\t\"k8s.io/apimachinery/pkg/watch\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/client-go/tools/cache\"\n\t\"k8s.io/client-go/tools/clientcmd\"\n\twatchtools \"k8s.io/client-go/tools/watch\"\n)\n\nfunc main() {\n\tkubeconfig := flag.String(\"kubeconfig\", \"\", \"kube config file path\")\n\te2ePodName := flag.String(\"e2e-podname\", \"\", \"e2e test pod's name\")\n\tns := flag.String(\"namespace\", \"default\", \"e2e test namespace\")\n\tlogsDir := flag.String(\"logs-dir\", \"_output/logs/\", \"dir for pods' logs\")\n\tflag.Parse()\n\n\tif len(*e2ePodName) == 0 {\n\t\tpanic(\"must set --e2e-podname\")\n\t}\n\n\tconfig, err := clientcmd.BuildConfigFromFlags(\"\", *kubeconfig)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tkubecli, err := kubernetes.NewForConfig(config)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tstopCh := make(chan struct{})\n\tpodListWatcher := cache.NewListWatchFromClient(kubecli.CoreV1().RESTClient(), \"pods\", *ns, fields.Everything())\n\t_, informer := cache.NewIndexerInformer(podListWatcher, &v1.Pod{}, 0, cache.ResourceEventHandlerFuncs{\n\t\tAddFunc: func(obj interface{}) {\n\t\t\tgo func(pod *v1.Pod, namespace, logsDir string) {\n\t\t\t\twatcher, err := kubecli.CoreV1().Pods(namespace).Watch(metav1.SingleObject(metav1.ObjectMeta{Name: pod.Name}))\n\t\t\t\tif err != nil {\n\t\t\t\t\tlogrus.Errorf(\"failed to watch for pod (%s): %v\", pod.Name, err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tctx, cancel := watchtools.ContextWithOptionalTimeout(context.Background(), 100*time.Second)\n\t\t\t\tdefer cancel()\n\t\t\t\t// We need to wait Pod Running before collecting its log\n\t\t\t\tev, err := watchtools.UntilWithoutRetry(ctx, watcher, podRunning)\n\t\t\t\tif err != nil {\n\t\t\t\t\tif err == watchtools.ErrWatchClosed {\n\t\t\t\t\t\t// present a consistent error interface to callers\n\t\t\t\t\t\terr = wait.ErrWaitTimeout\n\t\t\t\t\t}\n\t\t\t\t\tlogrus.Errorf(\"failed to reach Running for pod (%s): %v\", pod.Name, err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tpod = ev.Object.(*v1.Pod)\n\t\t\t\tcontainers := append(pod.Spec.InitContainers, pod.Spec.Containers...)\n\t\t\t\tfor i := range containers {\n\t\t\t\t\tgo func(c v1.Container) {\n\t\t\t\t\t\tlogOption := &v1.PodLogOptions{Follow: true, Container: c.Name}\n\t\t\t\t\t\treq := kubecli.CoreV1().Pods(namespace).GetLogs(pod.Name, logOption)\n\t\t\t\t\t\treadCloser, err := req.Stream()\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\tlogrus.Errorf(\"failed to open stream for pod (%s): %v\", pod.Name, err)\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdefer readCloser.Close()\n\n\t\t\t\t\t\tf, err := os.OpenFile(filepath.Join(logsDir, pod.Name+\".\"+c.Name+\".log\"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\tlogrus.Errorf(\"failed to open log file for pod (%s/%s): %v\", pod.Name, c.Name, err)\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_, err = io.Copy(f, readCloser)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\tlogrus.Errorf(\"failed to write log for pod (%s/%s): %v\", pod.Name, c.Name, err)\n\t\t\t\t\t\t}\n\t\t\t\t\t}(containers[i])\n\t\t\t\t}\n\t\t\t}(obj.(*v1.Pod), *ns, *logsDir)\n\t\t},\n\t\tUpdateFunc: func(old, new interface{}) {\n\t\t\tpod := new.(*v1.Pod)\n\t\t\tif pod.Name != *e2ePodName {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// If e2e test pod runs to completion, then stops this program.\n\t\t\tif pod.Status.Phase == v1.PodSucceeded || pod.Status.Phase == v1.PodFailed || pod.DeletionTimestamp != nil {\n\t\t\t\tclose(stopCh)\n\t\t\t}\n\t\t},\n\t}, cache.Indexers{})\n\n\tlogrus.Info(\"start collecting logs...\")\n\tinformer.Run(stopCh)\n\tlogrus.Info(\"stop collecting logs...\")\n}\n\n// **NOTE**: Copy from kubernetes.\n// podRunning returns true if the pod is running, false if the pod has not yet reached running state,\n// returns ErrPodCompleted if the pod has run to completion, or an error in any other case.\nfunc podRunning(event watch.Event) (bool, error) {\n\tswitch event.Type {\n\tcase watch.Deleted:\n\t\treturn false, errors.New(\"pod deleted\")\n\t}\n\tswitch t := event.Object.(type) {\n\tcase *v1.Pod:\n\t\tswitch t.Status.Phase {\n\t\tcase v1.PodRunning:\n\t\t\treturn true, nil\n\t\tcase v1.PodFailed, v1.PodSucceeded:\n\t\t\treturn false, errors.New(\"pod ran to completion\")\n\t\t}\n\t}\n\treturn false, nil\n}\n"
  },
  {
    "path": "third_party/etcd-operator/test/pod/Dockerfile",
    "content": "# golang:X-alpine can't be used since it does not support the race detector flag which assumes a glibc based system, whereas alpine linux uses musl libc\n# https://github.com/golang/go/issues/14481\nFROM golang:1.11.5\n\nRUN curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.12.6/bin/linux/amd64/kubectl \\\n    && chmod +x ./kubectl \\\n    && mv ./kubectl /usr/local/bin/kubectl\n\nADD ./ /go/src/github.com/coreos/etcd-operator\n\nWORKDIR /go/src/github.com/coreos/etcd-operator\n\nRUN rm -rf _output _test .git .gitignore\n"
  },
  {
    "path": "third_party/etcd-operator/test/pod/README.md",
    "content": "# Running Containarized Tests\n\nThe scripts at `test/pod` can be used to package and run the e2e tests inside a test-pod on a k8s cluster.\n\n## Create the AWS secret\n\nThe e2e tests need access to an S3 bucket for testing. Create a secret containing the aws credentials and config files in the same namespace that the test-pod will run in. Consult the [backup-operator guide][setup-aws-secret] on how to do so.\n\n## Build the test-pod image\n\nThe following should build and push the test-pod image to some specified repository:\n\n```sh\nTEST_IMAGE=gcr.io/coreos-k8s-scale-testing/etcd-operator-e2e test/pod/docker_push\n```\n\n## Generate the test-pod spec file\n\nThe [test-pod-tmpl.yaml](./test-pod-tmpl.yaml) can be used to define the test-pod spec with the necessary values for the following environment variables:\n\n- `OPERATOR_IMAGE` is the etcd-operator image used for testing\n- `TEST_S3_BUCKET` is the S3 bucket name used for testing\n- `TEST_AWS_SECRET` is the secret name containing the aws credentials/config files.\n- `E2E_TEST_SELECTOR` selects which e2e tests to run. Leave empty to run all tests.\n- `UPGRADE_TEST_SELECTOR` selects which upgrade tests to run. Leave empty to run all tests.\n- `PASSES` are the test passes to run (e2e, e2eslow, e2esh). See [hack/test](../../hack/test)\n- `UPGRADE_FROM` is the starting image used in the upgrade tests\n- `UPGRADE_TO` is the final image used in the upgrade tests\n\n```sh\nsed -e \"s|<POD_NAME>|e2e-testing|g\" \\\n    -e \"s|<TEST_IMAGE>|gcr.io/coreos-k8s-scale-testing/etcd-operator-e2e|g\" \\\n    -e \"s|<PASSES>|e2eslow|g\" \\\n    -e \"s|<OPERATOR_IMAGE>|quay.io/coreos/etcd-operator:dev|g\" \\\n    -e \"s|<E2E_TEST_SELECTOR>||g\" \\\n    -e \"s|<TEST_S3_BUCKET>|my-bucket|g\" \\\n    -e \"s|<TEST_AWS_SECRET>|aws-secret|g\" \\\n    -e \"s|<UPGRADE_TEST_SELECTOR>||g\" \\\n    -e \"s|<UPGRADE_FROM>|quay.io/coreos/etcd-operator:latest|g\" \\\n    -e \"s|<UPGRADE_TO>|quay.io/coreos/etcd-operator:dev|g\" \\\n    test/pod/test-pod-templ.yaml > test-pod-spec.yaml\n```\n\n## Run the test-pod\n\nThe `run-test-pod` script sets up RBAC for the namespace, runs the logcollector and then the test-pod. The script waits until the test-pod has run to completion.\n\n```sh\n  TEST_NAMESPACE=e2e \\\n    POD_NAME=testing-e2e \\\n    TEST_POD_SPEC=${PWD}/test-pod-spec.yaml \\\n    KUBECONFIG=/path/to/kubeconfig \\\n    test/pod/run-test-pod\n```\n\nThe logfiles for all the pods in the test namespace will be saved at `${CWD}/_output/logs`.\n\n[setup-aws-secret]:../../doc/user/walkthrough/backup-operator.md#setup-aws-secret\n"
  },
  {
    "path": "third_party/etcd-operator/test/pod/docker_push",
    "content": "#!/usr/bin/env bash\n\n# This script builds and pushes the test-pod image\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nif ! which docker > /dev/null; then\n\techo \"docker needs to be installed\"\n\texit 1\nfi\n\n: ${TEST_IMAGE:?\"Need to set TEST_IMAGE, e.g. gcr.io/coreos-k8s-scale-testing/etcd-operator-tests\"}\n\necho \"building test-pod container...\"\ndocker build --tag \"${TEST_IMAGE}\" -f test/pod/Dockerfile . 1>/dev/null\n\n# For gcr users, do \"gcloud docker -a\" to have access.\necho \"pushing test-pod container...\"\ndocker push \"${TEST_IMAGE}\"\n"
  },
  {
    "path": "third_party/etcd-operator/test/pod/run-test-pod",
    "content": "#!/usr/bin/env bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\n: ${TEST_NAMESPACE:?\"Need to set TEST_NAMESPACE\"}\n: ${POD_NAME:?\"Need to set POD_NAME\"}\n: ${KUBECONFIG:?\"Need to set KUBECONFIG\"}\n: ${TEST_POD_SPEC:?\"Need to set TEST_POD_SPEC\"}\n\n# Setup RBAC for the e2e tests\nsource hack/ci/rbac_utils.sh\nfunction cleanup {\n    rbac_cleanup\n    kubectl -n ${TEST_NAMESPACE} delete pod ${POD_NAME}\n}\ntrap cleanup EXIT\n\nif rbac_setup ; then\n    echo \"RBAC setup success! ===\"\nelse\n    echo \"RBAC setup fail! ===\"\n    exit 1\nfi\n\n\nkubectl -n ${TEST_NAMESPACE} create -f ${TEST_POD_SPEC}\n\nPHASE_RUNNING=\"Running\"\nPHASE_SUCCEEDED=\"Succeeded\"\nRETRY_INTERVAL=5\n\n# Wait until pod is running or timeout\necho \"Waiting for test-pod to start runnning\"\nTIMEOUT=90\nELAPSED=0\nPOD_PHASE=\"\"\nuntil [ \"${POD_PHASE}\" == \"${PHASE_RUNNING}\" ]\ndo\n    if [ \"${ELAPSED}\" -ge \"${TIMEOUT}\" ]; then\n        echo \"Timeout waiting for test-pod ${POD_NAME} to become running\"\n        echo \"==============\"\n        kubectl -n ${TEST_NAMESPACE} describe pod ${POD_NAME}\n        echo \"==============\"\n        exit 1\n    fi\n    sleep ${RETRY_INTERVAL}\n    ELAPSED=$(( $ELAPSED + $RETRY_INTERVAL ))\n    POD_PHASE=$(kubectl -n ${TEST_NAMESPACE} get pod ${POD_NAME} -o jsonpath='{.status.phase}')\ndone\n\n# Print out and save logs to a file until the pod stops running\necho \"collecting logs ==========\"\n\nDOCKER_REPO_ROOT=\"/go/src/github.com/coreos/etcd-operator\"\nmkdir -p _output/logs/\ncp $KUBECONFIG ./kubeconfig\n\ndocker run --rm \\\n    -v \"$PWD\":\"$DOCKER_REPO_ROOT\" \\\n    -w \"$DOCKER_REPO_ROOT\" \\\n    gcr.io/coreos-k8s-scale-testing/logcollector \\\n    logcollector --kubeconfig=${DOCKER_REPO_ROOT}/kubeconfig --e2e-podname=${POD_NAME} \\\n    --namespace=${TEST_NAMESPACE} --logs-dir=\"_output/logs/\"\n\n# Check for pod success or failure\nPOD_PHASE=$(kubectl -n ${TEST_NAMESPACE} get pod ${POD_NAME} -o jsonpath='{.status.phase}')\nif [ \"${POD_PHASE}\" == \"${PHASE_SUCCEEDED}\" ]; then\n    echo \"e2e tests finished successfully\"\nelse\n    echo \"e2e tests failed\"\n    kubectl -n ${TEST_NAMESPACE} describe pod ${POD_NAME}\n    exit 1\nfi\n"
  },
  {
    "path": "third_party/etcd-operator/test/pod/simple/Dockerfile",
    "content": "# golang:X-alpine can't be used since it does not support the race detector flag which assumes a glibc based system, whereas alpine linux uses musl libc\n# https://github.com/golang/go/issues/14481\nFROM golang:1.11.5 as builder\n\nRUN wget -nv -O /bin/kubectl https://storage.googleapis.com/kubernetes-release/release/v1.12.6/bin/linux/amd64/kubectl\n\nRUN chmod a+x /bin/kubectl\n\nADD ./ /go/src/github.com/coreos/etcd-operator\n\nWORKDIR /go/src/github.com/coreos/etcd-operator\n\nRUN go test ./test/e2e/ -c -o /bin/etcd-operator-e2e --race\n\nFROM busybox:1.28.3-glibc\n\nCOPY --from=builder /bin/etcd-operator-e2e /bin\nCOPY --from=builder /bin/kubectl /bin\nCOPY --from=builder /go/src/github.com/coreos/etcd-operator/test/pod/simple/run-e2e /bin/run-e2e\n\nCMD [\"/bin/run-e2e\"]\n"
  },
  {
    "path": "third_party/etcd-operator/test/pod/simple/run-e2e",
    "content": "#!/bin/sh\n\nset -o errexit\nset -o nounset\n\n: ${TEST_NAMESPACE:?\"Need to set TEST_NAMESPACE\"}\n\n# Run e2e tests \n/bin/etcd-operator-e2e -test.timeout 30m -test.failfast -test.parallel 4 --namespace=${TEST_NAMESPACE}\n"
  },
  {
    "path": "third_party/etcd-operator/test/pod/simple/simple-pod-templ.yaml",
    "content": "apiVersion: v1\nkind: Pod\nmetadata:\n  name: etcd-operator-e2e-tests\nspec:\n  restartPolicy: Never\n  containers:\n  - name: etcd-operator-e2e-tests\n    image: <TEST_IMAGE>\n    imagePullPolicy: Always\n    env:\n      - name: TEST_NAMESPACE\n        valueFrom:\n          fieldRef:\n            fieldPath: metadata.namespace\n"
  },
  {
    "path": "third_party/etcd-operator/test/pod/test-pod-templ.yaml",
    "content": "apiVersion: v1\nkind: Pod\nmetadata:\n  name: <POD_NAME>\nspec:\n  restartPolicy: Never\n  containers:\n  - name: <POD_NAME>\n    image: <TEST_IMAGE>\n    imagePullPolicy: Always\n    command: [\"hack/test\"]\n    resources:\n      requests:\n        cpu: 2\n    env:\n      - name: TEST_NAMESPACE\n        valueFrom:\n          fieldRef:\n            fieldPath: metadata.namespace\n      - name: PASSES\n        value: <PASSES>\n      - name: OPERATOR_IMAGE\n        value: <OPERATOR_IMAGE>\n      - name: E2E_TEST_SELECTOR\n        value: <E2E_TEST_SELECTOR>\n      - name: TEST_S3_BUCKET\n        value: <TEST_S3_BUCKET>\n      - name: TEST_AWS_SECRET\n        value: <TEST_AWS_SECRET>\n      - name: PARALLEL_TEST\n        value: \"true\"\n      - name: UPGRADE_TEST_SELECTOR\n        value: <UPGRADE_TEST_SELECTOR>\n      - name: UPGRADE_FROM\n        value: <UPGRADE_FROM>\n      - name: UPGRADE_TO\n        value: <UPGRADE_TO>\n"
  },
  {
    "path": "third_party/etcd-operator/version/version.go",
    "content": "// Copyright 2016 The etcd-operator 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\npackage version\n\nvar (\n\tVersion = \"0.9.4+git\"\n\tGitSHA  = \"Not provided (use ./build instead of go build)\"\n)\n"
  }
]