├── .circleci └── config.yml ├── .github ├── pull_request_template.md └── workflows │ ├── zz_generated.add-team-labels.yaml │ ├── zz_generated.add-to-project-board.yaml │ ├── zz_generated.check_values_schema.yaml │ ├── zz_generated.create_release.yaml │ ├── zz_generated.create_release_pr.yaml │ ├── zz_generated.gitleaks.yaml │ └── zz_generated.run_ossf_scorecard.yaml ├── .gitignore ├── .golangci.yaml ├── .nancy-ignore ├── .nancy-ignore.generated ├── .pre-commit-config.yaml ├── CHANGELOG.md ├── CODEOWNERS ├── DCO ├── Dockerfile ├── Documentation ├── storage.md └── targets.md ├── LICENSE ├── Makefile ├── Makefile.gen.app.mk ├── Makefile.gen.go.mk ├── Makefile.gen.k8sapi.mk ├── README.md ├── SECURITY.md ├── api └── v1alpha1 │ ├── doc.go │ ├── register.go │ ├── remoteWrite_types.go │ └── zz_generated.deepcopy.go ├── config └── crd │ └── monitoring.giantswarm.io_remotewrites.yaml ├── examples └── remotewrite.yaml ├── files └── templates │ ├── alertmanager │ ├── alertmanager.yaml │ └── notification-template.tmpl │ └── scrapeconfigs │ ├── _apiserver.yaml │ ├── _cert_exporter_namespace.yaml │ ├── _common.yaml │ ├── _labelingschema.yaml │ ├── _node_exporter_namespace.yaml │ ├── _node_role.yaml │ ├── _tlsconfig.yaml │ ├── _tlsconfig_skip.yaml │ └── additional-scrape-configs.template.yaml ├── flag ├── flag.go └── service │ ├── alertmanager │ └── alertmanager.go │ ├── grafana │ └── grafana.go │ ├── ingress │ └── ingress.go │ ├── installation │ └── installation.go │ ├── mimir │ └── mimir.go │ ├── opsgenie │ └── opsgenie.go │ ├── prometheus │ └── prometheus.go │ ├── provider │ └── provider.go │ ├── security │ └── security.go │ ├── service.go │ ├── slack │ └── slack.go │ └── vault │ └── vault.go ├── go.mod ├── go.sum ├── hack ├── .gitignore ├── boilerplate.go.txt └── sync-heartbeat-silences.sh ├── helm └── prometheus-meta-operator │ ├── Chart.yaml │ ├── templates │ ├── _helpers.tpl │ ├── _resource.tpl │ ├── alertmanager │ │ ├── alertmanager-global-secret.yaml │ │ ├── alertmanager-ingress.yaml │ │ ├── alertmanager-psp.yaml │ │ ├── alertmanager-rbac.yaml │ │ ├── alertmanager-service-account.yaml │ │ ├── alertmanager-tls-secret.yaml │ │ ├── alertmanager.yaml │ │ ├── cilium-network-policy.yaml │ │ └── servicemonitor.yaml │ ├── cilium-network-policy.yaml │ ├── configmap.yaml │ ├── deployment.yaml │ ├── ingress-oauth.yaml │ ├── kyverno-policy-exception.yaml │ ├── pod-monitor.yaml │ ├── priority-class.yaml │ ├── prometheus │ │ ├── prometheus-psp.yaml │ │ ├── prometheus-rbac.yaml │ │ └── prometheus-tls-secret.yaml │ ├── psp.yaml │ ├── rbac.yaml │ ├── remoteWrites_crd.yaml │ ├── secret.yaml │ └── service-account.yaml │ ├── values.schema.json │ └── values.yaml ├── main.go ├── pkg ├── cluster │ └── types.go ├── organization │ └── reader.go ├── password │ └── manager.go ├── project │ ├── project.go │ └── version_bundle.go ├── prometheus │ └── agent │ │ ├── sharding.go │ │ └── sharding_test.go ├── prometheusquerier │ └── querier.go ├── pvcresizing │ ├── pvc.go │ └── pvc_test.go ├── remotewrite │ └── configuration │ │ ├── error.go │ │ ├── type.go │ │ └── utils.go ├── remotewriteutils │ ├── error.go │ ├── util.go │ └── util_test.go ├── template │ └── template.go └── unittest │ ├── error.go │ ├── input │ ├── capi │ │ ├── case-1-capa-mc.golden │ │ ├── case-2-capa.golden │ │ ├── case-3-capz.golden │ │ ├── case-4-eks.golden │ │ └── case-5-gcp.golden │ └── vintage │ │ ├── case-1-vintage-mc.golden │ │ ├── case-2-aws-v16.golden │ │ └── case-3-aws-v18.golden │ └── unittest.go ├── renovate.json5 ├── server ├── endpoint │ ├── endpoint.go │ └── error.go ├── error.go └── server.go └── service ├── controller ├── clusterapi │ ├── controller.go │ ├── error.go │ └── resource.go ├── managementcluster │ ├── controller.go │ ├── error.go │ ├── resource.go │ └── wrapper.go ├── remotewrite │ ├── controller.go │ ├── error.go │ └── resource.go └── resource │ ├── alerting │ ├── alertmanagerconfig │ │ ├── create.go │ │ ├── delete.go │ │ ├── error.go │ │ ├── resource.go │ │ ├── resource_test.go │ │ └── test │ │ │ ├── alertmanager-config │ │ │ ├── classic │ │ │ │ ├── capi │ │ │ │ │ ├── case-1-capa-mc.golden │ │ │ │ │ ├── case-2-capa.golden │ │ │ │ │ ├── case-3-capz.golden │ │ │ │ │ ├── case-4-eks.golden │ │ │ │ │ └── case-5-gcp.golden │ │ │ │ └── vintage │ │ │ │ │ ├── case-1-vintage-mc.golden │ │ │ │ │ ├── case-2-aws-v16.golden │ │ │ │ │ └── case-3-aws-v18.golden │ │ │ ├── mimir-enabled │ │ │ │ ├── capi │ │ │ │ │ ├── case-1-capa-mc.golden │ │ │ │ │ ├── case-2-capa.golden │ │ │ │ │ ├── case-3-capz.golden │ │ │ │ │ ├── case-4-eks.golden │ │ │ │ │ └── case-5-gcp.golden │ │ │ │ └── vintage │ │ │ │ │ ├── case-1-vintage-mc.golden │ │ │ │ │ ├── case-2-aws-v16.golden │ │ │ │ │ └── case-3-aws-v18.golden │ │ │ └── slack-token │ │ │ │ ├── capi │ │ │ │ ├── case-1-capa-mc.golden │ │ │ │ ├── case-2-capa.golden │ │ │ │ ├── case-3-capz.golden │ │ │ │ ├── case-4-eks.golden │ │ │ │ └── case-5-gcp.golden │ │ │ │ └── vintage │ │ │ │ ├── case-1-vintage-mc.golden │ │ │ │ ├── case-2-aws-v16.golden │ │ │ │ └── case-3-aws-v18.golden │ │ │ └── notification-template │ │ │ ├── classic │ │ │ ├── capi │ │ │ │ ├── case-1-capa-mc.golden │ │ │ │ ├── case-2-capa.golden │ │ │ │ ├── case-3-capz.golden │ │ │ │ ├── case-4-eks.golden │ │ │ │ └── case-5-gcp.golden │ │ │ └── vintage │ │ │ │ ├── case-1-vintage-mc.golden │ │ │ │ ├── case-2-aws-v16.golden │ │ │ │ └── case-3-aws-v18.golden │ │ │ └── mimir-enabled │ │ │ ├── capi │ │ │ ├── case-1-capa-mc.golden │ │ │ ├── case-2-capa.golden │ │ │ ├── case-3-capz.golden │ │ │ ├── case-4-eks.golden │ │ │ └── case-5-gcp.golden │ │ │ └── vintage │ │ │ ├── case-1-vintage-mc.golden │ │ │ ├── case-2-aws-v16.golden │ │ │ └── case-3-aws-v18.golden │ ├── alertmanagerwiring │ │ ├── client.go │ │ ├── error.go │ │ ├── resource.go │ │ ├── resource_test.go │ │ └── test │ │ │ ├── capi │ │ │ ├── case-1-capa-mc.golden │ │ │ ├── case-2-capa.golden │ │ │ ├── case-3-capz.golden │ │ │ ├── case-4-eks.golden │ │ │ └── case-5-gcp.golden │ │ │ └── vintage │ │ │ ├── case-1-vintage-mc.golden │ │ │ ├── case-2-aws-v16.golden │ │ │ └── case-3-aws-v18.golden │ ├── heartbeat │ │ ├── create.go │ │ ├── delete.go │ │ ├── error.go │ │ └── resource.go │ └── heartbeatwebhookconfig │ │ ├── create.go │ │ ├── delete.go │ │ ├── error.go │ │ ├── resource.go │ │ ├── resource_test.go │ │ └── test │ │ ├── capi │ │ ├── case-1-capa-mc.golden │ │ ├── case-2-capa.golden │ │ ├── case-3-capz.golden │ │ ├── case-4-eks.golden │ │ └── case-5-gcp.golden │ │ └── vintage │ │ ├── case-1-vintage-mc.golden │ │ ├── case-2-aws-v16.golden │ │ └── case-3-aws-v18.golden │ ├── certificates │ ├── create.go │ ├── delete.go │ ├── doc.go │ ├── error.go │ └── resource.go │ ├── ciliumnetpol │ ├── create.go │ ├── delete.go │ ├── error.go │ └── resource.go │ ├── etcd-certificates │ ├── client.go │ ├── doc.go │ ├── error.go │ ├── resource.go │ ├── source.go │ └── target.go │ ├── generic │ ├── create.go │ ├── delete.go │ ├── error.go │ └── resource.go │ ├── monitoring │ ├── ingress │ │ ├── client.go │ │ ├── resource.go │ │ ├── resource_test.go │ │ └── test │ │ │ ├── default │ │ │ ├── capi │ │ │ │ ├── case-1-capa-mc.golden │ │ │ │ ├── case-2-capa.golden │ │ │ │ ├── case-3-capz.golden │ │ │ │ ├── case-4-eks.golden │ │ │ │ └── case-5-gcp.golden │ │ │ └── vintage │ │ │ │ ├── case-1-vintage-mc.golden │ │ │ │ ├── case-2-aws-v16.golden │ │ │ │ └── case-3-aws-v18.golden │ │ │ ├── externaldns-with-restricted-access │ │ │ ├── capi │ │ │ │ ├── case-1-capa-mc.golden │ │ │ │ ├── case-2-capa.golden │ │ │ │ ├── case-3-capz.golden │ │ │ │ ├── case-4-eks.golden │ │ │ │ └── case-5-gcp.golden │ │ │ └── vintage │ │ │ │ ├── case-1-vintage-mc.golden │ │ │ │ ├── case-2-aws-v16.golden │ │ │ │ └── case-3-aws-v18.golden │ │ │ ├── externaldns │ │ │ ├── capi │ │ │ │ ├── case-1-capa-mc.golden │ │ │ │ ├── case-2-capa.golden │ │ │ │ ├── case-3-capz.golden │ │ │ │ ├── case-4-eks.golden │ │ │ │ └── case-5-gcp.golden │ │ │ └── vintage │ │ │ │ ├── case-1-vintage-mc.golden │ │ │ │ ├── case-2-aws-v16.golden │ │ │ │ └── case-3-aws-v18.golden │ │ │ └── restricted-access │ │ │ ├── capi │ │ │ ├── case-1-capa-mc.golden │ │ │ ├── case-2-capa.golden │ │ │ ├── case-3-capz.golden │ │ │ ├── case-4-eks.golden │ │ │ └── case-5-gcp.golden │ │ │ └── vintage │ │ │ ├── case-1-vintage-mc.golden │ │ │ ├── case-2-aws-v16.golden │ │ │ └── case-3-aws-v18.golden │ ├── prometheus │ │ ├── client.go │ │ ├── error.go │ │ ├── resource.go │ │ ├── resource_test.go │ │ └── test │ │ │ ├── classic │ │ │ ├── capi │ │ │ │ ├── case-1-capa-mc.golden │ │ │ │ ├── case-2-capa.golden │ │ │ │ ├── case-3-capz.golden │ │ │ │ ├── case-4-eks.golden │ │ │ │ └── case-5-gcp.golden │ │ │ └── vintage │ │ │ │ ├── case-1-vintage-mc.golden │ │ │ │ ├── case-2-aws-v16.golden │ │ │ │ └── case-3-aws-v18.golden │ │ │ └── mimir-enabled │ │ │ ├── capi │ │ │ ├── case-1-capa-mc.golden │ │ │ ├── case-2-capa.golden │ │ │ ├── case-3-capz.golden │ │ │ ├── case-4-eks.golden │ │ │ └── case-5-gcp.golden │ │ │ └── vintage │ │ │ ├── case-1-vintage-mc.golden │ │ │ ├── case-2-aws-v16.golden │ │ │ └── case-3-aws-v18.golden │ ├── pvcresizingresource │ │ ├── create.go │ │ ├── delete.go │ │ ├── doc.go │ │ └── resource.go │ ├── remotewriteapiendpointconfigsecret │ │ ├── create.go │ │ ├── delete.go │ │ ├── doc.go │ │ ├── error.go │ │ └── resource.go │ ├── remotewriteconfig │ │ ├── create.go │ │ ├── delete.go │ │ ├── error.go │ │ └── resource.go │ ├── remotewriteingress │ │ ├── create.go │ │ ├── delete.go │ │ ├── resource.go │ │ ├── resource_test.go │ │ └── test │ │ │ ├── default │ │ │ ├── capi │ │ │ │ ├── case-1-capa-mc.golden │ │ │ │ ├── case-2-capa.golden │ │ │ │ ├── case-3-capz.golden │ │ │ │ ├── case-4-eks.golden │ │ │ │ └── case-5-gcp.golden │ │ │ └── vintage │ │ │ │ ├── case-1-vintage-mc.golden │ │ │ │ ├── case-2-aws-v16.golden │ │ │ │ └── case-3-aws-v18.golden │ │ │ └── externaldns │ │ │ ├── capi │ │ │ ├── case-1-capa-mc.golden │ │ │ ├── case-2-capa.golden │ │ │ ├── case-3-capz.golden │ │ │ ├── case-4-eks.golden │ │ │ └── case-5-gcp.golden │ │ │ └── vintage │ │ │ ├── case-1-vintage-mc.golden │ │ │ ├── case-2-aws-v16.golden │ │ │ └── case-3-aws-v18.golden │ ├── remotewriteingressauth │ │ ├── create.go │ │ ├── delete.go │ │ ├── doc.go │ │ └── resource.go │ ├── remotewritesecret │ │ ├── create.go │ │ ├── delete.go │ │ ├── error.go │ │ └── resource.go │ ├── scrapeconfigs │ │ ├── client.go │ │ ├── error.go │ │ ├── resource.go │ │ ├── resource_test.go │ │ └── test │ │ │ ├── aws │ │ │ ├── case-1-vintage-mc.golden │ │ │ ├── case-2-aws-v16.golden │ │ │ └── case-3-aws-v18.golden │ │ │ ├── azure │ │ │ ├── case-1-vintage-mc.golden │ │ │ ├── case-2-aws-v16.golden │ │ │ └── case-3-aws-v18.golden │ │ │ ├── capa │ │ │ ├── case-1-capa-mc.golden │ │ │ ├── case-2-capa.golden │ │ │ ├── case-3-capz.golden │ │ │ ├── case-4-eks.golden │ │ │ └── case-5-gcp.golden │ │ │ ├── capz │ │ │ ├── case-1-capa-mc.golden │ │ │ ├── case-2-capa.golden │ │ │ ├── case-3-capz.golden │ │ │ ├── case-4-eks.golden │ │ │ └── case-5-gcp.golden │ │ │ └── gcp │ │ │ ├── case-1-capa-mc.golden │ │ │ ├── case-2-capa.golden │ │ │ ├── case-3-capz.golden │ │ │ ├── case-4-eks.golden │ │ │ └── case-5-gcp.golden │ └── verticalpodautoscaler │ │ ├── create.go │ │ ├── delete.go │ │ ├── error.go │ │ ├── resource.go │ │ ├── resource_test.go │ │ └── test │ │ ├── capi │ │ ├── case-1-capa-mc.golden │ │ ├── case-2-capa.golden │ │ ├── case-3-capz.golden │ │ ├── case-4-eks.golden │ │ └── case-5-gcp.golden │ │ └── vintage │ │ ├── case-1-vintage-mc.golden │ │ ├── case-2-aws-v16.golden │ │ └── case-3-aws-v18.golden │ ├── namespace │ ├── client.go │ ├── resource.go │ ├── resource_test.go │ └── test │ │ ├── capi │ │ ├── case-1-capa-mc.golden │ │ ├── case-2-capa.golden │ │ ├── case-3-capz.golden │ │ ├── case-4-eks.golden │ │ └── case-5-gcp.golden │ │ └── vintage │ │ ├── case-1-vintage-mc.golden │ │ ├── case-2-aws-v16.golden │ │ └── case-3-aws-v18.golden │ ├── noop │ └── noop.go │ ├── prometheusremotewrite │ ├── create.go │ ├── delete.go │ ├── error.go │ ├── resource.go │ └── resource_test.go │ ├── rbac │ ├── create.go │ ├── delete.go │ ├── doc.go │ ├── error.go │ └── resource.go │ ├── remotewritesecret │ ├── create.go │ ├── delete.go │ ├── error.go │ └── resource.go │ ├── resourceutils │ └── utils.go │ └── wrapper │ └── monitoringdisabledresource │ ├── error.go │ ├── resource.go │ └── wrap.go ├── error.go ├── key ├── error.go └── key.go └── service.go /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | orbs: 4 | architect: giantswarm/architect@5.14.0 5 | workflows: 6 | build: 7 | jobs: 8 | - architect/go-build: 9 | name: build 10 | binary: prometheus-meta-operator 11 | resource_class: large 12 | filters: 13 | tags: 14 | only: /^v.*/ 15 | 16 | - architect/push-to-registries: 17 | context: architect 18 | name: push-to-registries 19 | requires: 20 | - build 21 | filters: 22 | tags: 23 | only: /^v.*/ 24 | 25 | branches: 26 | ignore: 27 | - main 28 | - master 29 | - architect/push-to-app-catalog: 30 | name: app-catalog 31 | context: architect 32 | app_catalog: control-plane-catalog 33 | app_catalog_test: control-plane-test-catalog 34 | chart: prometheus-meta-operator 35 | requires: 36 | - build 37 | filters: 38 | tags: 39 | only: /^v.*/ 40 | 41 | branches: 42 | ignore: 43 | - main 44 | - master 45 | - architect/push-to-app-collection: 46 | name: aws-app-collection 47 | context: architect 48 | app_name: prometheus-meta-operator 49 | app_namespace: monitoring 50 | app_collection_repo: aws-app-collection 51 | requires: 52 | - app-catalog 53 | - push-to-registries 54 | filters: 55 | branches: 56 | ignore: /.*/ 57 | tags: 58 | only: /^v.*/ 59 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Checklist 2 | 3 | I have: 4 | 5 | - [ ] Described why this change is being introduced 6 | - [ ] Separated out refactoring/reformatting in a dedicated PR 7 | - [ ] Updated changelog in `CHANGELOG.md` 8 | -------------------------------------------------------------------------------- /.github/workflows/zz_generated.gitleaks.yaml: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT. Generated with: 2 | # 3 | # devctl 4 | # 5 | # https://github.com/giantswarm/devctl/blob/8960b8810d2fdb97543d84baa8b50ffa40da26a9/pkg/gen/input/workflows/internal/file/gitleaks.yaml.template 6 | # 7 | name: gitleaks 8 | 9 | on: [pull_request] 10 | 11 | jobs: 12 | gitleaks: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 16 | with: 17 | fetch-depth: '0' 18 | - name: gitleaks-action 19 | uses: giantswarm/gitleaks-action@main 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | TODO 3 | /prometheus-meta-operator 4 | !vendor/** 5 | -------------------------------------------------------------------------------- /.golangci.yaml: -------------------------------------------------------------------------------- 1 | run: 2 | skip-dirs: 3 | - pkg/prometheus/common/config 4 | - pkg/alertmanager/config 5 | -------------------------------------------------------------------------------- /.nancy-ignore: -------------------------------------------------------------------------------- 1 | # pkg:golang/golang.org/x/net@v0.29.0 2 | CVE-2024-8421 3 | -------------------------------------------------------------------------------- /.nancy-ignore.generated: -------------------------------------------------------------------------------- 1 | # This file is generated by https://github.com/giantswarm/github 2 | # Repository specific ignores should be added to .nancy-ignore 3 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # This file is maintained centrally at 2 | # https://github.com/giantswarm/github/blob/main/languages/go/.pre-commit-config.yaml 3 | 4 | minimum_pre_commit_version: '2.17' 5 | repos: 6 | # shell scripts 7 | - repo: https://github.com/detailyang/pre-commit-shell 8 | rev: 1.0.5 9 | hooks: 10 | - id: shell-lint 11 | args: [ --format=json ] 12 | exclude: ".*\\.template" 13 | 14 | - repo: https://github.com/pre-commit/pre-commit-hooks 15 | rev: v5.0.0 16 | hooks: 17 | - id: check-added-large-files 18 | - id: check-merge-conflict 19 | - id: check-shebang-scripts-are-executable 20 | - id: detect-private-key 21 | - id: end-of-file-fixer 22 | exclude: ".*testdata/.*" 23 | - id: mixed-line-ending 24 | - id: trailing-whitespace 25 | exclude: ".*testdata/.*" 26 | 27 | - repo: https://github.com/dnephin/pre-commit-golang 28 | rev: v0.5.1 29 | hooks: 30 | - id: go-fmt 31 | - id: go-mod-tidy 32 | - id: golangci-lint 33 | # timeout is needed for CI 34 | args: [ -E, gosec, -E, goconst, -E, govet, --timeout, 300s ] 35 | - id: go-imports 36 | args: [ -local, github.com/giantswarm/prometheus-meta-operator ] 37 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # generated by giantswarm/github actions - changes will be overwritten 2 | * @giantswarm/team-atlas 3 | -------------------------------------------------------------------------------- /DCO: -------------------------------------------------------------------------------- 1 | Developer Certificate of Origin 2 | Version 1.1 3 | 4 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 5 | 660 York Street, Suite 102, 6 | San Francisco, CA 94110 USA 7 | 8 | Everyone is permitted to copy and distribute verbatim copies of this 9 | license document, but changing it is not allowed. 10 | 11 | 12 | Developer's Certificate of Origin 1.1 13 | 14 | By making a contribution to this project, I certify that: 15 | 16 | (a) The contribution was created in whole or in part by me and I 17 | have the right to submit it under the open source license 18 | indicated in the file; or 19 | 20 | (b) The contribution is based upon previous work that, to the best 21 | of my knowledge, is covered under an appropriate open source 22 | license and I have the right under that license to submit that 23 | work with modifications, whether created in whole or in part 24 | by me, under the same open source license (unless I am 25 | permitted to submit under a different license), as indicated 26 | in the file; or 27 | 28 | (c) The contribution was provided directly to me by some other 29 | person who certified (a), (b) or (c) and I have not modified 30 | it. 31 | 32 | (d) I understand and agree that this project and the contribution 33 | are public and that a record of the contribution (including all 34 | personal information I submit with it, including my sign-off) is 35 | maintained indefinitely and may be redistributed consistent with 36 | this project or the open source license(s) involved. 37 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.21.3 2 | 3 | RUN apk add --no-cache ca-certificates 4 | 5 | ADD ./files /opt/prometheus-meta-operator/files 6 | 7 | ADD ./prometheus-meta-operator /prometheus-meta-operator 8 | 9 | ENTRYPOINT ["/prometheus-meta-operator"] 10 | -------------------------------------------------------------------------------- /Documentation/storage.md: -------------------------------------------------------------------------------- 1 | # Prometheus storage 2 | 3 | When possible on customers installations, we decided to use dynamic provisioning to create volumes to store prometheus data. 4 | 5 | As some installations do not support dynamic provisioning (some on-prem installations), we decided to ask customers to provision volumes in the following pattern: 6 | 7 | - 1 Volume for the management cluster. 8 | - 1 Volume per workload cluster managed by the management cluster. 9 | - 1 extra volume that we can use in case a new cluster is created. 10 | 11 | ## Retention 12 | 13 | Max Retention size: **95 GB** 14 | 15 | ## Volume sizing 16 | 17 | We decided to use the same volume size accross all our clusters as to avoid having to figure out all the details regarding sizing per cluster, volume expansion and so on. 18 | 19 | Current Volume Size: **100GB** 20 | 21 | Reasons: 22 | 23 | As described in the [prometheus doc](https://www.prometheus.io/docs/prometheus/latest/storage/) and [Stack Exchange](https://devops.stackexchange.com/questions/9298/how-to-calculate-disk-space-required-by-prometheus-v2-2): 24 | 25 | **needed_disk_space** = **retention_time_in_seconds** * **ingested_samples_per_second** ** **bytes_per_sample** 26 | 27 | With: 28 | 29 | - retention_time_in_seconds = 1209600s 30 | - bytes_per_sample = rate(prometheus_tsdb_compaction_chunk_size_bytes_sum[1d]) / rate(prometheus_tsdb_compaction_chunk_samples_sum[1d]) for bytes / sample 31 | - ingested_samples_per_second = rate(prometheus_tsdb_head_samples_appended_total[2h]) 32 | 33 | 34 | By taking one of our biggest cluster on asgard, we found **bytes_per_sample** = _1.0811677050996586_ and **ingested_samples_per_second** = _41713_ 35 | 36 | With this, **needed_disk_space** = 1209600 * 41713 * 1.08 bytes ~= 54 GB 37 | 38 | As our storage needs will grow, we decided to go with 100 GB for now 39 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT. Generated with: 2 | # 3 | # devctl 4 | # 5 | # https://github.com/giantswarm/devctl/blob/6a704f7e2a8b0f09e82b5bab88f17971af849711/pkg/gen/input/makefile/internal/file/Makefile.template 6 | # 7 | 8 | include Makefile.*.mk 9 | 10 | ##@ General 11 | 12 | # The help target prints out all targets with their descriptions organized 13 | # beneath their categories. The categories are represented by '##@' and the 14 | # target descriptions by '##'. The awk commands is responsible for reading the 15 | # entire set of makefiles included in this invocation, looking for lines of the 16 | # file as xyz: ## something, and then pretty-format the target and help. Then, 17 | # if there's a line with ##@ something, that gets pretty-printed as a category. 18 | # More info on the usage of ANSI control characters for terminal formatting: 19 | # https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters 20 | # More info on the awk command: 21 | # http://linuxcommand.org/lc3_adv_awk.php 22 | 23 | .PHONY: help 24 | help: ## Display this help. 25 | @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z%\\\/_0-9-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) 26 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | Please visit for information on reporting security issues. 6 | -------------------------------------------------------------------------------- /api/v1alpha1/doc.go: -------------------------------------------------------------------------------- 1 | // +k8s:openapi-gen=true 2 | // +k8s:deepcopy-gen=package,register 3 | 4 | // +groupName=monitoring.giantswarm.io 5 | package v1alpha1 6 | -------------------------------------------------------------------------------- /api/v1alpha1/register.go: -------------------------------------------------------------------------------- 1 | package v1alpha1 2 | 3 | import ( 4 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 5 | "k8s.io/apimachinery/pkg/runtime" 6 | "k8s.io/apimachinery/pkg/runtime/schema" 7 | ) 8 | 9 | const ( 10 | group = "monitoring.giantswarm.io" 11 | version = "v1alpha1" 12 | ) 13 | 14 | // knownTypes is the full list of objects to register with the scheme. It 15 | // should contain all zero values of custom objects and custom object lists 16 | // in the group version. 17 | var knownTypes = []runtime.Object{ 18 | &RemoteWrite{}, 19 | &RemoteWriteList{}, 20 | } 21 | 22 | // SchemeGroupVersion is group version used to register these objects 23 | var SchemeGroupVersion = schema.GroupVersion{ 24 | Group: group, 25 | Version: version, 26 | } 27 | 28 | var ( 29 | schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) 30 | 31 | // AddToScheme is used by the generated client. 32 | AddToScheme = schemeBuilder.AddToScheme 33 | ) 34 | 35 | // Adds the list of known types to api.Scheme. 36 | func addKnownTypes(scheme *runtime.Scheme) error { 37 | scheme.AddKnownTypes(SchemeGroupVersion, knownTypes...) 38 | metav1.AddToGroupVersion(scheme, SchemeGroupVersion) 39 | return nil 40 | } 41 | -------------------------------------------------------------------------------- /examples/remotewrite.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.giantswarm.io/v1alpha1 2 | kind: RemoteWrite 3 | metadata: 4 | name: grafana-cloud 5 | spec: 6 | clusterSelector: 7 | matchLabels: 8 | 'giantswarm.io/cluster': 'ginger' 9 | remoteWrite: 10 | name: test 11 | url: https://some-url.grafana.net/api/prom/push 12 | basicAuth: 13 | password: 14 | key: password 15 | name: grafana-cloud-auth-basic 16 | username: 17 | key: username 18 | name: grafana-cloud-auth-basic 19 | remoteTimeout: "60s" 20 | queueConfig: 21 | capacity: 10000 22 | maxSamplesPerSend: 1000 23 | minShards: 10 24 | # Secrets provided here must be defined in the remotewrite config 25 | secrets: 26 | - name: grafana-cloud-auth-basic 27 | data: 28 | username: YWRtaW4K 29 | password: YWRtaW4K 30 | -------------------------------------------------------------------------------- /files/templates/scrapeconfigs/_apiserver.yaml: -------------------------------------------------------------------------------- 1 | [[- define "_apiserver" -]] 2 | [[- if ne .ClusterType "management_cluster" ]] 3 | api_server: https://[[ .APIServerURL ]] 4 | [[- if eq .AuthenticationType "token" ]] 5 | bearer_token_file: /etc/prometheus/secrets/[[ .SecretName ]]/token 6 | [[- end ]] 7 | tls_config: 8 | ca_file: /etc/prometheus/secrets/[[ .SecretName ]]/ca 9 | [[- if eq .AuthenticationType "certificates" ]] 10 | cert_file: /etc/prometheus/secrets/[[ .SecretName ]]/crt 11 | key_file: /etc/prometheus/secrets/[[ .SecretName ]]/key 12 | [[- end ]] 13 | insecure_skip_verify: false 14 | [[- end -]] 15 | [[- end -]] 16 | -------------------------------------------------------------------------------- /files/templates/scrapeconfigs/_cert_exporter_namespace.yaml: -------------------------------------------------------------------------------- 1 | [[- define "_cert_exporter_namespace" -]] 2 | [[- if and (eq .ClusterType "management_cluster") (.VintageManagementCluster) -]] 3 | monitoring 4 | [[- else -]] 5 | kube-system 6 | [[- end -]] 7 | [[- end -]] 8 | -------------------------------------------------------------------------------- /files/templates/scrapeconfigs/_common.yaml: -------------------------------------------------------------------------------- 1 | [[- define "_common" -]] 2 | # Add namespace label. 3 | - source_labels: [__meta_kubernetes_namespace] 4 | target_label: namespace 5 | # Add pod label. 6 | - source_labels: [__meta_kubernetes_pod_name] 7 | target_label: pod 8 | # Add container label. 9 | - source_labels: [__meta_kubernetes_pod_container_name] 10 | target_label: container 11 | # Add node label. 12 | - source_labels: [__meta_kubernetes_pod_node_name] 13 | target_label: node 14 | [[ include "_node_role" . ]] 15 | [[- end -]] 16 | -------------------------------------------------------------------------------- /files/templates/scrapeconfigs/_labelingschema.yaml: -------------------------------------------------------------------------------- 1 | [[- define "_labelingschema" -]] 2 | # Add cluster_id label. 3 | - target_label: cluster_id 4 | replacement: [[ .ClusterID ]] 5 | # Add cluster_type label. 6 | - target_label: cluster_type 7 | replacement: [[ .ClusterType ]] 8 | # Add customer label. 9 | - target_label: customer 10 | replacement: [[ .Customer ]] 11 | # Add installation label. 12 | - target_label: installation 13 | replacement: [[ .Installation ]] 14 | # Add organization label. 15 | - target_label: organization 16 | replacement: [[ .Organization | default "giantswarm" ]] 17 | # Add pipeline label. 18 | - target_label: pipeline 19 | replacement: [[ .Pipeline ]] 20 | # Add provider label. 21 | - target_label: provider 22 | replacement: [[ .Provider ]] 23 | # Add provider label. 24 | - target_label: region 25 | replacement: [[ .Region ]] 26 | # Add priority label. 27 | - target_label: service_priority 28 | replacement: [[ .ServicePriority | default "highest"]] 29 | [[- end -]] 30 | -------------------------------------------------------------------------------- /files/templates/scrapeconfigs/_node_exporter_namespace.yaml: -------------------------------------------------------------------------------- 1 | [[- define "_node_exporter_namespace" -]] 2 | [[- if and (eq .ClusterType "management_cluster") (.VintageManagementCluster) -]] 3 | monitoring 4 | [[- else -]] 5 | kube-system 6 | [[- end -]] 7 | [[- end -]] 8 | -------------------------------------------------------------------------------- /files/templates/scrapeconfigs/_node_role.yaml: -------------------------------------------------------------------------------- 1 | [[- define "_node_role" -]] 2 | # Add role label. 3 | - source_labels: [__meta_kubernetes_node_label_role] 4 | target_label: role 5 | [[- end -]] 6 | -------------------------------------------------------------------------------- /files/templates/scrapeconfigs/_tlsconfig.yaml: -------------------------------------------------------------------------------- 1 | [[- define "_tlsconfig" -]] 2 | [[- if ne .ClusterType "management_cluster" -]] 3 | [[- if eq .AuthenticationType "token" ]] 4 | bearer_token_file: /etc/prometheus/secrets/[[ .SecretName ]]/token 5 | [[- end ]] 6 | tls_config: 7 | ca_file: /etc/prometheus/secrets/[[ .SecretName ]]/ca 8 | [[- if eq .AuthenticationType "certificates" ]] 9 | cert_file: /etc/prometheus/secrets/[[ .SecretName ]]/crt 10 | key_file: /etc/prometheus/secrets/[[ .SecretName ]]/key 11 | [[- end ]] 12 | insecure_skip_verify: false 13 | [[- else ]] 14 | bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token 15 | tls_config: 16 | ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt 17 | insecure_skip_verify: true 18 | [[- end -]] 19 | [[- end -]] 20 | -------------------------------------------------------------------------------- /files/templates/scrapeconfigs/_tlsconfig_skip.yaml: -------------------------------------------------------------------------------- 1 | [[- define "_tlsconfig_skip" -]] 2 | [[- if ne .ClusterType "management_cluster" -]] 3 | [[- if eq .AuthenticationType "token" ]] 4 | bearer_token_file: /etc/prometheus/secrets/[[ .SecretName ]]/token 5 | [[- end ]] 6 | tls_config: 7 | ca_file: /etc/prometheus/secrets/[[ .SecretName ]]/ca 8 | [[- if eq .AuthenticationType "certificates" ]] 9 | cert_file: /etc/prometheus/secrets/[[ .SecretName ]]/crt 10 | key_file: /etc/prometheus/secrets/[[ .SecretName ]]/key 11 | [[- end ]] 12 | insecure_skip_verify: true 13 | [[- else ]] 14 | bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token 15 | tls_config: 16 | ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt 17 | insecure_skip_verify: true 18 | [[- end -]] 19 | [[- end -]] 20 | -------------------------------------------------------------------------------- /flag/flag.go: -------------------------------------------------------------------------------- 1 | package flag 2 | 3 | import ( 4 | "github.com/giantswarm/microkit/flag" 5 | 6 | "github.com/giantswarm/prometheus-meta-operator/v2/flag/service" 7 | ) 8 | 9 | // Flag provides data structure for service command line flags. 10 | type Flag struct { 11 | Service service.Service 12 | } 13 | 14 | // New constructs fills new Flag structure with given command line flags. 15 | func New() *Flag { 16 | f := &Flag{} 17 | flag.Init(f) 18 | 19 | return f 20 | } 21 | -------------------------------------------------------------------------------- /flag/service/alertmanager/alertmanager.go: -------------------------------------------------------------------------------- 1 | package alertmanager 2 | 3 | type Alertmanager struct { 4 | Enabled string 5 | } 6 | -------------------------------------------------------------------------------- /flag/service/grafana/grafana.go: -------------------------------------------------------------------------------- 1 | package grafana 2 | 3 | type Grafana struct { 4 | Address string 5 | } 6 | -------------------------------------------------------------------------------- /flag/service/ingress/ingress.go: -------------------------------------------------------------------------------- 1 | package ingress 2 | 3 | type Ingress struct { 4 | ExternalDNS ExternalDNS 5 | } 6 | 7 | type ExternalDNS struct { 8 | Enabled string 9 | } 10 | -------------------------------------------------------------------------------- /flag/service/installation/installation.go: -------------------------------------------------------------------------------- 1 | package installation 2 | 3 | type Installation struct { 4 | Customer string 5 | InsecureCA string 6 | Name string 7 | Pipeline string 8 | Region string 9 | Registry string 10 | } 11 | -------------------------------------------------------------------------------- /flag/service/mimir/mimir.go: -------------------------------------------------------------------------------- 1 | package mimir 2 | 3 | type Mimir struct { 4 | Enabled string 5 | } 6 | -------------------------------------------------------------------------------- /flag/service/opsgenie/opsgenie.go: -------------------------------------------------------------------------------- 1 | package opsgenie 2 | 3 | type Opsgenie struct { 4 | Key string 5 | } 6 | -------------------------------------------------------------------------------- /flag/service/prometheus/prometheus.go: -------------------------------------------------------------------------------- 1 | package prometheus 2 | 3 | type Prometheus struct { 4 | AdditionalScrapeConfigs string 5 | Address string 6 | BaseDomain string 7 | Bastions string 8 | EvaluationInterval string 9 | ImageRepository string 10 | LogLevel string 11 | ScrapeInterval string 12 | Version string 13 | } 14 | 15 | type PrometheusAgent struct { 16 | ShardScaleUpSeriesCount string 17 | ShardScaleDownPercentage string 18 | } 19 | -------------------------------------------------------------------------------- /flag/service/provider/provider.go: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | type Provider struct { 4 | Kind string 5 | Flavor string 6 | } 7 | -------------------------------------------------------------------------------- /flag/service/security/security.go: -------------------------------------------------------------------------------- 1 | package security 2 | 3 | type Security struct { 4 | RestrictedAccess RestrictedAccess 5 | } 6 | 7 | type RestrictedAccess struct { 8 | Enabled string 9 | Subnets string 10 | } 11 | -------------------------------------------------------------------------------- /flag/service/service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "github.com/giantswarm/operatorkit/v7/pkg/flag/service/kubernetes" 5 | 6 | "github.com/giantswarm/prometheus-meta-operator/v2/flag/service/alertmanager" 7 | "github.com/giantswarm/prometheus-meta-operator/v2/flag/service/grafana" 8 | "github.com/giantswarm/prometheus-meta-operator/v2/flag/service/ingress" 9 | "github.com/giantswarm/prometheus-meta-operator/v2/flag/service/installation" 10 | "github.com/giantswarm/prometheus-meta-operator/v2/flag/service/mimir" 11 | "github.com/giantswarm/prometheus-meta-operator/v2/flag/service/opsgenie" 12 | "github.com/giantswarm/prometheus-meta-operator/v2/flag/service/prometheus" 13 | "github.com/giantswarm/prometheus-meta-operator/v2/flag/service/provider" 14 | "github.com/giantswarm/prometheus-meta-operator/v2/flag/service/security" 15 | "github.com/giantswarm/prometheus-meta-operator/v2/flag/service/slack" 16 | "github.com/giantswarm/prometheus-meta-operator/v2/flag/service/vault" 17 | ) 18 | 19 | // Service is an intermediate data structure for command line configuration flags. 20 | type Service struct { 21 | Alertmanager alertmanager.Alertmanager 22 | Grafana grafana.Grafana 23 | Ingress ingress.Ingress 24 | Installation installation.Installation 25 | Kubernetes kubernetes.Kubernetes 26 | Opsgenie opsgenie.Opsgenie 27 | Mimir mimir.Mimir 28 | Prometheus prometheus.Prometheus 29 | PrometheusAgent prometheus.PrometheusAgent 30 | Provider provider.Provider 31 | Security security.Security 32 | Slack slack.Slack 33 | Vault vault.Vault 34 | } 35 | -------------------------------------------------------------------------------- /flag/service/slack/slack.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | type Slack struct { 4 | ApiToken string 5 | ApiURL string 6 | } 7 | -------------------------------------------------------------------------------- /flag/service/vault/vault.go: -------------------------------------------------------------------------------- 1 | package vault 2 | 3 | type Vault struct { 4 | Host string 5 | } 6 | -------------------------------------------------------------------------------- /hack/.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | -------------------------------------------------------------------------------- /hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright YEAR Giant Swarm GmbH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | -------------------------------------------------------------------------------- /hack/sync-heartbeat-silences.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script help with heartbeat and silences synchronization. 4 | # 5 | # Whenever a cluster is know to have issues, a silence is created in https://github.com/giantswarm/silences repository. 6 | # In some cases this silence might apply to the whole cluster, 7 | # when this is the case heartbeat in Opsgenie for the corresponding cluster 8 | # should be disabled. 9 | # When the silence is then removed the heartbeat in Opsgenie should be re-enabled. 10 | # 11 | # There is currently no automation for this, so this script is here to help humans to do their job right. 12 | # 13 | # Requirements to run this script : 14 | # - heartbeatctl: https://github.com/giantswarm/heartbeatctl 15 | # - silencectl: https://github.com/giantswarm/silencectl 16 | 17 | command -V heartbeatctl 18 | command -V silencectl 19 | 20 | echo "> start" 21 | 22 | echo "> re-enable disabled heartbeats (for cluster with no silences)" 23 | for h in $(heartbeatctl list -s=DISABLED --no-headers|awk '{print $1}'); do grep -q $h <(silencectl list) || heartbeatctl enable $h; done 24 | 25 | echo "> disable heartbeat (for cluster with silences)" 26 | silencectl list | xargs heartbeatctl disable 27 | 28 | echo "> end" 29 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: prometheus-meta-operator 3 | description: The prometheus-meta-operator manages Kubernetes clusters monitoring. 4 | home: https://github.com/giantswarm/prometheus-meta-operator 5 | version: [[ .Version ]] 6 | appVersion: [[ .AppVersion ]] 7 | annotations: 8 | application.giantswarm.io/team: "atlas" 9 | config.giantswarm.io/version: 1.x.x 10 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "name" -}} 6 | {{- .Chart.Name | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create chart name and version as used by the chart label. 11 | */}} 12 | {{- define "chart" -}} 13 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 14 | {{- end -}} 15 | 16 | {{/* 17 | Common labels 18 | */}} 19 | {{- define "labels.common" -}} 20 | app: {{ include "name" . | quote }} 21 | {{ include "labels.selector" . }} 22 | app.kubernetes.io/managed-by: {{ .Release.Service | quote }} 23 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 24 | application.giantswarm.io/team: {{ index .Chart.Annotations "application.giantswarm.io/team" | quote }} 25 | helm.sh/chart: {{ include "chart" . | quote }} 26 | {{- end -}} 27 | 28 | {{/* 29 | Selector labels 30 | */}} 31 | {{- define "labels.selector" -}} 32 | app.kubernetes.io/name: {{ include "name" . | quote }} 33 | app.kubernetes.io/instance: {{ .Release.Name | quote }} 34 | {{- end -}} 35 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/_resource.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Create a name stem for resource names 4 | 5 | When pods for deployments are created they have an additional 16 character 6 | suffix appended, e.g. "-957c9d6ff-pkzgw". Given that Kubernetes allows 63 7 | characters for resource names, the stem is truncated to 47 characters to leave 8 | room for such suffix. 9 | */}} 10 | {{- define "resource.default.name" -}} 11 | {{- .Release.Name | replace "." "-" | trunc 47 | trimSuffix "-" -}} 12 | {{- end -}} 13 | 14 | {{- define "resource.networkPolicy.name" -}} 15 | {{- include "resource.default.name" . -}}-network-policy 16 | {{- end -}} 17 | 18 | {{- define "resource.psp.name" -}} 19 | {{- include "resource.default.name" . -}}-psp 20 | {{- end -}} 21 | 22 | {{- define "resource.default.namespace" -}} 23 | monitoring 24 | {{- end -}} 25 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/alertmanager/alertmanager-global-secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.alertmanager.enabled -}} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | labels: 6 | {{- include "labels.common" . | nindent 4 }} 7 | name: alertmanager-global 8 | namespace: {{ include "resource.default.namespace" . }} 9 | data: 10 | slackApiToken: {{ .Values.alertmanager.slack.apiToken | b64enc | quote }} 11 | slackApiUrl: {{ .Values.alertmanager.slack.apiURL | b64enc | quote }} 12 | opsGenieApiUrl: {{ printf "api.opsgenie.com" | b64enc | quote }} 13 | opsGenieApiKey: {{ .Values.prometheus.heartbeat.opsgenieKey | b64enc | quote }} 14 | {{- end }} 15 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/alertmanager/alertmanager-ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.alertmanager.enabled -}} 2 | {{- if not .Values.mimir.enabled }} 3 | apiVersion: networking.k8s.io/v1 4 | kind: Ingress 5 | metadata: 6 | annotations: 7 | {{- if .Values.prometheus.letsencrypt }} 8 | kubernetes.io/tls-acme: "true" 9 | {{- with .Values.prometheus.clusterIssuerName }} 10 | cert-manager.io/cluster-issuer: "{{ . }}" 11 | {{- end }} 12 | {{- end }} 13 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 14 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 15 | {{- if .Values.security.restrictAccess.enabled }} 16 | nginx.ingress.kubernetes.io/whitelist-source-range: "{{ .Values.security.subnet.vpn }}" 17 | {{- end }} 18 | {{- if .Values.ingress.externalDNS }} 19 | external-dns.alpha.kubernetes.io/hostname: {{ .Values.alertmanager.host }} 20 | giantswarm.io/external-dns: managed 21 | {{- end }} 22 | labels: 23 | {{- include "labels.common" . | nindent 4 }} 24 | name: {{ include "resource.default.name" . }}-alertmanager 25 | namespace: {{ include "resource.default.namespace" . }} 26 | spec: 27 | ingressClassName: {{ .Values.ingress.className }} 28 | rules: 29 | - host: {{ .Values.alertmanager.host }} 30 | http: 31 | paths: 32 | - path: / 33 | pathType: ImplementationSpecific 34 | backend: 35 | service: 36 | name: alertmanager-operated 37 | port: 38 | number: 9093 39 | {{- end }} 40 | {{- end }} 41 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/alertmanager/alertmanager-psp.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.alertmanager.enabled -}} 2 | {{- if not .Values.global.podSecurityStandards.enforced }} 3 | {{- if .Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy" }} 4 | apiVersion: policy/v1beta1 5 | kind: PodSecurityPolicy 6 | metadata: 7 | labels: 8 | {{- include "labels.common" . | nindent 4 }} 9 | name: alertmanager-psp 10 | annotations: 11 | seccomp.security.alpha.kubernetes.io/allowedProfileNames: runtime/default 12 | spec: 13 | allowPrivilegeEscalation: false 14 | hostNetwork: false 15 | hostIPC: false 16 | hostPID: false 17 | fsGroup: 18 | ranges: 19 | - max: 65535 20 | min: 1 21 | rule: MustRunAs 22 | runAsUser: 23 | ranges: 24 | - max: 65535 25 | min: 1000 26 | rule: MustRunAs 27 | seLinux: 28 | rule: RunAsAny 29 | supplementalGroups: 30 | ranges: 31 | - max: 65535 32 | min: 1 33 | rule: MustRunAs 34 | privileged: false 35 | volumes: 36 | - 'configMap' 37 | - 'emptyDir' 38 | - 'projected' 39 | - 'secret' 40 | - 'downwardAPI' 41 | - 'persistentVolumeClaim' 42 | {{- end }} 43 | {{- end }} 44 | {{- end }} 45 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/alertmanager/alertmanager-rbac.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.alertmanager.enabled -}} 2 | {{- if not .Values.global.podSecurityStandards.enforced }} 3 | {{- if .Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy" }} 4 | apiVersion: rbac.authorization.k8s.io/v1 5 | kind: ClusterRole 6 | metadata: 7 | labels: 8 | {{- include "labels.common" . | nindent 4 }} 9 | name: alertmanager 10 | rules: 11 | - apiGroups: 12 | - policy 13 | - extensions 14 | resources: 15 | - podsecuritypolicies 16 | verbs: 17 | - use 18 | resourceNames: 19 | - alertmanager-psp 20 | --- 21 | apiVersion: rbac.authorization.k8s.io/v1 22 | kind: ClusterRoleBinding 23 | metadata: 24 | labels: 25 | {{- include "labels.common" . | nindent 4 }} 26 | name: alertmanager 27 | subjects: 28 | - kind: ServiceAccount 29 | name: alertmanager 30 | namespace: {{ include "resource.default.namespace" . }} 31 | roleRef: 32 | kind: ClusterRole 33 | name: alertmanager 34 | apiGroup: rbac.authorization.k8s.io 35 | {{- end }} 36 | {{- end }} 37 | {{- end }} 38 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/alertmanager/alertmanager-service-account.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.alertmanager.enabled -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | labels: 6 | {{- include "labels.common" . | nindent 4 }} 7 | name: alertmanager 8 | namespace: {{ include "resource.default.namespace" . }} 9 | {{- end }} 10 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/alertmanager/alertmanager-tls-secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.alertmanager.enabled -}} 2 | {{- if not .Values.mimir.enabled }} 3 | {{- if eq .Values.prometheus.letsencrypt false }} 4 | apiVersion: v1 5 | kind: Secret 6 | metadata: 7 | labels: 8 | {{- include "labels.common" . | nindent 4 }} 9 | name: alertmanager-tls 10 | namespace: {{ include "resource.default.namespace" . }} 11 | type: kubernetes.io/tls 12 | data: 13 | tls.crt: {{ .Values.certificate.monitoring.crtPem | quote }} 14 | tls.key: {{ .Values.certificate.monitoring.keyPem | quote }} 15 | {{- end }} 16 | {{- end }} 17 | {{- end }} 18 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/alertmanager/cilium-network-policy.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.alertmanager.enabled -}} 2 | {{- if .Values.ciliumNetworkPolicy.enabled -}} 3 | {{- if .Capabilities.APIVersions.Has "cilium.io/v2" -}} 4 | apiVersion: "cilium.io/v2" 5 | kind: CiliumNetworkPolicy 6 | metadata: 7 | labels: 8 | {{- include "labels.common" . | nindent 4 }} 9 | name: alertmanager 10 | namespace: {{ include "resource.default.namespace" . }} 11 | spec: 12 | endpointSelector: 13 | matchLabels: 14 | app.kubernetes.io/name: alertmanager 15 | egress: 16 | # Allow all DNS queries 17 | - toEndpoints: 18 | - matchLabels: 19 | "k8s:io.kubernetes.pod.namespace": kube-system 20 | "k8s:k8s-app": coredns 21 | - matchLabels: 22 | "k8s:io.kubernetes.pod.namespace": kube-system 23 | "k8s:k8s-app": k8s-dns-node-cache 24 | toPorts: 25 | - ports: 26 | - port: "1053" 27 | protocol: ANY 28 | - port: "53" 29 | protocol: ANY 30 | rules: 31 | dns: 32 | - matchPattern: "*" 33 | - toEntities: 34 | ## Needed to access opsgenie. 35 | - world 36 | ingress: 37 | - fromEntities: 38 | - cluster 39 | toPorts: 40 | - ports: 41 | - port: "9093" 42 | protocol: "TCP" 43 | {{ end }} 44 | {{ end }} 45 | {{- end }} 46 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/alertmanager/servicemonitor.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.alertmanager.enabled -}} 2 | apiVersion: monitoring.coreos.com/v1 3 | kind: ServiceMonitor 4 | metadata: 5 | labels: 6 | {{- include "labels.common" . | nindent 4 }} 7 | name: alertmanager 8 | namespace: {{ include "resource.default.namespace" . }} 9 | spec: 10 | endpoints: 11 | - port: web 12 | enableHttp2: true 13 | path: /metrics 14 | namespaceSelector: 15 | matchNames: 16 | - {{ include "resource.default.namespace" . }} 17 | selector: 18 | matchLabels: 19 | operated-alertmanager: "true" 20 | {{- end }} 21 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/cilium-network-policy.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ciliumNetworkPolicy.enabled -}} 2 | {{- if .Capabilities.APIVersions.Has "cilium.io/v2" -}} 3 | apiVersion: "cilium.io/v2" 4 | kind: CiliumNetworkPolicy 5 | metadata: 6 | name: {{ include "resource.default.name" . }} 7 | namespace: {{ include "resource.default.namespace" . }} 8 | labels: 9 | {{- include "labels.common" . | nindent 4 }} 10 | spec: 11 | endpointSelector: 12 | matchLabels: 13 | {{- include "labels.selector" . | nindent 6 }} 14 | egress: 15 | - toEntities: 16 | ## Needed to create anything in the MCs. 17 | - kube-apiserver 18 | ## Needed to set remote write informations. 19 | - cluster 20 | ## Needed to access opsgenie and create heartbeats. 21 | - world 22 | ingress: 23 | - fromEntities: 24 | - cluster 25 | toPorts: 26 | - ports: 27 | - port: "8000" 28 | protocol: "TCP" 29 | rules: 30 | http: 31 | - method: "GET" 32 | path: "/metrics" 33 | - method: "GET" 34 | path: "/healthz" 35 | {{ end }} 36 | {{ end }} 37 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/ingress-oauth.yaml: -------------------------------------------------------------------------------- 1 | {{- if not .Values.mimir.enabled }} 2 | apiVersion: networking.k8s.io/v1 3 | kind: Ingress 4 | metadata: 5 | annotations: 6 | kubernetes.io/tls-acme: "{{ .Values.prometheus.letsencrypt }}" 7 | {{- if .Values.prometheus.letsencrypt }} 8 | {{- with .Values.prometheus.clusterIssuerName }} 9 | cert-manager.io/cluster-issuer: "{{ . }}" 10 | {{- end }} 11 | {{- end }} 12 | {{- if .Values.ingress.externalDNS }} 13 | external-dns.alpha.kubernetes.io/hostname: {{ .Values.alertmanager.host }},{{ .Values.prometheus.host }} 14 | giantswarm.io/external-dns: managed 15 | {{- end }} 16 | labels: 17 | {{- include "labels.common" . | nindent 4 }} 18 | name: {{ include "resource.default.name" . }} 19 | namespace: {{ include "resource.default.namespace" . }} 20 | spec: 21 | ingressClassName: {{ .Values.ingress.className }} 22 | rules: 23 | - host: {{ .Values.prometheus.host }} 24 | http: 25 | paths: 26 | - backend: 27 | service: 28 | name: oauth2-proxy 29 | port: 30 | number: 4180 31 | path: /oauth2 32 | pathType: ImplementationSpecific 33 | - host: {{ .Values.alertmanager.host }} 34 | http: 35 | paths: 36 | - backend: 37 | service: 38 | name: oauth2-proxy 39 | port: 40 | number: 4180 41 | path: /oauth2 42 | pathType: ImplementationSpecific 43 | tls: 44 | - hosts: 45 | - {{ .Values.prometheus.host }} 46 | secretName: prometheus-tls 47 | - hosts: 48 | - {{ .Values.alertmanager.host }} 49 | secretName: alertmanager-tls 50 | {{- end }} 51 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/kyverno-policy-exception.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.kyvernoPolicyExceptions.enabled }} 2 | {{- if .Capabilities.APIVersions.Has "kyverno.io/v2alpha1/PolicyException" -}} 3 | apiVersion: kyverno.io/v2alpha1 4 | kind: PolicyException 5 | metadata: 6 | annotations: 7 | "helm.sh/hook": "pre-install,pre-upgrade" 8 | labels: 9 | {{- include "labels.common" . | nindent 4 }} 10 | name: {{ include "resource.default.name" . }} 11 | namespace: {{ .Values.kyvernoPolicyExceptions.namespace | default (include "resource.default.namespace" .) }} 12 | spec: 13 | exceptions: 14 | {{- if eq .Values.managementCluster.provider.flavor "vintage" }} 15 | ## Needed to access etcd certs in vintage 16 | - policyName: disallow-host-path 17 | ruleNames: 18 | - host-path 19 | - autogen-host-path 20 | - policyName: restrict-volume-types 21 | ruleNames: 22 | - restricted-volumes 23 | - autogen-restricted-volumes 24 | {{- end }} 25 | - policyName: require-run-as-non-root-user 26 | ruleNames: 27 | - run-as-non-root-user 28 | - autogen-run-as-non-root-user 29 | - policyName: require-run-as-nonroot 30 | ruleNames: 31 | - run-as-non-root 32 | - autogen-run-as-non-root 33 | - policyName: restrict-seccomp-strict 34 | ruleNames: 35 | - check-seccomp-strict 36 | - autogen-check-seccomp-strict 37 | match: 38 | any: 39 | - resources: 40 | kinds: 41 | - Deployment 42 | - ReplicaSet 43 | - Pod 44 | namespaces: 45 | - {{ include "resource.default.namespace" . }} 46 | names: 47 | - {{ include "resource.default.name" . }}* 48 | {{- end -}} 49 | {{- end -}} 50 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/pod-monitor.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 2 | kind: PodMonitor 3 | metadata: 4 | name: {{ include "resource.default.name" . }} 5 | namespace: {{ include "resource.default.namespace" . }} 6 | labels: 7 | {{- include "labels.common" . | nindent 4 }} 8 | spec: 9 | namespaceSelector: 10 | matchNames: 11 | - {{ include "resource.default.namespace" . }} 12 | selector: 13 | matchLabels: 14 | {{- include "labels.selector" . | nindent 6 }} 15 | podMetricsEndpoints: 16 | - port: http 17 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/priority-class.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: scheduling.k8s.io/v1 2 | kind: PriorityClass 3 | metadata: 4 | name: prometheus 5 | labels: 6 | {{- include "labels.common" . | nindent 4 }} 7 | value: 500000000 8 | description: "High-priority class for Prometheus service pods only." 9 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/prometheus/prometheus-psp.yaml: -------------------------------------------------------------------------------- 1 | {{- if not .Values.mimir.enabled }} 2 | {{- if not .Values.global.podSecurityStandards.enforced }} 3 | {{- if .Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy" }} 4 | apiVersion: policy/v1beta1 5 | kind: PodSecurityPolicy 6 | metadata: 7 | name: prometheus-psp 8 | labels: 9 | {{- include "labels.common" . | nindent 4 }} 10 | annotations: 11 | seccomp.security.alpha.kubernetes.io/allowedProfileNames: runtime/default 12 | spec: 13 | allowPrivilegeEscalation: false 14 | hostNetwork: false 15 | hostIPC: false 16 | hostPID: false 17 | fsGroup: 18 | ranges: 19 | - max: 65535 20 | min: 1 21 | rule: MustRunAs 22 | runAsUser: 23 | ranges: 24 | - max: 65535 25 | min: 1000 26 | rule: MustRunAs 27 | seLinux: 28 | rule: RunAsAny 29 | supplementalGroups: 30 | ranges: 31 | - max: 65535 32 | min: 1 33 | rule: MustRunAs 34 | privileged: false 35 | volumes: 36 | - 'emptyDir' 37 | - 'secret' 38 | - 'configMap' 39 | - 'persistentVolumeClaim' 40 | - 'projected' 41 | {{- end }} 42 | {{- end }} 43 | {{- end }} 44 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/prometheus/prometheus-rbac.yaml: -------------------------------------------------------------------------------- 1 | {{- if not .Values.mimir.enabled }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | {{- include "labels.common" . | nindent 4 }} 7 | name: prometheus 8 | rules: 9 | - apiGroups: 10 | - "" 11 | resources: 12 | - nodes 13 | - nodes/metrics 14 | - nodes/proxy 15 | - services 16 | - endpoints 17 | - pods 18 | - pods/proxy 19 | verbs: 20 | - get 21 | - list 22 | - watch 23 | - apiGroups: 24 | - "" 25 | resources: 26 | - configmaps 27 | verbs: 28 | - get 29 | - nonResourceURLs: 30 | - /metrics 31 | verbs: 32 | - get 33 | {{- if not .Values.global.podSecurityStandards.enforced }} 34 | {{- if .Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy" }} 35 | - apiGroups: 36 | - policy 37 | - extensions 38 | resourceNames: 39 | - prometheus-psp 40 | resources: 41 | - podsecuritypolicies 42 | verbs: 43 | - use 44 | {{- end }} 45 | {{- end }} 46 | {{- end }} 47 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/prometheus/prometheus-tls-secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if not .Values.mimir.enabled }} 2 | {{- if eq .Values.prometheus.letsencrypt false }} 3 | apiVersion: v1 4 | kind: Secret 5 | metadata: 6 | labels: 7 | {{- include "labels.common" . | nindent 4 }} 8 | name: prometheus-tls 9 | namespace: {{ include "resource.default.namespace" . }} 10 | type: kubernetes.io/tls 11 | data: 12 | tls.crt: {{ .Values.certificate.monitoring.crtPem | quote }} 13 | tls.key: {{ .Values.certificate.monitoring.keyPem | quote }} 14 | {{- end }} 15 | {{- end }} 16 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/psp.yaml: -------------------------------------------------------------------------------- 1 | {{- if not .Values.global.podSecurityStandards.enforced }} 2 | {{- if .Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy" }} 3 | apiVersion: policy/v1beta1 4 | kind: PodSecurityPolicy 5 | metadata: 6 | name: {{ include "resource.psp.name" . }} 7 | labels: 8 | {{- include "labels.common" . | nindent 4 }} 9 | spec: 10 | privileged: false 11 | fsGroup: 12 | rule: MustRunAs 13 | ranges: 14 | - min: 1 15 | max: 65535 16 | runAsUser: 17 | rule: RunAsAny 18 | runAsGroup: 19 | rule: MustRunAs 20 | ranges: 21 | - min: 1 22 | max: 65535 23 | seLinux: 24 | rule: RunAsAny 25 | supplementalGroups: 26 | rule: RunAsAny 27 | volumes: 28 | - 'secret' 29 | - 'configMap' 30 | {{- if eq .Values.managementCluster.provider.flavor "vintage" }} 31 | - 'hostPath' 32 | {{- end }} 33 | allowPrivilegeEscalation: false 34 | hostNetwork: false 35 | hostIPC: false 36 | hostPID: false 37 | {{- end }} 38 | {{- end }} 39 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/remoteWrites_crd.yaml: -------------------------------------------------------------------------------- 1 | ../../../config/crd/monitoring.giantswarm.io_remotewrites.yaml -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: {{ include "resource.default.name" . }} 5 | namespace: {{ include "resource.default.namespace" . }} 6 | labels: 7 | {{- include "labels.common" . | nindent 4 }} 8 | stringData: 9 | secret.yml: | 10 | service: 11 | opsgenie: 12 | key: {{ .Values.prometheus.heartbeat.opsgenieKey }} 13 | -------------------------------------------------------------------------------- /helm/prometheus-meta-operator/templates/service-account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: {{ include "resource.default.name" . }} 5 | namespace: {{ include "resource.default.namespace" . }} 6 | labels: 7 | {{- include "labels.common" . | nindent 4 }} 8 | -------------------------------------------------------------------------------- /pkg/cluster/types.go: -------------------------------------------------------------------------------- 1 | package cluster 2 | 3 | type Provider struct { 4 | Kind string 5 | Flavor string 6 | } 7 | 8 | const ( 9 | AWSClusterKind = "AWSCluster" 10 | AWSClusterKindProvider = "capa" 11 | 12 | AWSManagedClusterKind = "AWSManagedCluster" 13 | AWSManagedClusterKindProvider = "eks" 14 | 15 | AzureClusterKind = "AzureCluster" 16 | AzureClusterKindProvider = "capz" 17 | 18 | AzureManagedClusterKind = "AzureManagedCluster" 19 | AzureManagedClusterKindProvider = "aks" 20 | 21 | VCDClusterKind = "VCDCluster" 22 | VCDClusterKindProvider = "cloud-director" 23 | 24 | VSphereClusterKind = "VSphereCluster" 25 | VSphereClusterKindProvider = "vsphere" 26 | 27 | GCPClusterKind = "GCPCluster" 28 | GCPClusterKindProvider = "gcp" 29 | 30 | GCPManagedClusterKind = "GCPManagedCluster" 31 | GCPManagedClusterKindProvider = "gke" 32 | ) 33 | -------------------------------------------------------------------------------- /pkg/organization/reader.go: -------------------------------------------------------------------------------- 1 | package organization 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | 7 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 8 | "k8s.io/client-go/kubernetes" 9 | 10 | "github.com/giantswarm/prometheus-meta-operator/v2/pkg/cluster" 11 | "github.com/giantswarm/prometheus-meta-operator/v2/service/key" 12 | ) 13 | 14 | const ( 15 | DefaultOrganization string = "giantswarm" 16 | OrganizationLabel string = "giantswarm.io/organization" 17 | ) 18 | 19 | type Reader interface { 20 | Read(ctx context.Context, cluster metav1.Object) (string, error) 21 | } 22 | 23 | type NamespaceReader struct { 24 | client kubernetes.Interface 25 | installation string 26 | provider cluster.Provider 27 | } 28 | 29 | func NewNamespaceReader(client kubernetes.Interface, installation string, provider cluster.Provider) Reader { 30 | return NamespaceReader{client, installation, provider} 31 | } 32 | 33 | func (r NamespaceReader) Read(ctx context.Context, cluster metav1.Object) (string, error) { 34 | // Vintage MC 35 | if key.IsManagementCluster(r.installation, cluster) && !key.IsCAPIManagementCluster(r.provider) { 36 | return DefaultOrganization, nil 37 | } 38 | 39 | // For the rest, we extract the organization name from the namespace labels 40 | namespace, err := r.client.CoreV1().Namespaces().Get(ctx, cluster.GetNamespace(), metav1.GetOptions{}) 41 | if err != nil { 42 | return "", err 43 | } 44 | 45 | if organization, ok := namespace.Labels[OrganizationLabel]; ok { 46 | return organization, nil 47 | } 48 | return "", errors.New("cluster namespace missing organization label") 49 | } 50 | -------------------------------------------------------------------------------- /pkg/password/manager.go: -------------------------------------------------------------------------------- 1 | package password 2 | 3 | import ( 4 | "crypto/rand" 5 | "encoding/hex" 6 | 7 | "github.com/giantswarm/microerror" 8 | "golang.org/x/crypto/bcrypt" 9 | ) 10 | 11 | type Manager interface { 12 | GeneratePassword(length int) (string, error) 13 | Hash(password []byte) ([]byte, error) 14 | } 15 | 16 | type SimpleManager struct { 17 | } 18 | 19 | func (m SimpleManager) GeneratePassword(length int) (string, error) { 20 | bytes := make([]byte, length) 21 | if _, err := rand.Read(bytes); err != nil { 22 | return "", err 23 | } 24 | return hex.EncodeToString(bytes), nil 25 | } 26 | 27 | func (m SimpleManager) Hash(password []byte) ([]byte, error) { 28 | hash, err := bcrypt.GenerateFromPassword(password, 14) 29 | if err != nil { 30 | return nil, microerror.Mask(err) 31 | } 32 | return hash, nil 33 | } 34 | -------------------------------------------------------------------------------- /pkg/project/project.go: -------------------------------------------------------------------------------- 1 | package project 2 | 3 | var ( 4 | description = "The prometheus-meta-operator does something." 5 | gitSHA = "n/a" 6 | name = "prometheus-meta-operator" 7 | source = "https://github.com/giantswarm/prometheus-meta-operator" 8 | version = "4.88.1-dev" 9 | ) 10 | 11 | func Description() string { 12 | return description 13 | } 14 | 15 | func GitSHA() string { 16 | return gitSHA 17 | } 18 | 19 | func Name() string { 20 | return name 21 | } 22 | 23 | func Source() string { 24 | return source 25 | } 26 | 27 | func Version() string { 28 | return version 29 | } 30 | -------------------------------------------------------------------------------- /pkg/project/version_bundle.go: -------------------------------------------------------------------------------- 1 | package project 2 | 3 | import ( 4 | "github.com/giantswarm/versionbundle" 5 | ) 6 | 7 | func NewVersionBundle() versionbundle.Bundle { 8 | return versionbundle.Bundle{ 9 | Components: []versionbundle.Component{}, 10 | Name: "prometheus-meta-operator", 11 | Version: Version(), 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /pkg/prometheusquerier/querier.go: -------------------------------------------------------------------------------- 1 | package prometheusquerier 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "fmt" 7 | "net/http" 8 | "time" 9 | 10 | "github.com/prometheus/client_golang/api" 11 | v1 "github.com/prometheus/client_golang/api/prometheus/v1" 12 | "github.com/prometheus/common/model" 13 | ) 14 | 15 | // QueryInstant performs an instant query against a Prometheus server. 16 | func QueryTSDBHeadSeries(ctx context.Context, cluster string) (float64, error) { 17 | config := api.Config{ 18 | Address: fmt.Sprintf("http://prometheus-operated.%s-prometheus.svc:9090/%s", cluster, cluster), 19 | RoundTripper: http.DefaultTransport, 20 | } 21 | 22 | // Create new client. 23 | c, err := api.NewClient(config) 24 | if err != nil { 25 | return 0, err 26 | } 27 | 28 | // Run query against client. 29 | api := v1.NewAPI(c) 30 | 31 | ctx, cancel := context.WithTimeout(ctx, 2*time.Minute) 32 | val, _, err := api.Query(ctx, "max_over_time(prometheus_tsdb_head_series[6h])", time.Now()) // Ignoring warnings for now. 33 | cancel() 34 | if err != nil { 35 | return 0, err 36 | } 37 | 38 | switch val.Type() { 39 | case model.ValVector: 40 | vector := val.(model.Vector) 41 | return float64(vector[0].Value), nil 42 | default: 43 | return 0, errors.New("failed to get current number of time series") 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /pkg/pvcresizing/pvc.go: -------------------------------------------------------------------------------- 1 | package pvcresizing 2 | 3 | import ( 4 | "fmt" 5 | 6 | "k8s.io/apimachinery/pkg/api/resource" 7 | 8 | "github.com/giantswarm/prometheus-meta-operator/v2/service/key" 9 | ) 10 | 11 | const ( 12 | PrometheusStorageSizeSmall PrometheusStorageSizeType = "small" 13 | PrometheusStorageSizeMedium PrometheusStorageSizeType = "medium" 14 | PrometheusStorageSizeLarge PrometheusStorageSizeType = "large" 15 | ) 16 | 17 | type PrometheusStorageSizeType string 18 | 19 | // PrometheusVolumeSize returns the desired disk size based on the 20 | // param annotationValue: small, medium Or large 21 | func PrometheusVolumeSize(annotationValue string) string { 22 | value := PrometheusStorageSizeType(annotationValue) 23 | switch value { 24 | case PrometheusStorageSizeSmall: 25 | return "30Gi" 26 | case PrometheusStorageSizeLarge: 27 | return "200Gi" 28 | default: 29 | return "100Gi" 30 | } 31 | } 32 | 33 | // Set Retention.Size (TSDB limit) to a ratio of the volume storage size. 34 | // See Prometheus spec: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#prometheusspec 35 | // See ByteSize format: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#bytesizestring-alias 36 | func GetRetentionSize(storageSize resource.Quantity) string { 37 | storageSize.Set(int64(storageSize.AsApproximateFloat64() * key.PrometheusVolumeStorageLimitRatio)) 38 | // Trick to fit with the expected format 39 | return fmt.Sprintf("%sB", storageSize.String()) 40 | } 41 | -------------------------------------------------------------------------------- /pkg/pvcresizing/pvc_test.go: -------------------------------------------------------------------------------- 1 | package pvcresizing 2 | 3 | import ( 4 | "flag" 5 | "testing" 6 | 7 | "github.com/google/go-cmp/cmp" 8 | ) 9 | 10 | var _ = flag.Bool("update", false, "doing nothing") 11 | 12 | func TestPrometheusVolumeSize(t *testing.T) { 13 | 14 | type args struct { 15 | value string 16 | } 17 | 18 | type want struct { 19 | result string 20 | } 21 | 22 | expectedLargeValue := "200Gi" 23 | expectedMediumValue := "100Gi" 24 | expectedSmallValue := "30Gi" 25 | 26 | cases := map[string]struct { 27 | reason string 28 | args args 29 | want want 30 | }{ 31 | "VolumeSizeLarge": { 32 | reason: "Return volume size large", 33 | args: args{ 34 | value: "large", 35 | }, 36 | want: want{ 37 | result: expectedLargeValue, 38 | }, 39 | }, 40 | "VolumeSizeMedium": { 41 | reason: "Return volume size medium", 42 | args: args{ 43 | value: "medium", 44 | }, 45 | want: want{ 46 | result: expectedMediumValue, 47 | }, 48 | }, 49 | "VolumeSizeSmall": { 50 | reason: "Return volume size small", 51 | args: args{ 52 | value: "small", 53 | }, 54 | want: want{ 55 | result: expectedSmallValue, 56 | }, 57 | }, 58 | "VolumeSizeDefault": { 59 | reason: "Return volume size defaul", 60 | args: args{ 61 | value: "", 62 | }, 63 | want: want{ 64 | result: expectedMediumValue, 65 | }, 66 | }, 67 | } 68 | 69 | for n, tc := range cases { 70 | t.Run(n, func(t *testing.T) { 71 | got := PrometheusVolumeSize(tc.args.value) 72 | if diff := cmp.Diff(tc.want.result, got); diff != "" { 73 | t.Errorf("\n%s\nExpand(...): -want, +got:\n%s", tc.reason, diff) 74 | } 75 | }) 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /pkg/remotewrite/configuration/error.go: -------------------------------------------------------------------------------- 1 | package configuration 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var secretNotFound = µerror.Error{ 8 | Kind: "secretNotFound", 9 | } 10 | 11 | // IsSecretNotFound asserts secretNotFound. 12 | func IsSecretNotFound(err error) bool { 13 | return microerror.Cause(err) == secretNotFound 14 | } 15 | 16 | var remoteWriteNotFound = µerror.Error{ 17 | Kind: "remoteWriteNotFound", 18 | } 19 | 20 | // IsRemoteWriteNotFound asserts remoteWriteNotFound. 21 | func IsRemoteWriteNotFound(err error) bool { 22 | return microerror.Cause(err) == remoteWriteNotFound 23 | } 24 | -------------------------------------------------------------------------------- /pkg/remotewrite/configuration/type.go: -------------------------------------------------------------------------------- 1 | package configuration 2 | 3 | import ( 4 | promv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" 5 | ) 6 | 7 | type RemoteWriteConfig struct { 8 | // We keep this until we are sure this can be removed 9 | GlobalConfig GlobalConfig `yaml:"global,omitempty" json:"global,omitempty"` 10 | PrometheusAgentConfig PrometheusAgentConfig `yaml:"prometheus-agent,omitempty" json:"prometheus-agent,omitempty"` 11 | } 12 | 13 | type GlobalConfig struct { 14 | RemoteWrite []RemoteWrite `yaml:"remoteWrite,omitempty" json:"remoteWrite,omitempty"` 15 | ExternalLabels map[string]string `yaml:"externalLabels,omitempty" json:"externalLabels,omitempty"` 16 | } 17 | 18 | type PrometheusAgentConfig struct { 19 | RemoteWrite []RemoteWrite `yaml:"remoteWrite,omitempty" json:"remoteWrite,omitempty"` 20 | ExternalLabels map[string]string `yaml:"externalLabels,omitempty" json:"externalLabels,omitempty"` 21 | Image PrometheusAgentImage `yaml:"image,omitempty" json:"image,omitempty"` 22 | Shards int `yaml:"shards,omitempty" json:"shards,omitempty"` 23 | Version string `yaml:"version,omitempty" json:"version,omitempty"` 24 | } 25 | 26 | type PrometheusAgentImage struct { 27 | Tag string `yaml:"tag" json:"tag"` 28 | } 29 | 30 | type RemoteWrite struct { 31 | Name string `yaml:"name" json:"name"` 32 | Password string `yaml:"password" json:"password"` 33 | Username string `yaml:"username" json:"username"` 34 | URL string `yaml:"url" json:"url"` 35 | RemoteTimeout string `yaml:"remoteTimeout" json:"remoteTimeout"` 36 | QueueConfig promv1.QueueConfig `yaml:"queueConfig" json:"queueConfig"` 37 | TLSConfig promv1.TLSConfig `yaml:"tlsConfig" json:"tlsConfig"` 38 | } 39 | -------------------------------------------------------------------------------- /pkg/remotewriteutils/error.go: -------------------------------------------------------------------------------- 1 | package remotewriteutils 2 | 3 | import "github.com/giantswarm/microerror" 4 | 5 | var wrongTypeError = µerror.Error{ 6 | Kind: "wrongTypeError", 7 | } 8 | 9 | var errorFetchingPrometheus = µerror.Error{ 10 | Kind: "errorFetchingPrometheus", 11 | } 12 | -------------------------------------------------------------------------------- /pkg/template/template.go: -------------------------------------------------------------------------------- 1 | package template 2 | 3 | import ( 4 | "bytes" 5 | "html/template" 6 | "strings" 7 | 8 | "github.com/Masterminds/sprig" 9 | "github.com/giantswarm/microerror" 10 | ) 11 | 12 | // RenderTemplate render all template files matching templateLocation glob filter, using templateData. 13 | // template files are using [[ and ]] as delimiters. 14 | // There's an additional 'include' template function provided taken from helm: https://helm.sh/docs/howto/charts_tips_and_tricks/#using-the-include-function 15 | func RenderTemplate(templateData interface{}, templateLocation string) ([]byte, error) { 16 | tpl := template.New("_base").Delims("[[", "]]") 17 | 18 | // Clone the func map because we are adding context-specific functions. 19 | var funcMap template.FuncMap = map[string]interface{}{} 20 | for k, v := range sprig.FuncMap() { 21 | funcMap[k] = v 22 | } 23 | 24 | // copied from: https://github.com/helm/helm/blob/8648ccf5d35d682dcd5f7a9c2082f0aaf071e817/pkg/engine/engine.go#L147-L154 25 | funcMap["include"] = func(name string, data interface{}) (string, error) { 26 | buf := bytes.NewBuffer(nil) 27 | if err := tpl.ExecuteTemplate(buf, name, data); err != nil { 28 | return "", err 29 | } 30 | return buf.String(), nil 31 | } 32 | 33 | tpl, err := tpl.Funcs(funcMap).ParseGlob(templateLocation) 34 | if err != nil { 35 | return nil, microerror.Mask(err) 36 | } 37 | 38 | var b bytes.Buffer 39 | for _, t := range tpl.Templates() { 40 | if strings.HasPrefix(t.Name(), "_") { 41 | continue 42 | } 43 | err := t.Delims("[[", "]]").Execute(&b, templateData) 44 | if err != nil { 45 | return nil, microerror.Mask(err) 46 | } 47 | } 48 | return b.Bytes(), nil 49 | } 50 | -------------------------------------------------------------------------------- /pkg/unittest/error.go: -------------------------------------------------------------------------------- 1 | package unittest 2 | 3 | import ( 4 | "reflect" 5 | 6 | "github.com/giantswarm/microerror" 7 | "github.com/google/go-cmp/cmp" 8 | ) 9 | 10 | var executionError = µerror.Error{ 11 | Kind: "executionError", 12 | } 13 | 14 | // IsExecution asserts executionError. 15 | func IsExecution(err error) bool { 16 | return microerror.Cause(err) == executionError 17 | } 18 | 19 | // EquateErrors returns true if the supplied errors are of the same type and 20 | // produce identical strings. This mirrors the error comparison behaviour of 21 | // https://github.com/go-test/deep, 22 | // 23 | // This differs from cmpopts.EquateErrors, which does not test for error strings 24 | // and instead returns whether one error 'is' (in the errors.Is sense) the 25 | // other. 26 | func EquateErrors() cmp.Option { 27 | return cmp.Comparer(func(a, b error) bool { 28 | if a == nil || b == nil { 29 | return a == nil && b == nil 30 | } 31 | 32 | av := reflect.ValueOf(a) 33 | bv := reflect.ValueOf(b) 34 | if av.Type() != bv.Type() { 35 | return false 36 | } 37 | 38 | return a.Error() == b.Error() 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /pkg/unittest/input/capi/case-1-capa-mc.golden: -------------------------------------------------------------------------------- 1 | apiVersion: cluster.x-k8s.io/v1beta1 2 | kind: Cluster 3 | metadata: 4 | name: test-installation 5 | namespace: org-my-organization 6 | spec: 7 | controlPlaneEndpoint: 8 | host: master.test-installation 9 | port: 443 10 | infrastructureRef: 11 | kind: AWSCluster 12 | -------------------------------------------------------------------------------- /pkg/unittest/input/capi/case-2-capa.golden: -------------------------------------------------------------------------------- 1 | apiVersion: cluster.x-k8s.io/v1beta1 2 | kind: Cluster 3 | metadata: 4 | name: baz 5 | namespace: org-my-organization 6 | spec: 7 | controlPlaneEndpoint: 8 | host: master.baz 9 | port: 443 10 | infrastructureRef: 11 | kind: AWSCluster 12 | -------------------------------------------------------------------------------- /pkg/unittest/input/capi/case-3-capz.golden: -------------------------------------------------------------------------------- 1 | apiVersion: cluster.x-k8s.io/v1beta1 2 | kind: Cluster 3 | metadata: 4 | name: foo 5 | namespace: org-my-organization 6 | spec: 7 | controlPlaneEndpoint: 8 | host: master.foo 9 | port: 443 10 | infrastructureRef: 11 | kind: AzureCluster 12 | -------------------------------------------------------------------------------- /pkg/unittest/input/capi/case-4-eks.golden: -------------------------------------------------------------------------------- 1 | apiVersion: cluster.x-k8s.io/v1beta1 2 | kind: Cluster 3 | metadata: 4 | name: eks-sample 5 | namespace: org-my-organization 6 | spec: 7 | controlPlaneEndpoint: 8 | host: master.eks-sample 9 | port: 443 10 | infrastructureRef: 11 | kind: AWSManagedCluster 12 | -------------------------------------------------------------------------------- /pkg/unittest/input/capi/case-5-gcp.golden: -------------------------------------------------------------------------------- 1 | apiVersion: cluster.x-k8s.io/v1beta1 2 | kind: Cluster 3 | metadata: 4 | name: gcp-sample 5 | namespace: org-my-organization 6 | spec: 7 | controlPlaneEndpoint: 8 | host: master.gcp-sample 9 | port: 443 10 | infrastructureRef: 11 | kind: GCPCluster 12 | -------------------------------------------------------------------------------- /pkg/unittest/input/vintage/case-1-vintage-mc.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: kubernetes 5 | namespace: default 6 | spec: 7 | clusterIP: 127.0.0.1 8 | -------------------------------------------------------------------------------- /pkg/unittest/input/vintage/case-2-aws-v16.golden: -------------------------------------------------------------------------------- 1 | apiVersion: cluster.x-k8s.io/v1beta1 2 | kind: Cluster 3 | metadata: 4 | labels: 5 | "release.giantswarm.io/version": 16.0.0 6 | name: alice 7 | namespace: org-my-organization 8 | spec: 9 | controlPlaneEndpoint: 10 | host: master.alice 11 | port: 443 12 | infrastructureRef: 13 | kind: AWSCluster 14 | -------------------------------------------------------------------------------- /pkg/unittest/input/vintage/case-3-aws-v18.golden: -------------------------------------------------------------------------------- 1 | apiVersion: cluster.x-k8s.io/v1beta1 2 | kind: Cluster 3 | metadata: 4 | labels: 5 | "release.giantswarm.io/version": 18.0.0 6 | name: baz 7 | namespace: org-my-organization 8 | spec: 9 | controlPlaneEndpoint: 10 | host: master.baz 11 | port: 443 12 | infrastructureRef: 13 | kind: AWSCluster 14 | -------------------------------------------------------------------------------- /renovate.json5: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | // Base config - https://github.com/giantswarm/renovate-presets/blob/main/default.json5 4 | "github>giantswarm/renovate-presets:default.json5", 5 | // Go specific config - https://github.com/giantswarm/renovate-presets/blob/main/lang-go.json5 6 | "github>giantswarm/renovate-presets:lang-go.json5", 7 | ], 8 | } 9 | -------------------------------------------------------------------------------- /server/endpoint/endpoint.go: -------------------------------------------------------------------------------- 1 | package endpoint 2 | 3 | import ( 4 | "github.com/giantswarm/microendpoint/endpoint/healthz" 5 | "github.com/giantswarm/microendpoint/endpoint/version" 6 | "github.com/giantswarm/microerror" 7 | "github.com/giantswarm/micrologger" 8 | 9 | "github.com/giantswarm/prometheus-meta-operator/v2/service" 10 | ) 11 | 12 | type Config struct { 13 | Logger micrologger.Logger 14 | Service *service.Service 15 | } 16 | 17 | type Endpoint struct { 18 | Healthz *healthz.Endpoint 19 | Version *version.Endpoint 20 | } 21 | 22 | func New(config Config) (*Endpoint, error) { 23 | var err error 24 | 25 | var healthzEndpoint *healthz.Endpoint 26 | { 27 | c := healthz.Config{ 28 | Logger: config.Logger, 29 | } 30 | 31 | healthzEndpoint, err = healthz.New(c) 32 | if err != nil { 33 | return nil, microerror.Mask(err) 34 | } 35 | } 36 | 37 | var versionEndpoint *version.Endpoint 38 | { 39 | c := version.Config{ 40 | Logger: config.Logger, 41 | Service: config.Service.Version, 42 | } 43 | 44 | versionEndpoint, err = version.New(c) 45 | if err != nil { 46 | return nil, microerror.Mask(err) 47 | } 48 | } 49 | 50 | e := &Endpoint{ 51 | Healthz: healthzEndpoint, 52 | Version: versionEndpoint, 53 | } 54 | 55 | return e, nil 56 | } 57 | -------------------------------------------------------------------------------- /server/endpoint/error.go: -------------------------------------------------------------------------------- 1 | package endpoint 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var invalidConfigError = µerror.Error{ 8 | Kind: "invalidConfigError", 9 | } 10 | 11 | // IsInvalidConfig asserts invalidConfigError. 12 | func IsInvalidConfig(err error) bool { 13 | return microerror.Cause(err) == invalidConfigError 14 | } 15 | -------------------------------------------------------------------------------- /server/error.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var invalidConfigError = µerror.Error{ 8 | Kind: "invalidConfigError", 9 | } 10 | 11 | // IsInvalidConfig asserts invalidConfigError. 12 | func IsInvalidConfig(err error) bool { 13 | return microerror.Cause(err) == invalidConfigError 14 | } 15 | -------------------------------------------------------------------------------- /service/controller/clusterapi/error.go: -------------------------------------------------------------------------------- 1 | package clusterapi 2 | 3 | import "github.com/giantswarm/microerror" 4 | 5 | var unsupportedStorageVersionError = µerror.Error{ 6 | Kind: "unsupportedStorageVersionError", 7 | } 8 | 9 | // IsUnsupportedStorageVersion asserts unsupportedStorageVersionError. 10 | func IsUnsupportedStorageVersion(err error) bool { 11 | return microerror.Cause(err) == unsupportedStorageVersionError 12 | } 13 | -------------------------------------------------------------------------------- /service/controller/managementcluster/error.go: -------------------------------------------------------------------------------- 1 | package managementcluster 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var invalidConfigError = µerror.Error{ 8 | Kind: "invalidConfigError", 9 | } 10 | 11 | // IsInvalidConfig asserts invalidConfigError. 12 | func IsInvalidConfig(err error) bool { 13 | return microerror.Cause(err) == invalidConfigError 14 | } 15 | -------------------------------------------------------------------------------- /service/controller/remotewrite/controller.go: -------------------------------------------------------------------------------- 1 | package remotewrite 2 | 3 | import ( 4 | "net/url" 5 | 6 | "github.com/giantswarm/k8sclient/v7/pkg/k8sclient" 7 | "github.com/giantswarm/microerror" 8 | "github.com/giantswarm/micrologger" 9 | "github.com/giantswarm/operatorkit/v7/pkg/controller" 10 | "github.com/giantswarm/operatorkit/v7/pkg/resource" 11 | promclient "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned" 12 | 13 | "sigs.k8s.io/controller-runtime/pkg/client" 14 | 15 | pmov1alpha1 "github.com/giantswarm/prometheus-meta-operator/v2/api/v1alpha1" 16 | "github.com/giantswarm/prometheus-meta-operator/v2/pkg/project" 17 | ) 18 | 19 | type ControllerConfig struct { 20 | K8sClient k8sclient.Interface 21 | Logger micrologger.Logger 22 | PrometheusClient promclient.Interface 23 | Proxy func(reqURL *url.URL) (*url.URL, error) 24 | } 25 | 26 | type Controller struct { 27 | *controller.Controller 28 | } 29 | 30 | func NewController(config ControllerConfig) (*Controller, error) { 31 | var err error 32 | 33 | var resources []resource.Interface 34 | { 35 | resources, err = newResources(config) 36 | if err != nil { 37 | return nil, microerror.Mask(err) 38 | } 39 | } 40 | var operatorkitController *controller.Controller 41 | { 42 | c := controller.Config{ 43 | K8sClient: config.K8sClient, 44 | Logger: config.Logger, 45 | Name: project.Name() + "-remote-write-controller", 46 | NewRuntimeObjectFunc: func() client.Object { 47 | return new(pmov1alpha1.RemoteWrite) 48 | }, 49 | Resources: resources, 50 | } 51 | 52 | operatorkitController, err = controller.New(c) 53 | if err != nil { 54 | return nil, microerror.Mask(err) 55 | } 56 | } 57 | 58 | c := &Controller{ 59 | Controller: operatorkitController, 60 | } 61 | 62 | return c, nil 63 | } 64 | -------------------------------------------------------------------------------- /service/controller/remotewrite/error.go: -------------------------------------------------------------------------------- 1 | package remotewrite 2 | -------------------------------------------------------------------------------- /service/controller/remotewrite/resource.go: -------------------------------------------------------------------------------- 1 | package remotewrite 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | "github.com/giantswarm/operatorkit/v7/pkg/resource" 6 | 7 | "github.com/giantswarm/prometheus-meta-operator/v2/service/controller/resource/prometheusremotewrite" 8 | "github.com/giantswarm/prometheus-meta-operator/v2/service/controller/resource/remotewritesecret" 9 | ) 10 | 11 | func newResources(config ControllerConfig) ([]resource.Interface, error) { 12 | var err error 13 | 14 | var prometheusRemoteWrite resource.Interface 15 | { 16 | c := prometheusremotewrite.Config{ 17 | K8sClient: config.K8sClient, 18 | Logger: config.Logger, 19 | PrometheusClient: config.PrometheusClient, 20 | 21 | Proxy: config.Proxy, 22 | } 23 | 24 | prometheusRemoteWrite, err = prometheusremotewrite.New(c) 25 | if err != nil { 26 | return nil, microerror.Mask(err) 27 | } 28 | } 29 | 30 | var rwSecretResource resource.Interface 31 | { 32 | c := remotewritesecret.Config{ 33 | K8sClient: config.K8sClient, 34 | Logger: config.Logger, 35 | PrometheusClient: config.PrometheusClient, 36 | } 37 | 38 | rwSecretResource, err = remotewritesecret.New(c) 39 | if err != nil { 40 | return nil, microerror.Mask(err) 41 | } 42 | } 43 | 44 | resources := []resource.Interface{ 45 | rwSecretResource, 46 | prometheusRemoteWrite, 47 | } 48 | 49 | return resources, nil 50 | } 51 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/alertmanagerconfig/create.go: -------------------------------------------------------------------------------- 1 | package alertmanagerconfig 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | 10 | "github.com/giantswarm/prometheus-meta-operator/v2/service/controller/resource/resourceutils" 11 | ) 12 | 13 | func (r *Resource) EnsureCreated(ctx context.Context, obj interface{}) error { 14 | if !r.config.AlertmanagerEnabled { 15 | r.config.Logger.Debugf(ctx, "alertmanager is disabled, deleting alertmanager config if it exists") 16 | return r.EnsureDeleted(ctx, obj) 17 | } 18 | desired, err := r.toSecret() 19 | if err != nil { 20 | return microerror.Mask(err) 21 | } 22 | 23 | r.config.Logger.Debugf(ctx, "creating") 24 | current, err := r.config.K8sClient.K8sClient().CoreV1().Secrets(desired.GetNamespace()).Get(ctx, desired.GetName(), metav1.GetOptions{}) 25 | if apierrors.IsNotFound(err) { 26 | current, err = r.config.K8sClient.K8sClient().CoreV1().Secrets(desired.GetNamespace()).Create(ctx, desired, metav1.CreateOptions{}) 27 | } 28 | 29 | if err != nil { 30 | return microerror.Mask(err) 31 | } 32 | 33 | if r.hasChanged(current, desired) { 34 | resourceutils.UpdateMeta(current, desired) 35 | _, err = r.config.K8sClient.K8sClient().CoreV1().Secrets(desired.GetNamespace()).Update(ctx, desired, metav1.UpdateOptions{}) 36 | if err != nil { 37 | return microerror.Mask(err) 38 | } 39 | } 40 | r.config.Logger.Debugf(ctx, "created") 41 | 42 | return nil 43 | } 44 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/alertmanagerconfig/delete.go: -------------------------------------------------------------------------------- 1 | package alertmanagerconfig 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | ) 10 | 11 | func (r *Resource) EnsureDeleted(ctx context.Context, obj interface{}) error { 12 | object := getObjectMeta() 13 | 14 | r.config.Logger.Debugf(ctx, "deleting") 15 | err := r.config.K8sClient.K8sClient().CoreV1().Secrets(object.GetNamespace()).Delete(ctx, object.GetName(), metav1.DeleteOptions{}) 16 | if apierrors.IsNotFound(err) { 17 | // fall through 18 | } else if err != nil { 19 | return microerror.Mask(err) 20 | } 21 | r.config.Logger.Debugf(ctx, "deleted") 22 | 23 | return nil 24 | } 25 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/alertmanagerconfig/error.go: -------------------------------------------------------------------------------- 1 | package alertmanagerconfig 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var wrongTypeError = µerror.Error{ 8 | Kind: "wrongTypeError", 9 | } 10 | 11 | // IsWrongType asserts wrongTypeError. 12 | func IsWrongType(err error) bool { 13 | return microerror.Cause(err) == wrongTypeError 14 | } 15 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/alertmanagerwiring/client.go: -------------------------------------------------------------------------------- 1 | package alertmanagerwiring 2 | 3 | import ( 4 | "context" 5 | 6 | corev1 "k8s.io/api/core/v1" 7 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 8 | v1 "k8s.io/client-go/kubernetes/typed/core/v1" 9 | ) 10 | 11 | type wrappedClient struct { 12 | client v1.SecretInterface 13 | } 14 | 15 | func (c wrappedClient) Create(ctx context.Context, o metav1.Object, options metav1.CreateOptions) (metav1.Object, error) { 16 | return c.client.Create(ctx, o.(*corev1.Secret), options) 17 | } 18 | 19 | func (c wrappedClient) Update(ctx context.Context, o metav1.Object, options metav1.UpdateOptions) (metav1.Object, error) { 20 | return c.client.Update(ctx, o.(*corev1.Secret), options) 21 | } 22 | 23 | func (c wrappedClient) Get(ctx context.Context, name string, options metav1.GetOptions) (metav1.Object, error) { 24 | return c.client.Get(ctx, name, options) 25 | } 26 | 27 | func (c wrappedClient) Delete(ctx context.Context, name string, options *metav1.DeleteOptions) error { 28 | return c.client.Delete(ctx, name, *options) 29 | } 30 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/alertmanagerwiring/error.go: -------------------------------------------------------------------------------- 1 | package alertmanagerwiring 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var invalidConfigError = µerror.Error{ 8 | Kind: "invalidConfigError", 9 | } 10 | 11 | // IsInvalidConfig asserts invalidConfigError. 12 | func IsInvalidConfig(err error) bool { 13 | return microerror.Cause(err) == invalidConfigError 14 | } 15 | 16 | var wrongTypeError = µerror.Error{ 17 | Kind: "wrongTypeError", 18 | } 19 | 20 | // IsWrongType asserts wrongTypeError. 21 | func IsWrongType(err error) bool { 22 | return microerror.Cause(err) == wrongTypeError 23 | } 24 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/alertmanagerwiring/resource_test.go: -------------------------------------------------------------------------------- 1 | package alertmanagerwiring 2 | 3 | import ( 4 | "flag" 5 | "path/filepath" 6 | "testing" 7 | 8 | "github.com/giantswarm/prometheus-meta-operator/v2/pkg/unittest" 9 | ) 10 | 11 | var update = flag.Bool("update", false, "update the output file") 12 | 13 | func TestAlertmanagerconfig(t *testing.T) { 14 | for _, flavor := range unittest.ProviderFlavors { 15 | outputDir, err := filepath.Abs("./test/" + flavor) 16 | 17 | if err != nil { 18 | t.Fatal(err) 19 | } 20 | 21 | c := unittest.Config{ 22 | Flavor: flavor, 23 | OutputDir: outputDir, 24 | T: t, 25 | TestFunc: func(v interface{}) (interface{}, error) { 26 | return toData(), nil 27 | }, 28 | TestFuncReturnsBytes: true, 29 | Update: *update, 30 | } 31 | runner, err := unittest.NewRunner(c) 32 | if err != nil { 33 | t.Fatal(err) 34 | } 35 | 36 | err = runner.Run() 37 | if err != nil { 38 | t.Fatal(err) 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/alertmanagerwiring/test/capi/case-1-capa-mc.golden: -------------------------------------------------------------------------------- 1 | - static_configs: 2 | - targets: 3 | - alertmanager-operated.monitoring.svc:9093 4 | scheme: http 5 | timeout: 10s 6 | api_version: v2 7 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/alertmanagerwiring/test/capi/case-2-capa.golden: -------------------------------------------------------------------------------- 1 | - static_configs: 2 | - targets: 3 | - alertmanager-operated.monitoring.svc:9093 4 | scheme: http 5 | timeout: 10s 6 | api_version: v2 7 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/alertmanagerwiring/test/capi/case-3-capz.golden: -------------------------------------------------------------------------------- 1 | - static_configs: 2 | - targets: 3 | - alertmanager-operated.monitoring.svc:9093 4 | scheme: http 5 | timeout: 10s 6 | api_version: v2 7 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/alertmanagerwiring/test/capi/case-4-eks.golden: -------------------------------------------------------------------------------- 1 | - static_configs: 2 | - targets: 3 | - alertmanager-operated.monitoring.svc:9093 4 | scheme: http 5 | timeout: 10s 6 | api_version: v2 7 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/alertmanagerwiring/test/capi/case-5-gcp.golden: -------------------------------------------------------------------------------- 1 | - static_configs: 2 | - targets: 3 | - alertmanager-operated.monitoring.svc:9093 4 | scheme: http 5 | timeout: 10s 6 | api_version: v2 7 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/alertmanagerwiring/test/vintage/case-1-vintage-mc.golden: -------------------------------------------------------------------------------- 1 | - static_configs: 2 | - targets: 3 | - alertmanager-operated.monitoring.svc:9093 4 | scheme: http 5 | timeout: 10s 6 | api_version: v2 7 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/alertmanagerwiring/test/vintage/case-2-aws-v16.golden: -------------------------------------------------------------------------------- 1 | - static_configs: 2 | - targets: 3 | - alertmanager-operated.monitoring.svc:9093 4 | scheme: http 5 | timeout: 10s 6 | api_version: v2 7 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/alertmanagerwiring/test/vintage/case-3-aws-v18.golden: -------------------------------------------------------------------------------- 1 | - static_configs: 2 | - targets: 3 | - alertmanager-operated.monitoring.svc:9093 4 | scheme: http 5 | timeout: 10s 6 | api_version: v2 7 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/heartbeat/delete.go: -------------------------------------------------------------------------------- 1 | package heartbeat 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | ) 8 | 9 | func (r *Resource) EnsureDeleted(ctx context.Context, obj interface{}) error { 10 | desired, err := toHeartbeat(obj, r.installation, r.pipeline) 11 | if err != nil { 12 | return microerror.Mask(err) 13 | } 14 | 15 | r.logger.Debugf(ctx, "checking if heartbeat exists") 16 | _, err = r.heartbeatClient.Get(ctx, desired.Name) 17 | if IsApiNotFoundError(err) { 18 | r.logger.Debugf(ctx, "heartbeat does not exist") 19 | } else if err != nil { 20 | return microerror.Mask(err) 21 | } else { 22 | r.logger.Debugf(ctx, "triggering final heartbeat ping") 23 | // The final ping to the heartbeat cleans up any opened heartbeat alerts for the cluster being deleted. 24 | _, err = r.heartbeatClient.Ping(ctx, desired.Name) 25 | if err != nil { 26 | return microerror.Mask(err) 27 | } 28 | r.logger.Debugf(ctx, "triggered final heartbeat ping") 29 | 30 | r.logger.Debugf(ctx, "deleting heartbeat") 31 | _, err = r.heartbeatClient.Delete(ctx, desired.Name) 32 | if err != nil { 33 | return microerror.Mask(err) 34 | } 35 | 36 | r.logger.Debugf(ctx, "deleted heartbeat") 37 | } 38 | 39 | return nil 40 | } 41 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/heartbeat/error.go: -------------------------------------------------------------------------------- 1 | package heartbeat 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/giantswarm/microerror" 7 | "github.com/opsgenie/opsgenie-go-sdk-v2/client" 8 | ) 9 | 10 | var invalidConfigError = µerror.Error{ 11 | Kind: "invalidConfigError", 12 | } 13 | 14 | // IsInvalidConfig asserts invalidConfigError. 15 | func IsInvalidConfig(err error) bool { 16 | return microerror.Cause(err) == invalidConfigError 17 | } 18 | 19 | var wrongTypeError = µerror.Error{ 20 | Kind: "wrongTypeError", 21 | } 22 | 23 | // IsWrongType asserts wrongTypeError. 24 | func IsWrongType(err error) bool { 25 | return microerror.Cause(err) == wrongTypeError 26 | } 27 | 28 | var apiNotFoundError = µerror.Error{ 29 | Kind: "apiNotFoundError", 30 | } 31 | 32 | func IsApiNotFoundError(err error) bool { 33 | if microerror.Cause(err) == apiNotFoundError { 34 | return true 35 | } 36 | 37 | apiErr, ok := err.(*client.ApiError) 38 | return ok && apiErr.StatusCode == http.StatusNotFound 39 | } 40 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/heartbeatwebhookconfig/create.go: -------------------------------------------------------------------------------- 1 | package heartbeatwebhookconfig 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | 10 | "github.com/giantswarm/prometheus-meta-operator/v2/service/controller/resource/resourceutils" 11 | ) 12 | 13 | func (r *Resource) EnsureCreated(ctx context.Context, obj interface{}) error { 14 | if r.mimirEnabled { 15 | return r.EnsureDeleted(ctx, obj) 16 | } 17 | 18 | desired, err := r.toAlertmanagerConfig(obj) 19 | if err != nil { 20 | return microerror.Mask(err) 21 | } 22 | 23 | r.logger.Debugf(ctx, "creating") 24 | current, err := r.client.MonitoringV1alpha1().AlertmanagerConfigs(desired.GetNamespace()).Get(ctx, desired.GetName(), metav1.GetOptions{}) 25 | if apierrors.IsNotFound(err) { 26 | current, err = r.client.MonitoringV1alpha1().AlertmanagerConfigs(desired.GetNamespace()).Create(ctx, desired, metav1.CreateOptions{}) 27 | } 28 | 29 | if err != nil { 30 | return microerror.Mask(err) 31 | } 32 | 33 | if r.hasChanged(current, desired) { 34 | resourceutils.UpdateMeta(current, desired) 35 | _, err = r.client.MonitoringV1alpha1().AlertmanagerConfigs(desired.GetNamespace()).Update(ctx, desired, metav1.UpdateOptions{}) 36 | if err != nil { 37 | return microerror.Mask(err) 38 | } 39 | } 40 | r.logger.Debugf(ctx, "created") 41 | 42 | return nil 43 | } 44 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/heartbeatwebhookconfig/delete.go: -------------------------------------------------------------------------------- 1 | package heartbeatwebhookconfig 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | ) 10 | 11 | func (r *Resource) EnsureDeleted(ctx context.Context, obj interface{}) error { 12 | object, err := r.getObjectMeta(obj) 13 | if err != nil { 14 | return microerror.Mask(err) 15 | } 16 | 17 | r.logger.Debugf(ctx, "deleting") 18 | err = r.client.MonitoringV1alpha1().AlertmanagerConfigs(object.GetNamespace()).Delete(ctx, object.GetName(), metav1.DeleteOptions{}) 19 | if apierrors.IsNotFound(err) { 20 | // fall through 21 | } else if err != nil { 22 | return microerror.Mask(err) 23 | } 24 | r.logger.Debugf(ctx, "deleted") 25 | 26 | return nil 27 | } 28 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/heartbeatwebhookconfig/error.go: -------------------------------------------------------------------------------- 1 | package heartbeatwebhookconfig 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var invalidConfigError = µerror.Error{ 8 | Kind: "invalidConfigError", 9 | } 10 | 11 | // IsInvalidConfig asserts invalidConfigError. 12 | func IsInvalidConfig(err error) bool { 13 | return microerror.Cause(err) == invalidConfigError 14 | } 15 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/heartbeatwebhookconfig/resource_test.go: -------------------------------------------------------------------------------- 1 | package heartbeatwebhookconfig 2 | 3 | import ( 4 | "flag" 5 | "path/filepath" 6 | "testing" 7 | 8 | "github.com/giantswarm/micrologger" 9 | "golang.org/x/net/http/httpproxy" 10 | 11 | "github.com/giantswarm/prometheus-meta-operator/v2/pkg/unittest" 12 | ) 13 | 14 | var update = flag.Bool("update", false, "update the output file") 15 | 16 | func TestAlertmanagerConfig(t *testing.T) { 17 | var err error 18 | var logger micrologger.Logger 19 | { 20 | c := micrologger.Config{} 21 | 22 | logger, err = micrologger.New(c) 23 | if err != nil { 24 | t.Fatal(err) 25 | } 26 | } 27 | 28 | proxyConfig := httpproxy.Config{} 29 | config := Config{ 30 | Proxy: proxyConfig.ProxyFunc(), 31 | Logger: logger, 32 | Installation: "test-installation", 33 | } 34 | 35 | resource, err := New(config) 36 | if err != nil { 37 | t.Fatal(err) 38 | } 39 | 40 | for _, flavor := range unittest.ProviderFlavors { 41 | outputDir, err := filepath.Abs("./test/" + flavor) 42 | if err != nil { 43 | t.Fatal(err) 44 | } 45 | c := unittest.Config{ 46 | OutputDir: outputDir, 47 | Flavor: flavor, 48 | T: t, 49 | TestFunc: func(v interface{}) (interface{}, error) { 50 | return resource.toAlertmanagerConfig(v) 51 | }, 52 | Update: *update, 53 | } 54 | runner, err := unittest.NewRunner(c) 55 | if err != nil { 56 | t.Fatal(err) 57 | } 58 | 59 | err = runner.Run() 60 | if err != nil { 61 | t.Fatal(err) 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/heartbeatwebhookconfig/test/capi/case-1-capa-mc.golden: -------------------------------------------------------------------------------- 1 | metadata: 2 | creationTimestamp: null 3 | labels: 4 | app.kubernetes.io/instance: alertmanager 5 | app.kubernetes.io/managed-by: prometheus-meta-operator 6 | app.kubernetes.io/name: alertmanager 7 | name: test-installation 8 | namespace: monitoring 9 | spec: 10 | receivers: 11 | - name: heartbeat_test-installation_test-installation 12 | webhookConfigs: 13 | - httpConfig: 14 | authorization: 15 | credentials: 16 | key: opsGenieApiKey 17 | name: alertmanager-global 18 | type: GenieKey 19 | sendResolved: false 20 | url: https://api.opsgenie.com/v2/heartbeats/test-installation-test-installation/ping 21 | route: 22 | groupInterval: 30s 23 | groupWait: 30s 24 | matchers: 25 | - name: cluster_id 26 | value: test-installation 27 | - name: installation 28 | value: test-installation 29 | - name: type 30 | value: heartbeat 31 | receiver: heartbeat_test-installation_test-installation 32 | repeatInterval: 15m 33 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/heartbeatwebhookconfig/test/capi/case-2-capa.golden: -------------------------------------------------------------------------------- 1 | metadata: 2 | creationTimestamp: null 3 | labels: 4 | app.kubernetes.io/instance: alertmanager 5 | app.kubernetes.io/managed-by: prometheus-meta-operator 6 | app.kubernetes.io/name: alertmanager 7 | name: baz 8 | namespace: monitoring 9 | spec: 10 | receivers: 11 | - name: heartbeat_test-installation_baz 12 | webhookConfigs: 13 | - httpConfig: 14 | authorization: 15 | credentials: 16 | key: opsGenieApiKey 17 | name: alertmanager-global 18 | type: GenieKey 19 | sendResolved: false 20 | url: https://api.opsgenie.com/v2/heartbeats/test-installation-baz/ping 21 | route: 22 | groupInterval: 30s 23 | groupWait: 30s 24 | matchers: 25 | - name: cluster_id 26 | value: baz 27 | - name: installation 28 | value: test-installation 29 | - name: type 30 | value: heartbeat 31 | receiver: heartbeat_test-installation_baz 32 | repeatInterval: 15m 33 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/heartbeatwebhookconfig/test/capi/case-3-capz.golden: -------------------------------------------------------------------------------- 1 | metadata: 2 | creationTimestamp: null 3 | labels: 4 | app.kubernetes.io/instance: alertmanager 5 | app.kubernetes.io/managed-by: prometheus-meta-operator 6 | app.kubernetes.io/name: alertmanager 7 | name: foo 8 | namespace: monitoring 9 | spec: 10 | receivers: 11 | - name: heartbeat_test-installation_foo 12 | webhookConfigs: 13 | - httpConfig: 14 | authorization: 15 | credentials: 16 | key: opsGenieApiKey 17 | name: alertmanager-global 18 | type: GenieKey 19 | sendResolved: false 20 | url: https://api.opsgenie.com/v2/heartbeats/test-installation-foo/ping 21 | route: 22 | groupInterval: 30s 23 | groupWait: 30s 24 | matchers: 25 | - name: cluster_id 26 | value: foo 27 | - name: installation 28 | value: test-installation 29 | - name: type 30 | value: heartbeat 31 | receiver: heartbeat_test-installation_foo 32 | repeatInterval: 15m 33 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/heartbeatwebhookconfig/test/capi/case-4-eks.golden: -------------------------------------------------------------------------------- 1 | metadata: 2 | creationTimestamp: null 3 | labels: 4 | app.kubernetes.io/instance: alertmanager 5 | app.kubernetes.io/managed-by: prometheus-meta-operator 6 | app.kubernetes.io/name: alertmanager 7 | name: eks-sample 8 | namespace: monitoring 9 | spec: 10 | receivers: 11 | - name: heartbeat_test-installation_eks-sample 12 | webhookConfigs: 13 | - httpConfig: 14 | authorization: 15 | credentials: 16 | key: opsGenieApiKey 17 | name: alertmanager-global 18 | type: GenieKey 19 | sendResolved: false 20 | url: https://api.opsgenie.com/v2/heartbeats/test-installation-eks-sample/ping 21 | route: 22 | groupInterval: 30s 23 | groupWait: 30s 24 | matchers: 25 | - name: cluster_id 26 | value: eks-sample 27 | - name: installation 28 | value: test-installation 29 | - name: type 30 | value: heartbeat 31 | receiver: heartbeat_test-installation_eks-sample 32 | repeatInterval: 15m 33 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/heartbeatwebhookconfig/test/capi/case-5-gcp.golden: -------------------------------------------------------------------------------- 1 | metadata: 2 | creationTimestamp: null 3 | labels: 4 | app.kubernetes.io/instance: alertmanager 5 | app.kubernetes.io/managed-by: prometheus-meta-operator 6 | app.kubernetes.io/name: alertmanager 7 | name: gcp-sample 8 | namespace: monitoring 9 | spec: 10 | receivers: 11 | - name: heartbeat_test-installation_gcp-sample 12 | webhookConfigs: 13 | - httpConfig: 14 | authorization: 15 | credentials: 16 | key: opsGenieApiKey 17 | name: alertmanager-global 18 | type: GenieKey 19 | sendResolved: false 20 | url: https://api.opsgenie.com/v2/heartbeats/test-installation-gcp-sample/ping 21 | route: 22 | groupInterval: 30s 23 | groupWait: 30s 24 | matchers: 25 | - name: cluster_id 26 | value: gcp-sample 27 | - name: installation 28 | value: test-installation 29 | - name: type 30 | value: heartbeat 31 | receiver: heartbeat_test-installation_gcp-sample 32 | repeatInterval: 15m 33 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/heartbeatwebhookconfig/test/vintage/case-1-vintage-mc.golden: -------------------------------------------------------------------------------- 1 | metadata: 2 | creationTimestamp: null 3 | labels: 4 | app.kubernetes.io/instance: alertmanager 5 | app.kubernetes.io/managed-by: prometheus-meta-operator 6 | app.kubernetes.io/name: alertmanager 7 | name: kubernetes 8 | namespace: monitoring 9 | spec: 10 | receivers: 11 | - name: heartbeat_test-installation_kubernetes 12 | webhookConfigs: 13 | - httpConfig: 14 | authorization: 15 | credentials: 16 | key: opsGenieApiKey 17 | name: alertmanager-global 18 | type: GenieKey 19 | sendResolved: false 20 | url: https://api.opsgenie.com/v2/heartbeats/test-installation-kubernetes/ping 21 | route: 22 | groupInterval: 30s 23 | groupWait: 30s 24 | matchers: 25 | - name: cluster_id 26 | value: kubernetes 27 | - name: installation 28 | value: test-installation 29 | - name: type 30 | value: heartbeat 31 | receiver: heartbeat_test-installation_kubernetes 32 | repeatInterval: 15m 33 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/heartbeatwebhookconfig/test/vintage/case-2-aws-v16.golden: -------------------------------------------------------------------------------- 1 | metadata: 2 | creationTimestamp: null 3 | labels: 4 | app.kubernetes.io/instance: alertmanager 5 | app.kubernetes.io/managed-by: prometheus-meta-operator 6 | app.kubernetes.io/name: alertmanager 7 | name: alice 8 | namespace: monitoring 9 | spec: 10 | receivers: 11 | - name: heartbeat_test-installation_alice 12 | webhookConfigs: 13 | - httpConfig: 14 | authorization: 15 | credentials: 16 | key: opsGenieApiKey 17 | name: alertmanager-global 18 | type: GenieKey 19 | sendResolved: false 20 | url: https://api.opsgenie.com/v2/heartbeats/test-installation-alice/ping 21 | route: 22 | groupInterval: 30s 23 | groupWait: 30s 24 | matchers: 25 | - name: cluster_id 26 | value: alice 27 | - name: installation 28 | value: test-installation 29 | - name: type 30 | value: heartbeat 31 | receiver: heartbeat_test-installation_alice 32 | repeatInterval: 15m 33 | -------------------------------------------------------------------------------- /service/controller/resource/alerting/heartbeatwebhookconfig/test/vintage/case-3-aws-v18.golden: -------------------------------------------------------------------------------- 1 | metadata: 2 | creationTimestamp: null 3 | labels: 4 | app.kubernetes.io/instance: alertmanager 5 | app.kubernetes.io/managed-by: prometheus-meta-operator 6 | app.kubernetes.io/name: alertmanager 7 | name: baz 8 | namespace: monitoring 9 | spec: 10 | receivers: 11 | - name: heartbeat_test-installation_baz 12 | webhookConfigs: 13 | - httpConfig: 14 | authorization: 15 | credentials: 16 | key: opsGenieApiKey 17 | name: alertmanager-global 18 | type: GenieKey 19 | sendResolved: false 20 | url: https://api.opsgenie.com/v2/heartbeats/test-installation-baz/ping 21 | route: 22 | groupInterval: 30s 23 | groupWait: 30s 24 | matchers: 25 | - name: cluster_id 26 | value: baz 27 | - name: installation 28 | value: test-installation 29 | - name: type 30 | value: heartbeat 31 | receiver: heartbeat_test-installation_baz 32 | repeatInterval: 15m 33 | -------------------------------------------------------------------------------- /service/controller/resource/certificates/create.go: -------------------------------------------------------------------------------- 1 | package certificates 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | 10 | "github.com/giantswarm/prometheus-meta-operator/v2/service/controller/resource/resourceutils" 11 | ) 12 | 13 | func (r *Resource) EnsureCreated(ctx context.Context, obj interface{}) error { 14 | if r.config.MimirEnabled { 15 | r.config.Logger.Debugf(ctx, "mimir is enabled, deleting heartbeat if it exists") 16 | return r.EnsureDeleted(ctx, obj) 17 | } 18 | desired, err := r.getDesiredObject(ctx, obj) 19 | if err != nil { 20 | return microerror.Mask(err) 21 | } 22 | 23 | r.config.Logger.Debugf(ctx, "creating") 24 | c := r.config.K8sClient.K8sClient().CoreV1().Secrets(desired.GetNamespace()) 25 | current, err := c.Get(ctx, desired.GetName(), metav1.GetOptions{}) 26 | if apierrors.IsNotFound(err) { 27 | current, err = c.Create(ctx, desired, metav1.CreateOptions{}) 28 | } 29 | if err != nil { 30 | return microerror.Mask(err) 31 | } 32 | 33 | if r.hasChanged(current, desired) { 34 | resourceutils.UpdateMeta(current, desired) 35 | _, err = c.Update(ctx, desired, metav1.UpdateOptions{}) 36 | if err != nil { 37 | return microerror.Mask(err) 38 | } 39 | } 40 | r.config.Logger.Debugf(ctx, "created") 41 | 42 | return nil 43 | } 44 | -------------------------------------------------------------------------------- /service/controller/resource/certificates/delete.go: -------------------------------------------------------------------------------- 1 | package certificates 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | ) 10 | 11 | func (r *Resource) EnsureDeleted(ctx context.Context, obj interface{}) error { 12 | object, err := r.getObjectMeta(obj) 13 | if err != nil { 14 | return microerror.Mask(err) 15 | } 16 | 17 | r.config.Logger.Debugf(ctx, "deleting") 18 | c := r.config.K8sClient.K8sClient().CoreV1().Secrets(object.GetNamespace()) 19 | err = c.Delete(ctx, object.GetName(), metav1.DeleteOptions{}) 20 | if apierrors.IsNotFound(err) { 21 | // fall through 22 | } else if err != nil { 23 | return microerror.Mask(err) 24 | } 25 | r.config.Logger.Debugf(ctx, "deleted") 26 | 27 | return nil 28 | } 29 | -------------------------------------------------------------------------------- /service/controller/resource/certificates/doc.go: -------------------------------------------------------------------------------- 1 | package certificates 2 | 3 | // The Kubernetes Secrets we currently use for prometheus (e.g: $CLUSTER_ID-prometheus) are held in the default namespace. 4 | // We want to run the Prometheus servers in a per-cluster namespace ($CLUSTER_ID-prometheus). prometheus-operator does not support referencing a secret in a different namespace. 5 | // So, we need to copy the secret default/$CLUSTER_ID-prometheus to the cluster prometheus namespace - e.g: $CLUSTER_ID-prometheus/cluster-certificates 6 | -------------------------------------------------------------------------------- /service/controller/resource/certificates/error.go: -------------------------------------------------------------------------------- 1 | package certificates 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var invalidConfigError = µerror.Error{ 8 | Kind: "invalidConfigError", 9 | } 10 | 11 | // IsInvalidConfig asserts invalidConfigError. 12 | func IsInvalidConfig(err error) bool { 13 | return microerror.Cause(err) == invalidConfigError 14 | } 15 | 16 | var wrongTypeError = µerror.Error{ 17 | Kind: "wrongTypeError", 18 | } 19 | 20 | // IsWrongType asserts wrongTypeError. 21 | func IsWrongType(err error) bool { 22 | return microerror.Cause(err) == wrongTypeError 23 | } 24 | -------------------------------------------------------------------------------- /service/controller/resource/ciliumnetpol/create.go: -------------------------------------------------------------------------------- 1 | package ciliumnetpol 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | "k8s.io/apimachinery/pkg/runtime/schema" 10 | 11 | "github.com/giantswarm/prometheus-meta-operator/v2/service/controller/resource/resourceutils" 12 | ) 13 | 14 | func (r *Resource) EnsureCreated(ctx context.Context, obj interface{}) error { 15 | if r.config.MimirEnabled { 16 | r.config.Logger.Debugf(ctx, "mimir is enabled, deleting heartbeat if it exists") 17 | return r.EnsureDeleted(ctx, obj) 18 | } 19 | 20 | r.config.Logger.Debugf(ctx, "creating") 21 | { 22 | resource := schema.GroupVersionResource{ 23 | Group: "cilium.io", 24 | Version: "v2", 25 | Resource: "ciliumnetworkpolicies", 26 | } 27 | 28 | desired, err := toCiliumNetworkPolicy(obj) 29 | if err != nil { 30 | return microerror.Mask(err) 31 | } 32 | 33 | current, err := r.config.DynamicK8sClient.Resource(resource).Namespace(desired.GetNamespace()).Get(ctx, desired.GetName(), metav1.GetOptions{}) 34 | if apierrors.IsNotFound(err) { 35 | current, err = r.config.DynamicK8sClient.Resource(resource).Namespace(desired.GetNamespace()).Create(ctx, desired, metav1.CreateOptions{}) 36 | } 37 | if err != nil { 38 | return microerror.Mask(err) 39 | } 40 | 41 | if hasCiliumNetworkPolicyChanged(current, desired) { 42 | resourceutils.UpdateMeta(current, desired) 43 | _, err = r.config.DynamicK8sClient.Resource(resource).Namespace(desired.GetNamespace()).Update(ctx, desired, metav1.UpdateOptions{}) 44 | if err != nil { 45 | return microerror.Mask(err) 46 | } 47 | } 48 | } 49 | r.config.Logger.Debugf(ctx, "created") 50 | 51 | return nil 52 | } 53 | -------------------------------------------------------------------------------- /service/controller/resource/ciliumnetpol/delete.go: -------------------------------------------------------------------------------- 1 | package ciliumnetpol 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | "k8s.io/apimachinery/pkg/runtime/schema" 10 | ) 11 | 12 | func (r *Resource) EnsureDeleted(ctx context.Context, obj interface{}) error { 13 | r.config.Logger.Debugf(ctx, "deleting") 14 | { 15 | resource := schema.GroupVersionResource{ 16 | Group: "cilium.io", 17 | Version: "v2", 18 | Resource: "ciliumnetworkpolicies", 19 | } 20 | 21 | desired, err := toCiliumNetworkPolicy(obj) 22 | if err != nil { 23 | return microerror.Mask(err) 24 | } 25 | 26 | err = r.config.DynamicK8sClient.Resource(resource).Namespace(desired.GetNamespace()).Delete(ctx, desired.GetName(), metav1.DeleteOptions{}) 27 | if apierrors.IsNotFound(err) { 28 | // fall through 29 | } else if err != nil { 30 | return microerror.Mask(err) 31 | } 32 | } 33 | r.config.Logger.Debugf(ctx, "deleted") 34 | 35 | return nil 36 | } 37 | -------------------------------------------------------------------------------- /service/controller/resource/ciliumnetpol/error.go: -------------------------------------------------------------------------------- 1 | package ciliumnetpol 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var invalidConfigError = µerror.Error{ 8 | Kind: "invalidConfigError", 9 | } 10 | 11 | // IsInvalidConfig asserts invalidConfigError. 12 | func IsInvalidConfig(err error) bool { 13 | return microerror.Cause(err) == invalidConfigError 14 | } 15 | 16 | var wrongTypeError = µerror.Error{ 17 | Kind: "wrongTypeError", 18 | } 19 | 20 | // IsWrongType asserts wrongTypeError. 21 | func IsWrongType(err error) bool { 22 | return microerror.Cause(err) == wrongTypeError 23 | } 24 | -------------------------------------------------------------------------------- /service/controller/resource/etcd-certificates/client.go: -------------------------------------------------------------------------------- 1 | package etcdcertificates 2 | 3 | import ( 4 | "context" 5 | 6 | corev1 "k8s.io/api/core/v1" 7 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 8 | clientcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" 9 | ) 10 | 11 | type wrappedClient struct { 12 | client clientcorev1.SecretInterface 13 | } 14 | 15 | func (c wrappedClient) Create(ctx context.Context, o metav1.Object, options metav1.CreateOptions) (metav1.Object, error) { 16 | return c.client.Create(ctx, o.(*corev1.Secret), options) 17 | } 18 | 19 | func (c wrappedClient) Update(ctx context.Context, o metav1.Object, options metav1.UpdateOptions) (metav1.Object, error) { 20 | return c.client.Update(ctx, o.(*corev1.Secret), options) 21 | } 22 | 23 | func (c wrappedClient) Get(ctx context.Context, name string, options metav1.GetOptions) (metav1.Object, error) { 24 | return c.client.Get(ctx, name, options) 25 | } 26 | 27 | func (c wrappedClient) Delete(ctx context.Context, name string, options *metav1.DeleteOptions) error { 28 | return c.client.Delete(ctx, name, *options) 29 | } 30 | -------------------------------------------------------------------------------- /service/controller/resource/etcd-certificates/doc.go: -------------------------------------------------------------------------------- 1 | package etcdcertificates 2 | 3 | // Package etcdcertificates implements a resource in charge of finding 4 | // necessary TLS certificates to communicate with Etcd endpoints. 5 | -------------------------------------------------------------------------------- /service/controller/resource/etcd-certificates/error.go: -------------------------------------------------------------------------------- 1 | package etcdcertificates 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var invalidConfigError = µerror.Error{ 8 | Kind: "invalidConfigError", 9 | } 10 | 11 | // IsInvalidConfig asserts invalidConfigError. 12 | func IsInvalidConfig(err error) bool { 13 | return microerror.Cause(err) == invalidConfigError 14 | } 15 | 16 | var wrongTypeError = µerror.Error{ 17 | Kind: "wrongTypeError", 18 | } 19 | 20 | // IsWrongType asserts wrongTypeError. 21 | func IsWrongType(err error) bool { 22 | return microerror.Cause(err) == wrongTypeError 23 | } 24 | 25 | var keyMissingError = µerror.Error{ 26 | Kind: "keyMissingError", 27 | } 28 | 29 | // IsKeyMissing asserts keyMissingError. 30 | func IsKeyMissing(err error) bool { 31 | return microerror.Cause(err) == keyMissingError 32 | } 33 | -------------------------------------------------------------------------------- /service/controller/resource/etcd-certificates/target.go: -------------------------------------------------------------------------------- 1 | package etcdcertificates 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | corev1 "k8s.io/api/core/v1" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | 10 | "github.com/giantswarm/prometheus-meta-operator/v2/service/key" 11 | ) 12 | 13 | // getObjectMeta returns the target secret metadata. 14 | func getObjectMeta(v interface{}, installation string) (metav1.ObjectMeta, error) { 15 | cluster, err := key.ToCluster(v) 16 | if err != nil { 17 | return metav1.ObjectMeta{}, microerror.Mask(err) 18 | } 19 | 20 | return metav1.ObjectMeta{ 21 | Name: key.EtcdSecret(installation, v), 22 | Namespace: key.Namespace(cluster), 23 | }, nil 24 | } 25 | 26 | // ToSecret returns the target secret by combining results of getObjectMeta and getSource. 27 | func (sc *secretCopier) ToSecret(ctx context.Context, v interface{}, config Config) (metav1.Object, error) { 28 | objectMeta, err := getObjectMeta(v, sc.installation) 29 | if err != nil { 30 | return nil, microerror.Mask(err) 31 | } 32 | 33 | data, err := sc.getSource(ctx, v, config) 34 | if err != nil { 35 | return nil, microerror.Mask(err) 36 | } 37 | 38 | secret := &corev1.Secret{ 39 | ObjectMeta: objectMeta, 40 | StringData: data, 41 | } 42 | 43 | return secret, nil 44 | } 45 | -------------------------------------------------------------------------------- /service/controller/resource/generic/create.go: -------------------------------------------------------------------------------- 1 | package generic 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | 10 | "github.com/giantswarm/prometheus-meta-operator/v2/service/controller/resource/resourceutils" 11 | ) 12 | 13 | func (r *Resource) EnsureCreated(ctx context.Context, obj interface{}) error { 14 | if r.deleteIfMimirEnabled { 15 | return r.EnsureDeleted(ctx, obj) 16 | } 17 | desired, err := r.getDesiredObject(ctx, obj) 18 | if err != nil { 19 | return microerror.Mask(err) 20 | } 21 | 22 | r.logger.Debugf(ctx, "creating") 23 | c := r.clientFunc(desired.GetNamespace()) 24 | current, err := c.Get(ctx, desired.GetName(), metav1.GetOptions{}) 25 | if apierrors.IsNotFound(err) { 26 | current, err = c.Create(ctx, desired, metav1.CreateOptions{}) 27 | } 28 | 29 | if err != nil { 30 | return microerror.Mask(err) 31 | } 32 | 33 | if r.hasChangedFunc(current, desired) { 34 | resourceutils.UpdateMeta(current, desired) 35 | _, err = c.Update(ctx, desired, metav1.UpdateOptions{}) 36 | if err != nil { 37 | return microerror.Mask(err) 38 | } 39 | } 40 | r.logger.Debugf(ctx, "created") 41 | 42 | return nil 43 | } 44 | -------------------------------------------------------------------------------- /service/controller/resource/generic/delete.go: -------------------------------------------------------------------------------- 1 | package generic 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | ) 10 | 11 | func (r *Resource) EnsureDeleted(ctx context.Context, obj interface{}) error { 12 | object, err := r.getObjectMeta(ctx, obj) 13 | if err != nil { 14 | return microerror.Mask(err) 15 | } 16 | 17 | r.logger.Debugf(ctx, "deleting") 18 | c := r.clientFunc(object.GetNamespace()) 19 | err = c.Delete(ctx, object.GetName(), &metav1.DeleteOptions{}) 20 | if apierrors.IsNotFound(err) { 21 | // fall through 22 | } else if err != nil { 23 | return microerror.Mask(err) 24 | } 25 | r.logger.Debugf(ctx, "deleted") 26 | 27 | return nil 28 | } 29 | -------------------------------------------------------------------------------- /service/controller/resource/generic/error.go: -------------------------------------------------------------------------------- 1 | package generic 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var invalidConfigError = µerror.Error{ 8 | Kind: "invalidConfigError", 9 | } 10 | 11 | // IsInvalidConfig asserts invalidConfigError. 12 | func IsInvalidConfig(err error) bool { 13 | return microerror.Cause(err) == invalidConfigError 14 | } 15 | 16 | var wrongTypeError = µerror.Error{ 17 | Kind: "wrongTypeError", 18 | } 19 | 20 | // IsWrongType asserts wrongTypeError. 21 | func IsWrongType(err error) bool { 22 | return microerror.Cause(err) == wrongTypeError 23 | } 24 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/client.go: -------------------------------------------------------------------------------- 1 | package ingress 2 | 3 | import ( 4 | "context" 5 | 6 | networkingv1 "k8s.io/api/networking/v1" 7 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 8 | v1 "k8s.io/client-go/kubernetes/typed/networking/v1" 9 | ) 10 | 11 | type wrappedClient struct { 12 | client v1.IngressInterface 13 | } 14 | 15 | func (c wrappedClient) Create(ctx context.Context, o metav1.Object, options metav1.CreateOptions) (metav1.Object, error) { 16 | return c.client.Create(ctx, o.(*networkingv1.Ingress), options) 17 | } 18 | 19 | func (c wrappedClient) Update(ctx context.Context, o metav1.Object, options metav1.UpdateOptions) (metav1.Object, error) { 20 | return c.client.Update(ctx, o.(*networkingv1.Ingress), options) 21 | } 22 | 23 | func (c wrappedClient) Get(ctx context.Context, name string, options metav1.GetOptions) (metav1.Object, error) { 24 | return c.client.Get(ctx, name, options) 25 | } 26 | 27 | func (c wrappedClient) Delete(ctx context.Context, name string, options *metav1.DeleteOptions) error { 28 | return c.client.Delete(ctx, name, *options) 29 | } 30 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/default/capi/case-1-capa-mc.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 6 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 7 | creationTimestamp: null 8 | labels: 9 | app.kubernetes.io/instance: test-installation 10 | app.kubernetes.io/managed-by: prometheus-meta-operator 11 | app.kubernetes.io/name: prometheus 12 | giantswarm.io/cluster: test-installation 13 | name: prometheus-test-installation 14 | namespace: test-installation-prometheus 15 | spec: 16 | ingressClassName: nginx 17 | rules: 18 | - host: prometheus 19 | http: 20 | paths: 21 | - backend: 22 | service: 23 | name: prometheus-operated 24 | port: 25 | number: 9090 26 | path: /test-installation 27 | pathType: ImplementationSpecific 28 | status: 29 | loadBalancer: {} 30 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/default/capi/case-2-capa.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 6 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 7 | creationTimestamp: null 8 | labels: 9 | app.kubernetes.io/instance: baz 10 | app.kubernetes.io/managed-by: prometheus-meta-operator 11 | app.kubernetes.io/name: prometheus 12 | giantswarm.io/cluster: baz 13 | name: prometheus-baz 14 | namespace: baz-prometheus 15 | spec: 16 | ingressClassName: nginx 17 | rules: 18 | - host: prometheus 19 | http: 20 | paths: 21 | - backend: 22 | service: 23 | name: prometheus-operated 24 | port: 25 | number: 9090 26 | path: /baz 27 | pathType: ImplementationSpecific 28 | status: 29 | loadBalancer: {} 30 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/default/capi/case-3-capz.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 6 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 7 | creationTimestamp: null 8 | labels: 9 | app.kubernetes.io/instance: foo 10 | app.kubernetes.io/managed-by: prometheus-meta-operator 11 | app.kubernetes.io/name: prometheus 12 | giantswarm.io/cluster: foo 13 | name: prometheus-foo 14 | namespace: foo-prometheus 15 | spec: 16 | ingressClassName: nginx 17 | rules: 18 | - host: prometheus 19 | http: 20 | paths: 21 | - backend: 22 | service: 23 | name: prometheus-operated 24 | port: 25 | number: 9090 26 | path: /foo 27 | pathType: ImplementationSpecific 28 | status: 29 | loadBalancer: {} 30 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/default/capi/case-4-eks.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 6 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 7 | creationTimestamp: null 8 | labels: 9 | app.kubernetes.io/instance: eks-sample 10 | app.kubernetes.io/managed-by: prometheus-meta-operator 11 | app.kubernetes.io/name: prometheus 12 | giantswarm.io/cluster: eks-sample 13 | name: prometheus-eks-sample 14 | namespace: eks-sample-prometheus 15 | spec: 16 | ingressClassName: nginx 17 | rules: 18 | - host: prometheus 19 | http: 20 | paths: 21 | - backend: 22 | service: 23 | name: prometheus-operated 24 | port: 25 | number: 9090 26 | path: /eks-sample 27 | pathType: ImplementationSpecific 28 | status: 29 | loadBalancer: {} 30 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/default/capi/case-5-gcp.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 6 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 7 | creationTimestamp: null 8 | labels: 9 | app.kubernetes.io/instance: gcp-sample 10 | app.kubernetes.io/managed-by: prometheus-meta-operator 11 | app.kubernetes.io/name: prometheus 12 | giantswarm.io/cluster: gcp-sample 13 | name: prometheus-gcp-sample 14 | namespace: gcp-sample-prometheus 15 | spec: 16 | ingressClassName: nginx 17 | rules: 18 | - host: prometheus 19 | http: 20 | paths: 21 | - backend: 22 | service: 23 | name: prometheus-operated 24 | port: 25 | number: 9090 26 | path: /gcp-sample 27 | pathType: ImplementationSpecific 28 | status: 29 | loadBalancer: {} 30 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/default/vintage/case-1-vintage-mc.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 6 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 7 | creationTimestamp: null 8 | labels: 9 | app.kubernetes.io/instance: kubernetes 10 | app.kubernetes.io/managed-by: prometheus-meta-operator 11 | app.kubernetes.io/name: prometheus 12 | giantswarm.io/cluster: kubernetes 13 | name: prometheus-kubernetes 14 | namespace: kubernetes-prometheus 15 | spec: 16 | ingressClassName: nginx 17 | rules: 18 | - host: prometheus 19 | http: 20 | paths: 21 | - backend: 22 | service: 23 | name: prometheus-operated 24 | port: 25 | number: 9090 26 | path: /kubernetes 27 | pathType: ImplementationSpecific 28 | status: 29 | loadBalancer: {} 30 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/default/vintage/case-2-aws-v16.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 6 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 7 | creationTimestamp: null 8 | labels: 9 | app.kubernetes.io/instance: alice 10 | app.kubernetes.io/managed-by: prometheus-meta-operator 11 | app.kubernetes.io/name: prometheus 12 | giantswarm.io/cluster: alice 13 | name: prometheus-alice 14 | namespace: alice-prometheus 15 | spec: 16 | ingressClassName: nginx 17 | rules: 18 | - host: prometheus 19 | http: 20 | paths: 21 | - backend: 22 | service: 23 | name: prometheus-operated 24 | port: 25 | number: 9090 26 | path: /alice 27 | pathType: ImplementationSpecific 28 | status: 29 | loadBalancer: {} 30 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/default/vintage/case-3-aws-v18.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 6 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 7 | creationTimestamp: null 8 | labels: 9 | app.kubernetes.io/instance: baz 10 | app.kubernetes.io/managed-by: prometheus-meta-operator 11 | app.kubernetes.io/name: prometheus 12 | giantswarm.io/cluster: baz 13 | name: prometheus-baz 14 | namespace: baz-prometheus 15 | spec: 16 | ingressClassName: nginx 17 | rules: 18 | - host: prometheus 19 | http: 20 | paths: 21 | - backend: 22 | service: 23 | name: prometheus-operated 24 | port: 25 | number: 9090 26 | path: /baz 27 | pathType: ImplementationSpecific 28 | status: 29 | loadBalancer: {} 30 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/externaldns-with-restricted-access/capi/case-1-capa-mc.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus.3lkdj.test.gigantic.io 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 8 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 9 | nginx.ingress.kubernetes.io/whitelist-source-range: 21.10.178/24 10 | creationTimestamp: null 11 | labels: 12 | app.kubernetes.io/instance: test-installation 13 | app.kubernetes.io/managed-by: prometheus-meta-operator 14 | app.kubernetes.io/name: prometheus 15 | giantswarm.io/cluster: test-installation 16 | name: prometheus-test-installation 17 | namespace: test-installation-prometheus 18 | spec: 19 | ingressClassName: nginx 20 | rules: 21 | - host: prometheus.3lkdj.test.gigantic.io 22 | http: 23 | paths: 24 | - backend: 25 | service: 26 | name: prometheus-operated 27 | port: 28 | number: 9090 29 | path: /test-installation 30 | pathType: ImplementationSpecific 31 | status: 32 | loadBalancer: {} 33 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/externaldns-with-restricted-access/capi/case-2-capa.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus.3lkdj.test.gigantic.io 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 8 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 9 | nginx.ingress.kubernetes.io/whitelist-source-range: 21.10.178/24 10 | creationTimestamp: null 11 | labels: 12 | app.kubernetes.io/instance: baz 13 | app.kubernetes.io/managed-by: prometheus-meta-operator 14 | app.kubernetes.io/name: prometheus 15 | giantswarm.io/cluster: baz 16 | name: prometheus-baz 17 | namespace: baz-prometheus 18 | spec: 19 | ingressClassName: nginx 20 | rules: 21 | - host: prometheus.3lkdj.test.gigantic.io 22 | http: 23 | paths: 24 | - backend: 25 | service: 26 | name: prometheus-operated 27 | port: 28 | number: 9090 29 | path: /baz 30 | pathType: ImplementationSpecific 31 | status: 32 | loadBalancer: {} 33 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/externaldns-with-restricted-access/capi/case-3-capz.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus.3lkdj.test.gigantic.io 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 8 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 9 | nginx.ingress.kubernetes.io/whitelist-source-range: 21.10.178/24 10 | creationTimestamp: null 11 | labels: 12 | app.kubernetes.io/instance: foo 13 | app.kubernetes.io/managed-by: prometheus-meta-operator 14 | app.kubernetes.io/name: prometheus 15 | giantswarm.io/cluster: foo 16 | name: prometheus-foo 17 | namespace: foo-prometheus 18 | spec: 19 | ingressClassName: nginx 20 | rules: 21 | - host: prometheus.3lkdj.test.gigantic.io 22 | http: 23 | paths: 24 | - backend: 25 | service: 26 | name: prometheus-operated 27 | port: 28 | number: 9090 29 | path: /foo 30 | pathType: ImplementationSpecific 31 | status: 32 | loadBalancer: {} 33 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/externaldns-with-restricted-access/capi/case-4-eks.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus.3lkdj.test.gigantic.io 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 8 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 9 | nginx.ingress.kubernetes.io/whitelist-source-range: 21.10.178/24 10 | creationTimestamp: null 11 | labels: 12 | app.kubernetes.io/instance: eks-sample 13 | app.kubernetes.io/managed-by: prometheus-meta-operator 14 | app.kubernetes.io/name: prometheus 15 | giantswarm.io/cluster: eks-sample 16 | name: prometheus-eks-sample 17 | namespace: eks-sample-prometheus 18 | spec: 19 | ingressClassName: nginx 20 | rules: 21 | - host: prometheus.3lkdj.test.gigantic.io 22 | http: 23 | paths: 24 | - backend: 25 | service: 26 | name: prometheus-operated 27 | port: 28 | number: 9090 29 | path: /eks-sample 30 | pathType: ImplementationSpecific 31 | status: 32 | loadBalancer: {} 33 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/externaldns-with-restricted-access/capi/case-5-gcp.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus.3lkdj.test.gigantic.io 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 8 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 9 | nginx.ingress.kubernetes.io/whitelist-source-range: 21.10.178/24 10 | creationTimestamp: null 11 | labels: 12 | app.kubernetes.io/instance: gcp-sample 13 | app.kubernetes.io/managed-by: prometheus-meta-operator 14 | app.kubernetes.io/name: prometheus 15 | giantswarm.io/cluster: gcp-sample 16 | name: prometheus-gcp-sample 17 | namespace: gcp-sample-prometheus 18 | spec: 19 | ingressClassName: nginx 20 | rules: 21 | - host: prometheus.3lkdj.test.gigantic.io 22 | http: 23 | paths: 24 | - backend: 25 | service: 26 | name: prometheus-operated 27 | port: 28 | number: 9090 29 | path: /gcp-sample 30 | pathType: ImplementationSpecific 31 | status: 32 | loadBalancer: {} 33 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/externaldns-with-restricted-access/vintage/case-1-vintage-mc.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus.3lkdj.test.gigantic.io 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 8 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 9 | nginx.ingress.kubernetes.io/whitelist-source-range: 21.10.178/24 10 | creationTimestamp: null 11 | labels: 12 | app.kubernetes.io/instance: kubernetes 13 | app.kubernetes.io/managed-by: prometheus-meta-operator 14 | app.kubernetes.io/name: prometheus 15 | giantswarm.io/cluster: kubernetes 16 | name: prometheus-kubernetes 17 | namespace: kubernetes-prometheus 18 | spec: 19 | ingressClassName: nginx 20 | rules: 21 | - host: prometheus.3lkdj.test.gigantic.io 22 | http: 23 | paths: 24 | - backend: 25 | service: 26 | name: prometheus-operated 27 | port: 28 | number: 9090 29 | path: /kubernetes 30 | pathType: ImplementationSpecific 31 | status: 32 | loadBalancer: {} 33 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/externaldns-with-restricted-access/vintage/case-2-aws-v16.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus.3lkdj.test.gigantic.io 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 8 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 9 | nginx.ingress.kubernetes.io/whitelist-source-range: 21.10.178/24 10 | creationTimestamp: null 11 | labels: 12 | app.kubernetes.io/instance: alice 13 | app.kubernetes.io/managed-by: prometheus-meta-operator 14 | app.kubernetes.io/name: prometheus 15 | giantswarm.io/cluster: alice 16 | name: prometheus-alice 17 | namespace: alice-prometheus 18 | spec: 19 | ingressClassName: nginx 20 | rules: 21 | - host: prometheus.3lkdj.test.gigantic.io 22 | http: 23 | paths: 24 | - backend: 25 | service: 26 | name: prometheus-operated 27 | port: 28 | number: 9090 29 | path: /alice 30 | pathType: ImplementationSpecific 31 | status: 32 | loadBalancer: {} 33 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/externaldns-with-restricted-access/vintage/case-3-aws-v18.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus.3lkdj.test.gigantic.io 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 8 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 9 | nginx.ingress.kubernetes.io/whitelist-source-range: 21.10.178/24 10 | creationTimestamp: null 11 | labels: 12 | app.kubernetes.io/instance: baz 13 | app.kubernetes.io/managed-by: prometheus-meta-operator 14 | app.kubernetes.io/name: prometheus 15 | giantswarm.io/cluster: baz 16 | name: prometheus-baz 17 | namespace: baz-prometheus 18 | spec: 19 | ingressClassName: nginx 20 | rules: 21 | - host: prometheus.3lkdj.test.gigantic.io 22 | http: 23 | paths: 24 | - backend: 25 | service: 26 | name: prometheus-operated 27 | port: 28 | number: 9090 29 | path: /baz 30 | pathType: ImplementationSpecific 31 | status: 32 | loadBalancer: {} 33 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/externaldns/capi/case-1-capa-mc.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 8 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 9 | creationTimestamp: null 10 | labels: 11 | app.kubernetes.io/instance: test-installation 12 | app.kubernetes.io/managed-by: prometheus-meta-operator 13 | app.kubernetes.io/name: prometheus 14 | giantswarm.io/cluster: test-installation 15 | name: prometheus-test-installation 16 | namespace: test-installation-prometheus 17 | spec: 18 | ingressClassName: nginx 19 | rules: 20 | - host: prometheus 21 | http: 22 | paths: 23 | - backend: 24 | service: 25 | name: prometheus-operated 26 | port: 27 | number: 9090 28 | path: /test-installation 29 | pathType: ImplementationSpecific 30 | status: 31 | loadBalancer: {} 32 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/externaldns/capi/case-2-capa.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 8 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 9 | creationTimestamp: null 10 | labels: 11 | app.kubernetes.io/instance: baz 12 | app.kubernetes.io/managed-by: prometheus-meta-operator 13 | app.kubernetes.io/name: prometheus 14 | giantswarm.io/cluster: baz 15 | name: prometheus-baz 16 | namespace: baz-prometheus 17 | spec: 18 | ingressClassName: nginx 19 | rules: 20 | - host: prometheus 21 | http: 22 | paths: 23 | - backend: 24 | service: 25 | name: prometheus-operated 26 | port: 27 | number: 9090 28 | path: /baz 29 | pathType: ImplementationSpecific 30 | status: 31 | loadBalancer: {} 32 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/externaldns/capi/case-3-capz.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 8 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 9 | creationTimestamp: null 10 | labels: 11 | app.kubernetes.io/instance: foo 12 | app.kubernetes.io/managed-by: prometheus-meta-operator 13 | app.kubernetes.io/name: prometheus 14 | giantswarm.io/cluster: foo 15 | name: prometheus-foo 16 | namespace: foo-prometheus 17 | spec: 18 | ingressClassName: nginx 19 | rules: 20 | - host: prometheus 21 | http: 22 | paths: 23 | - backend: 24 | service: 25 | name: prometheus-operated 26 | port: 27 | number: 9090 28 | path: /foo 29 | pathType: ImplementationSpecific 30 | status: 31 | loadBalancer: {} 32 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/externaldns/capi/case-4-eks.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 8 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 9 | creationTimestamp: null 10 | labels: 11 | app.kubernetes.io/instance: eks-sample 12 | app.kubernetes.io/managed-by: prometheus-meta-operator 13 | app.kubernetes.io/name: prometheus 14 | giantswarm.io/cluster: eks-sample 15 | name: prometheus-eks-sample 16 | namespace: eks-sample-prometheus 17 | spec: 18 | ingressClassName: nginx 19 | rules: 20 | - host: prometheus 21 | http: 22 | paths: 23 | - backend: 24 | service: 25 | name: prometheus-operated 26 | port: 27 | number: 9090 28 | path: /eks-sample 29 | pathType: ImplementationSpecific 30 | status: 31 | loadBalancer: {} 32 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/externaldns/capi/case-5-gcp.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 8 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 9 | creationTimestamp: null 10 | labels: 11 | app.kubernetes.io/instance: gcp-sample 12 | app.kubernetes.io/managed-by: prometheus-meta-operator 13 | app.kubernetes.io/name: prometheus 14 | giantswarm.io/cluster: gcp-sample 15 | name: prometheus-gcp-sample 16 | namespace: gcp-sample-prometheus 17 | spec: 18 | ingressClassName: nginx 19 | rules: 20 | - host: prometheus 21 | http: 22 | paths: 23 | - backend: 24 | service: 25 | name: prometheus-operated 26 | port: 27 | number: 9090 28 | path: /gcp-sample 29 | pathType: ImplementationSpecific 30 | status: 31 | loadBalancer: {} 32 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/externaldns/vintage/case-1-vintage-mc.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 8 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 9 | creationTimestamp: null 10 | labels: 11 | app.kubernetes.io/instance: kubernetes 12 | app.kubernetes.io/managed-by: prometheus-meta-operator 13 | app.kubernetes.io/name: prometheus 14 | giantswarm.io/cluster: kubernetes 15 | name: prometheus-kubernetes 16 | namespace: kubernetes-prometheus 17 | spec: 18 | ingressClassName: nginx 19 | rules: 20 | - host: prometheus 21 | http: 22 | paths: 23 | - backend: 24 | service: 25 | name: prometheus-operated 26 | port: 27 | number: 9090 28 | path: /kubernetes 29 | pathType: ImplementationSpecific 30 | status: 31 | loadBalancer: {} 32 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/externaldns/vintage/case-2-aws-v16.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 8 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 9 | creationTimestamp: null 10 | labels: 11 | app.kubernetes.io/instance: alice 12 | app.kubernetes.io/managed-by: prometheus-meta-operator 13 | app.kubernetes.io/name: prometheus 14 | giantswarm.io/cluster: alice 15 | name: prometheus-alice 16 | namespace: alice-prometheus 17 | spec: 18 | ingressClassName: nginx 19 | rules: 20 | - host: prometheus 21 | http: 22 | paths: 23 | - backend: 24 | service: 25 | name: prometheus-operated 26 | port: 27 | number: 9090 28 | path: /alice 29 | pathType: ImplementationSpecific 30 | status: 31 | loadBalancer: {} 32 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/externaldns/vintage/case-3-aws-v18.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 8 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 9 | creationTimestamp: null 10 | labels: 11 | app.kubernetes.io/instance: baz 12 | app.kubernetes.io/managed-by: prometheus-meta-operator 13 | app.kubernetes.io/name: prometheus 14 | giantswarm.io/cluster: baz 15 | name: prometheus-baz 16 | namespace: baz-prometheus 17 | spec: 18 | ingressClassName: nginx 19 | rules: 20 | - host: prometheus 21 | http: 22 | paths: 23 | - backend: 24 | service: 25 | name: prometheus-operated 26 | port: 27 | number: 9090 28 | path: /baz 29 | pathType: ImplementationSpecific 30 | status: 31 | loadBalancer: {} 32 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/restricted-access/capi/case-1-capa-mc.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 6 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 7 | nginx.ingress.kubernetes.io/whitelist-source-range: 21.10.178/24 8 | creationTimestamp: null 9 | labels: 10 | app.kubernetes.io/instance: test-installation 11 | app.kubernetes.io/managed-by: prometheus-meta-operator 12 | app.kubernetes.io/name: prometheus 13 | giantswarm.io/cluster: test-installation 14 | name: prometheus-test-installation 15 | namespace: test-installation-prometheus 16 | spec: 17 | ingressClassName: nginx 18 | rules: 19 | - host: prometheus 20 | http: 21 | paths: 22 | - backend: 23 | service: 24 | name: prometheus-operated 25 | port: 26 | number: 9090 27 | path: /test-installation 28 | pathType: ImplementationSpecific 29 | status: 30 | loadBalancer: {} 31 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/restricted-access/capi/case-2-capa.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 6 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 7 | nginx.ingress.kubernetes.io/whitelist-source-range: 21.10.178/24 8 | creationTimestamp: null 9 | labels: 10 | app.kubernetes.io/instance: baz 11 | app.kubernetes.io/managed-by: prometheus-meta-operator 12 | app.kubernetes.io/name: prometheus 13 | giantswarm.io/cluster: baz 14 | name: prometheus-baz 15 | namespace: baz-prometheus 16 | spec: 17 | ingressClassName: nginx 18 | rules: 19 | - host: prometheus 20 | http: 21 | paths: 22 | - backend: 23 | service: 24 | name: prometheus-operated 25 | port: 26 | number: 9090 27 | path: /baz 28 | pathType: ImplementationSpecific 29 | status: 30 | loadBalancer: {} 31 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/restricted-access/capi/case-3-capz.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 6 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 7 | nginx.ingress.kubernetes.io/whitelist-source-range: 21.10.178/24 8 | creationTimestamp: null 9 | labels: 10 | app.kubernetes.io/instance: foo 11 | app.kubernetes.io/managed-by: prometheus-meta-operator 12 | app.kubernetes.io/name: prometheus 13 | giantswarm.io/cluster: foo 14 | name: prometheus-foo 15 | namespace: foo-prometheus 16 | spec: 17 | ingressClassName: nginx 18 | rules: 19 | - host: prometheus 20 | http: 21 | paths: 22 | - backend: 23 | service: 24 | name: prometheus-operated 25 | port: 26 | number: 9090 27 | path: /foo 28 | pathType: ImplementationSpecific 29 | status: 30 | loadBalancer: {} 31 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/restricted-access/capi/case-4-eks.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 6 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 7 | nginx.ingress.kubernetes.io/whitelist-source-range: 21.10.178/24 8 | creationTimestamp: null 9 | labels: 10 | app.kubernetes.io/instance: eks-sample 11 | app.kubernetes.io/managed-by: prometheus-meta-operator 12 | app.kubernetes.io/name: prometheus 13 | giantswarm.io/cluster: eks-sample 14 | name: prometheus-eks-sample 15 | namespace: eks-sample-prometheus 16 | spec: 17 | ingressClassName: nginx 18 | rules: 19 | - host: prometheus 20 | http: 21 | paths: 22 | - backend: 23 | service: 24 | name: prometheus-operated 25 | port: 26 | number: 9090 27 | path: /eks-sample 28 | pathType: ImplementationSpecific 29 | status: 30 | loadBalancer: {} 31 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/restricted-access/capi/case-5-gcp.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 6 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 7 | nginx.ingress.kubernetes.io/whitelist-source-range: 21.10.178/24 8 | creationTimestamp: null 9 | labels: 10 | app.kubernetes.io/instance: gcp-sample 11 | app.kubernetes.io/managed-by: prometheus-meta-operator 12 | app.kubernetes.io/name: prometheus 13 | giantswarm.io/cluster: gcp-sample 14 | name: prometheus-gcp-sample 15 | namespace: gcp-sample-prometheus 16 | spec: 17 | ingressClassName: nginx 18 | rules: 19 | - host: prometheus 20 | http: 21 | paths: 22 | - backend: 23 | service: 24 | name: prometheus-operated 25 | port: 26 | number: 9090 27 | path: /gcp-sample 28 | pathType: ImplementationSpecific 29 | status: 30 | loadBalancer: {} 31 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/restricted-access/vintage/case-1-vintage-mc.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 6 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 7 | nginx.ingress.kubernetes.io/whitelist-source-range: 21.10.178/24 8 | creationTimestamp: null 9 | labels: 10 | app.kubernetes.io/instance: kubernetes 11 | app.kubernetes.io/managed-by: prometheus-meta-operator 12 | app.kubernetes.io/name: prometheus 13 | giantswarm.io/cluster: kubernetes 14 | name: prometheus-kubernetes 15 | namespace: kubernetes-prometheus 16 | spec: 17 | ingressClassName: nginx 18 | rules: 19 | - host: prometheus 20 | http: 21 | paths: 22 | - backend: 23 | service: 24 | name: prometheus-operated 25 | port: 26 | number: 9090 27 | path: /kubernetes 28 | pathType: ImplementationSpecific 29 | status: 30 | loadBalancer: {} 31 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/restricted-access/vintage/case-2-aws-v16.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 6 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 7 | nginx.ingress.kubernetes.io/whitelist-source-range: 21.10.178/24 8 | creationTimestamp: null 9 | labels: 10 | app.kubernetes.io/instance: alice 11 | app.kubernetes.io/managed-by: prometheus-meta-operator 12 | app.kubernetes.io/name: prometheus 13 | giantswarm.io/cluster: alice 14 | name: prometheus-alice 15 | namespace: alice-prometheus 16 | spec: 17 | ingressClassName: nginx 18 | rules: 19 | - host: prometheus 20 | http: 21 | paths: 22 | - backend: 23 | service: 24 | name: prometheus-operated 25 | port: 26 | number: 9090 27 | path: /alice 28 | pathType: ImplementationSpecific 29 | status: 30 | loadBalancer: {} 31 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/ingress/test/restricted-access/vintage/case-3-aws-v18.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri 6 | nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth 7 | nginx.ingress.kubernetes.io/whitelist-source-range: 21.10.178/24 8 | creationTimestamp: null 9 | labels: 10 | app.kubernetes.io/instance: baz 11 | app.kubernetes.io/managed-by: prometheus-meta-operator 12 | app.kubernetes.io/name: prometheus 13 | giantswarm.io/cluster: baz 14 | name: prometheus-baz 15 | namespace: baz-prometheus 16 | spec: 17 | ingressClassName: nginx 18 | rules: 19 | - host: prometheus 20 | http: 21 | paths: 22 | - backend: 23 | service: 24 | name: prometheus-operated 25 | port: 26 | number: 9090 27 | path: /baz 28 | pathType: ImplementationSpecific 29 | status: 30 | loadBalancer: {} 31 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/prometheus/client.go: -------------------------------------------------------------------------------- 1 | package prometheus 2 | 3 | import ( 4 | promv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" 5 | monv1 "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned/typed/monitoring/v1" 6 | "golang.org/x/net/context" 7 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 8 | ) 9 | 10 | type wrappedClient struct { 11 | client monv1.PrometheusInterface 12 | } 13 | 14 | func (c wrappedClient) Create(ctx context.Context, object metav1.Object, options metav1.CreateOptions) (metav1.Object, error) { 15 | return c.client.Create(ctx, object.(*promv1.Prometheus), options) 16 | } 17 | func (c wrappedClient) Update(ctx context.Context, object metav1.Object, options metav1.UpdateOptions) (metav1.Object, error) { 18 | return c.client.Update(ctx, object.(*promv1.Prometheus), options) 19 | } 20 | func (c wrappedClient) Get(ctx context.Context, name string, options metav1.GetOptions) (metav1.Object, error) { 21 | return c.client.Get(ctx, name, options) 22 | } 23 | func (c wrappedClient) Delete(ctx context.Context, name string, options *metav1.DeleteOptions) error { 24 | return c.client.Delete(ctx, name, *options) 25 | } 26 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/prometheus/error.go: -------------------------------------------------------------------------------- 1 | package prometheus 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var invalidConfigError = µerror.Error{ 8 | Kind: "invalidConfigError", 9 | } 10 | 11 | // IsInvalidConfig asserts invalidConfigError. 12 | func IsInvalidConfig(err error) bool { 13 | return microerror.Cause(err) == invalidConfigError 14 | } 15 | 16 | var wrongTypeError = µerror.Error{ 17 | Kind: "wrongTypeError", 18 | } 19 | 20 | // IsWrongType asserts wrongTypeError. 21 | func IsWrongType(err error) bool { 22 | return microerror.Cause(err) == wrongTypeError 23 | } 24 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/pvcresizingresource/delete.go: -------------------------------------------------------------------------------- 1 | package pvcresizingresource 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | func (r *Resource) EnsureDeleted(ctx context.Context, obj interface{}) error { 8 | // No need to delete anything as PV gets deleted by prometheus-operator 9 | 10 | return nil 11 | } 12 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/pvcresizingresource/doc.go: -------------------------------------------------------------------------------- 1 | package pvcresizingresource 2 | 3 | // This package is used to Watch Cluster CR and check if the value of 4 | // the annotation `monitoring.giantswarm.io/prometheus-volume-size` has changed 5 | // and triggers a PVC resize 6 | // following this procedure https://github.com/prometheus-operator/prometheus-operator/issues/4079#issuecomment-1211989005 7 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/pvcresizingresource/resource.go: -------------------------------------------------------------------------------- 1 | package pvcresizingresource 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/giantswarm/k8sclient/v7/pkg/k8sclient" 7 | "github.com/giantswarm/micrologger" 8 | ) 9 | 10 | const ( 11 | Name = "pvcresizingresource" 12 | ) 13 | 14 | type Config struct { 15 | K8sClient k8sclient.Interface 16 | Logger micrologger.Logger 17 | } 18 | 19 | type Resource struct { 20 | k8sClient k8sclient.Interface 21 | logger micrologger.Logger 22 | } 23 | 24 | func New(config Config) (*Resource, error) { 25 | r := &Resource{ 26 | k8sClient: config.K8sClient, 27 | logger: config.Logger, 28 | } 29 | 30 | return r, nil 31 | } 32 | 33 | func (r *Resource) Name() string { 34 | return Name 35 | } 36 | 37 | func resourceName(clusterID string) string { 38 | return fmt.Sprintf("prometheus-%v", clusterID) 39 | } 40 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteapiendpointconfigsecret/delete.go: -------------------------------------------------------------------------------- 1 | package remotewriteapiendpointconfigsecret 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | "k8s.io/apimachinery/pkg/types" 10 | 11 | "github.com/giantswarm/prometheus-meta-operator/v2/service/key" 12 | ) 13 | 14 | func (r *Resource) EnsureDeleted(ctx context.Context, obj interface{}) error { 15 | r.logger.Debugf(ctx, "deleting prometheus remote write api endpoint secret") 16 | { 17 | cluster, err := key.ToCluster(obj) 18 | if err != nil { 19 | return microerror.Mask(err) 20 | } 21 | 22 | name := key.RemoteWriteAPIEndpointConfigSecretName(cluster, r.provider) 23 | namespace := key.GetClusterAppsNamespace(cluster, r.installation, r.provider) 24 | 25 | _, err = r.k8sClient.K8sClient().CoreV1().Secrets(namespace).Get(ctx, name, metav1.GetOptions{}) 26 | if apierrors.IsNotFound(err) { 27 | // We ignore cases where the secret is not found (it it was manually deleted for instance) 28 | return nil 29 | } else if err != nil { 30 | return microerror.Mask(err) 31 | } 32 | 33 | // Delete the finalizer 34 | patch := []byte(`{"metadata":{"finalizers":null}}`) 35 | current, err := r.k8sClient.K8sClient().CoreV1().Secrets(namespace).Patch(ctx, name, types.StrategicMergePatchType, patch, metav1.PatchOptions{}) 36 | if err != nil { 37 | return microerror.Mask(err) 38 | } 39 | 40 | err = r.deleteSecret(ctx, current) 41 | if err != nil { 42 | return microerror.Mask(err) 43 | } 44 | 45 | } 46 | r.logger.Debugf(ctx, "deleted prometheus remote write api endpoint secret") 47 | 48 | return nil 49 | } 50 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteapiendpointconfigsecret/doc.go: -------------------------------------------------------------------------------- 1 | package remotewriteapiendpointconfigsecret 2 | 3 | // This packages wraps the remote write config in a secret. 4 | // This is to be used by prometheus operator to configure prometheus. 5 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteapiendpointconfigsecret/error.go: -------------------------------------------------------------------------------- 1 | package remotewriteapiendpointconfigsecret 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var invalidConfigError = µerror.Error{ 8 | Kind: "invalidConfigError", 9 | } 10 | 11 | // IsInvalidConfig asserts invalidConfigError. 12 | func IsInvalidConfig(err error) bool { 13 | return microerror.Cause(err) == invalidConfigError 14 | } 15 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteconfig/delete.go: -------------------------------------------------------------------------------- 1 | package remotewriteconfig 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | "k8s.io/apimachinery/pkg/types" 10 | 11 | "github.com/giantswarm/prometheus-meta-operator/v2/service/key" 12 | ) 13 | 14 | func (r *Resource) EnsureDeleted(ctx context.Context, obj interface{}) error { 15 | r.logger.Debugf(ctx, "deleting prometheus remote write config") 16 | { 17 | cluster, err := key.ToCluster(obj) 18 | if err != nil { 19 | return microerror.Mask(err) 20 | } 21 | 22 | name := key.RemoteWriteConfigName(cluster) 23 | namespace := key.GetClusterAppsNamespace(cluster, r.installation, r.provider) 24 | 25 | _, err = r.k8sClient.K8sClient().CoreV1().ConfigMaps(namespace).Get(ctx, name, metav1.GetOptions{}) 26 | if apierrors.IsNotFound(err) { 27 | // We ignore cases where the configmap is not found (it it was manually deleted for instance) 28 | return nil 29 | } else if err != nil { 30 | return microerror.Mask(err) 31 | } 32 | 33 | // Delete the finalizer 34 | patch := []byte(`{"metadata":{"finalizers":null}}`) 35 | current, err := r.k8sClient.K8sClient().CoreV1().ConfigMaps(namespace).Patch(ctx, name, types.StrategicMergePatchType, patch, metav1.PatchOptions{}) 36 | if err != nil { 37 | return microerror.Mask(err) 38 | } 39 | 40 | err = r.deleteConfigMap(ctx, current) 41 | if err != nil { 42 | return microerror.Mask(err) 43 | } 44 | 45 | } 46 | r.logger.Debugf(ctx, "deleted prometheus remote write config") 47 | 48 | return nil 49 | } 50 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteconfig/error.go: -------------------------------------------------------------------------------- 1 | package remotewriteconfig 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var invalidConfigError = µerror.Error{ 8 | Kind: "invalidConfigError", 9 | } 10 | 11 | // IsInvalidConfig asserts invalidConfigError. 12 | func IsInvalidConfig(err error) bool { 13 | return microerror.Cause(err) == invalidConfigError 14 | } 15 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingress/create.go: -------------------------------------------------------------------------------- 1 | package remotewriteingress 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | 10 | "github.com/giantswarm/prometheus-meta-operator/v2/service/controller/resource/resourceutils" 11 | ) 12 | 13 | func (r *Resource) EnsureCreated(ctx context.Context, obj interface{}) error { 14 | if r.config.MimirEnabled { 15 | r.config.Logger.Debugf(ctx, "mimir is enabled, deleting heartbeat if it exists") 16 | return r.EnsureDeleted(ctx, obj) 17 | } 18 | 19 | desired, err := r.toIngress(obj) 20 | if err != nil { 21 | return microerror.Mask(err) 22 | } 23 | 24 | r.config.Logger.Debugf(ctx, "creating") 25 | current, err := r.config.K8sClient.K8sClient().NetworkingV1().Ingresses(desired.GetNamespace()).Get(ctx, desired.GetName(), metav1.GetOptions{}) 26 | if apierrors.IsNotFound(err) { 27 | current, err = r.config.K8sClient.K8sClient().NetworkingV1().Ingresses(desired.GetNamespace()).Create(ctx, desired, metav1.CreateOptions{}) 28 | } 29 | 30 | if err != nil { 31 | return microerror.Mask(err) 32 | } 33 | 34 | if r.hasChanged(current, desired) { 35 | resourceutils.UpdateMeta(current, desired) 36 | _, err = r.config.K8sClient.K8sClient().NetworkingV1().Ingresses(desired.GetNamespace()).Update(ctx, desired, metav1.UpdateOptions{}) 37 | if err != nil { 38 | return microerror.Mask(err) 39 | } 40 | } 41 | r.config.Logger.Debugf(ctx, "created") 42 | 43 | return nil 44 | } 45 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingress/delete.go: -------------------------------------------------------------------------------- 1 | package remotewriteingress 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | ) 10 | 11 | func (r *Resource) EnsureDeleted(ctx context.Context, obj interface{}) error { 12 | object, err := r.getObjectMeta(obj) 13 | if err != nil { 14 | return microerror.Mask(err) 15 | } 16 | 17 | r.config.Logger.Debugf(ctx, "deleting") 18 | err = r.config.K8sClient.K8sClient().NetworkingV1().Ingresses(object.GetNamespace()).Delete(ctx, object.GetName(), metav1.DeleteOptions{}) 19 | if apierrors.IsNotFound(err) { 20 | // fall through 21 | } else if err != nil { 22 | return microerror.Mask(err) 23 | } 24 | r.config.Logger.Debugf(ctx, "deleted") 25 | 26 | return nil 27 | } 28 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingress/test/default/capi/case-1-capa-mc.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-realm: Authentication Required 6 | nginx.ingress.kubernetes.io/auth-secret: remote-write-ingress-auth 7 | nginx.ingress.kubernetes.io/auth-type: basic 8 | nginx.ingress.kubernetes.io/client-body-buffer-size: 50m 9 | nginx.ingress.kubernetes.io/proxy-body-size: 50m 10 | creationTimestamp: null 11 | labels: 12 | app.kubernetes.io/instance: test-installation 13 | app.kubernetes.io/managed-by: prometheus-meta-operator 14 | app.kubernetes.io/name: prometheus 15 | giantswarm.io/cluster: test-installation 16 | name: prometheus-test-installation-remote-write 17 | namespace: test-installation-prometheus 18 | spec: 19 | ingressClassName: nginx 20 | rules: 21 | - host: prometheus 22 | http: 23 | paths: 24 | - backend: 25 | service: 26 | name: prometheus-operated 27 | port: 28 | number: 9090 29 | path: /test-installation/api/v1/write 30 | pathType: ImplementationSpecific 31 | status: 32 | loadBalancer: {} 33 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingress/test/default/capi/case-2-capa.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-realm: Authentication Required 6 | nginx.ingress.kubernetes.io/auth-secret: remote-write-ingress-auth 7 | nginx.ingress.kubernetes.io/auth-type: basic 8 | nginx.ingress.kubernetes.io/client-body-buffer-size: 50m 9 | nginx.ingress.kubernetes.io/proxy-body-size: 50m 10 | creationTimestamp: null 11 | labels: 12 | app.kubernetes.io/instance: baz 13 | app.kubernetes.io/managed-by: prometheus-meta-operator 14 | app.kubernetes.io/name: prometheus 15 | giantswarm.io/cluster: baz 16 | name: prometheus-baz-remote-write 17 | namespace: baz-prometheus 18 | spec: 19 | ingressClassName: nginx 20 | rules: 21 | - host: prometheus 22 | http: 23 | paths: 24 | - backend: 25 | service: 26 | name: prometheus-operated 27 | port: 28 | number: 9090 29 | path: /baz/api/v1/write 30 | pathType: ImplementationSpecific 31 | status: 32 | loadBalancer: {} 33 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingress/test/default/capi/case-3-capz.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-realm: Authentication Required 6 | nginx.ingress.kubernetes.io/auth-secret: remote-write-ingress-auth 7 | nginx.ingress.kubernetes.io/auth-type: basic 8 | nginx.ingress.kubernetes.io/client-body-buffer-size: 50m 9 | nginx.ingress.kubernetes.io/proxy-body-size: 50m 10 | creationTimestamp: null 11 | labels: 12 | app.kubernetes.io/instance: foo 13 | app.kubernetes.io/managed-by: prometheus-meta-operator 14 | app.kubernetes.io/name: prometheus 15 | giantswarm.io/cluster: foo 16 | name: prometheus-foo-remote-write 17 | namespace: foo-prometheus 18 | spec: 19 | ingressClassName: nginx 20 | rules: 21 | - host: prometheus 22 | http: 23 | paths: 24 | - backend: 25 | service: 26 | name: prometheus-operated 27 | port: 28 | number: 9090 29 | path: /foo/api/v1/write 30 | pathType: ImplementationSpecific 31 | status: 32 | loadBalancer: {} 33 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingress/test/default/capi/case-4-eks.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-realm: Authentication Required 6 | nginx.ingress.kubernetes.io/auth-secret: remote-write-ingress-auth 7 | nginx.ingress.kubernetes.io/auth-type: basic 8 | nginx.ingress.kubernetes.io/client-body-buffer-size: 50m 9 | nginx.ingress.kubernetes.io/proxy-body-size: 50m 10 | creationTimestamp: null 11 | labels: 12 | app.kubernetes.io/instance: eks-sample 13 | app.kubernetes.io/managed-by: prometheus-meta-operator 14 | app.kubernetes.io/name: prometheus 15 | giantswarm.io/cluster: eks-sample 16 | name: prometheus-eks-sample-remote-write 17 | namespace: eks-sample-prometheus 18 | spec: 19 | ingressClassName: nginx 20 | rules: 21 | - host: prometheus 22 | http: 23 | paths: 24 | - backend: 25 | service: 26 | name: prometheus-operated 27 | port: 28 | number: 9090 29 | path: /eks-sample/api/v1/write 30 | pathType: ImplementationSpecific 31 | status: 32 | loadBalancer: {} 33 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingress/test/default/capi/case-5-gcp.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-realm: Authentication Required 6 | nginx.ingress.kubernetes.io/auth-secret: remote-write-ingress-auth 7 | nginx.ingress.kubernetes.io/auth-type: basic 8 | nginx.ingress.kubernetes.io/client-body-buffer-size: 50m 9 | nginx.ingress.kubernetes.io/proxy-body-size: 50m 10 | creationTimestamp: null 11 | labels: 12 | app.kubernetes.io/instance: gcp-sample 13 | app.kubernetes.io/managed-by: prometheus-meta-operator 14 | app.kubernetes.io/name: prometheus 15 | giantswarm.io/cluster: gcp-sample 16 | name: prometheus-gcp-sample-remote-write 17 | namespace: gcp-sample-prometheus 18 | spec: 19 | ingressClassName: nginx 20 | rules: 21 | - host: prometheus 22 | http: 23 | paths: 24 | - backend: 25 | service: 26 | name: prometheus-operated 27 | port: 28 | number: 9090 29 | path: /gcp-sample/api/v1/write 30 | pathType: ImplementationSpecific 31 | status: 32 | loadBalancer: {} 33 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingress/test/default/vintage/case-1-vintage-mc.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-realm: Authentication Required 6 | nginx.ingress.kubernetes.io/auth-secret: remote-write-ingress-auth 7 | nginx.ingress.kubernetes.io/auth-type: basic 8 | nginx.ingress.kubernetes.io/client-body-buffer-size: 50m 9 | nginx.ingress.kubernetes.io/proxy-body-size: 50m 10 | creationTimestamp: null 11 | labels: 12 | app.kubernetes.io/instance: kubernetes 13 | app.kubernetes.io/managed-by: prometheus-meta-operator 14 | app.kubernetes.io/name: prometheus 15 | giantswarm.io/cluster: kubernetes 16 | name: prometheus-kubernetes-remote-write 17 | namespace: kubernetes-prometheus 18 | spec: 19 | ingressClassName: nginx 20 | rules: 21 | - host: prometheus 22 | http: 23 | paths: 24 | - backend: 25 | service: 26 | name: prometheus-operated 27 | port: 28 | number: 9090 29 | path: /kubernetes/api/v1/write 30 | pathType: ImplementationSpecific 31 | status: 32 | loadBalancer: {} 33 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingress/test/default/vintage/case-2-aws-v16.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-realm: Authentication Required 6 | nginx.ingress.kubernetes.io/auth-secret: remote-write-ingress-auth 7 | nginx.ingress.kubernetes.io/auth-type: basic 8 | nginx.ingress.kubernetes.io/client-body-buffer-size: 50m 9 | nginx.ingress.kubernetes.io/proxy-body-size: 50m 10 | creationTimestamp: null 11 | labels: 12 | app.kubernetes.io/instance: alice 13 | app.kubernetes.io/managed-by: prometheus-meta-operator 14 | app.kubernetes.io/name: prometheus 15 | giantswarm.io/cluster: alice 16 | name: prometheus-alice-remote-write 17 | namespace: alice-prometheus 18 | spec: 19 | ingressClassName: nginx 20 | rules: 21 | - host: prometheus 22 | http: 23 | paths: 24 | - backend: 25 | service: 26 | name: prometheus-operated 27 | port: 28 | number: 9090 29 | path: /alice/api/v1/write 30 | pathType: ImplementationSpecific 31 | status: 32 | loadBalancer: {} 33 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingress/test/default/vintage/case-3-aws-v18.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | nginx.ingress.kubernetes.io/auth-realm: Authentication Required 6 | nginx.ingress.kubernetes.io/auth-secret: remote-write-ingress-auth 7 | nginx.ingress.kubernetes.io/auth-type: basic 8 | nginx.ingress.kubernetes.io/client-body-buffer-size: 50m 9 | nginx.ingress.kubernetes.io/proxy-body-size: 50m 10 | creationTimestamp: null 11 | labels: 12 | app.kubernetes.io/instance: baz 13 | app.kubernetes.io/managed-by: prometheus-meta-operator 14 | app.kubernetes.io/name: prometheus 15 | giantswarm.io/cluster: baz 16 | name: prometheus-baz-remote-write 17 | namespace: baz-prometheus 18 | spec: 19 | ingressClassName: nginx 20 | rules: 21 | - host: prometheus 22 | http: 23 | paths: 24 | - backend: 25 | service: 26 | name: prometheus-operated 27 | port: 28 | number: 9090 29 | path: /baz/api/v1/write 30 | pathType: ImplementationSpecific 31 | status: 32 | loadBalancer: {} 33 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingress/test/externaldns/capi/case-1-capa-mc.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-realm: Authentication Required 8 | nginx.ingress.kubernetes.io/auth-secret: remote-write-ingress-auth 9 | nginx.ingress.kubernetes.io/auth-type: basic 10 | nginx.ingress.kubernetes.io/client-body-buffer-size: 50m 11 | nginx.ingress.kubernetes.io/proxy-body-size: 50m 12 | creationTimestamp: null 13 | labels: 14 | app.kubernetes.io/instance: test-installation 15 | app.kubernetes.io/managed-by: prometheus-meta-operator 16 | app.kubernetes.io/name: prometheus 17 | giantswarm.io/cluster: test-installation 18 | name: prometheus-test-installation-remote-write 19 | namespace: test-installation-prometheus 20 | spec: 21 | ingressClassName: nginx 22 | rules: 23 | - host: prometheus 24 | http: 25 | paths: 26 | - backend: 27 | service: 28 | name: prometheus-operated 29 | port: 30 | number: 9090 31 | path: /test-installation/api/v1/write 32 | pathType: ImplementationSpecific 33 | status: 34 | loadBalancer: {} 35 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingress/test/externaldns/capi/case-2-capa.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-realm: Authentication Required 8 | nginx.ingress.kubernetes.io/auth-secret: remote-write-ingress-auth 9 | nginx.ingress.kubernetes.io/auth-type: basic 10 | nginx.ingress.kubernetes.io/client-body-buffer-size: 50m 11 | nginx.ingress.kubernetes.io/proxy-body-size: 50m 12 | creationTimestamp: null 13 | labels: 14 | app.kubernetes.io/instance: baz 15 | app.kubernetes.io/managed-by: prometheus-meta-operator 16 | app.kubernetes.io/name: prometheus 17 | giantswarm.io/cluster: baz 18 | name: prometheus-baz-remote-write 19 | namespace: baz-prometheus 20 | spec: 21 | ingressClassName: nginx 22 | rules: 23 | - host: prometheus 24 | http: 25 | paths: 26 | - backend: 27 | service: 28 | name: prometheus-operated 29 | port: 30 | number: 9090 31 | path: /baz/api/v1/write 32 | pathType: ImplementationSpecific 33 | status: 34 | loadBalancer: {} 35 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingress/test/externaldns/capi/case-3-capz.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-realm: Authentication Required 8 | nginx.ingress.kubernetes.io/auth-secret: remote-write-ingress-auth 9 | nginx.ingress.kubernetes.io/auth-type: basic 10 | nginx.ingress.kubernetes.io/client-body-buffer-size: 50m 11 | nginx.ingress.kubernetes.io/proxy-body-size: 50m 12 | creationTimestamp: null 13 | labels: 14 | app.kubernetes.io/instance: foo 15 | app.kubernetes.io/managed-by: prometheus-meta-operator 16 | app.kubernetes.io/name: prometheus 17 | giantswarm.io/cluster: foo 18 | name: prometheus-foo-remote-write 19 | namespace: foo-prometheus 20 | spec: 21 | ingressClassName: nginx 22 | rules: 23 | - host: prometheus 24 | http: 25 | paths: 26 | - backend: 27 | service: 28 | name: prometheus-operated 29 | port: 30 | number: 9090 31 | path: /foo/api/v1/write 32 | pathType: ImplementationSpecific 33 | status: 34 | loadBalancer: {} 35 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingress/test/externaldns/capi/case-4-eks.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-realm: Authentication Required 8 | nginx.ingress.kubernetes.io/auth-secret: remote-write-ingress-auth 9 | nginx.ingress.kubernetes.io/auth-type: basic 10 | nginx.ingress.kubernetes.io/client-body-buffer-size: 50m 11 | nginx.ingress.kubernetes.io/proxy-body-size: 50m 12 | creationTimestamp: null 13 | labels: 14 | app.kubernetes.io/instance: eks-sample 15 | app.kubernetes.io/managed-by: prometheus-meta-operator 16 | app.kubernetes.io/name: prometheus 17 | giantswarm.io/cluster: eks-sample 18 | name: prometheus-eks-sample-remote-write 19 | namespace: eks-sample-prometheus 20 | spec: 21 | ingressClassName: nginx 22 | rules: 23 | - host: prometheus 24 | http: 25 | paths: 26 | - backend: 27 | service: 28 | name: prometheus-operated 29 | port: 30 | number: 9090 31 | path: /eks-sample/api/v1/write 32 | pathType: ImplementationSpecific 33 | status: 34 | loadBalancer: {} 35 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingress/test/externaldns/capi/case-5-gcp.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-realm: Authentication Required 8 | nginx.ingress.kubernetes.io/auth-secret: remote-write-ingress-auth 9 | nginx.ingress.kubernetes.io/auth-type: basic 10 | nginx.ingress.kubernetes.io/client-body-buffer-size: 50m 11 | nginx.ingress.kubernetes.io/proxy-body-size: 50m 12 | creationTimestamp: null 13 | labels: 14 | app.kubernetes.io/instance: gcp-sample 15 | app.kubernetes.io/managed-by: prometheus-meta-operator 16 | app.kubernetes.io/name: prometheus 17 | giantswarm.io/cluster: gcp-sample 18 | name: prometheus-gcp-sample-remote-write 19 | namespace: gcp-sample-prometheus 20 | spec: 21 | ingressClassName: nginx 22 | rules: 23 | - host: prometheus 24 | http: 25 | paths: 26 | - backend: 27 | service: 28 | name: prometheus-operated 29 | port: 30 | number: 9090 31 | path: /gcp-sample/api/v1/write 32 | pathType: ImplementationSpecific 33 | status: 34 | loadBalancer: {} 35 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingress/test/externaldns/vintage/case-1-vintage-mc.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-realm: Authentication Required 8 | nginx.ingress.kubernetes.io/auth-secret: remote-write-ingress-auth 9 | nginx.ingress.kubernetes.io/auth-type: basic 10 | nginx.ingress.kubernetes.io/client-body-buffer-size: 50m 11 | nginx.ingress.kubernetes.io/proxy-body-size: 50m 12 | creationTimestamp: null 13 | labels: 14 | app.kubernetes.io/instance: kubernetes 15 | app.kubernetes.io/managed-by: prometheus-meta-operator 16 | app.kubernetes.io/name: prometheus 17 | giantswarm.io/cluster: kubernetes 18 | name: prometheus-kubernetes-remote-write 19 | namespace: kubernetes-prometheus 20 | spec: 21 | ingressClassName: nginx 22 | rules: 23 | - host: prometheus 24 | http: 25 | paths: 26 | - backend: 27 | service: 28 | name: prometheus-operated 29 | port: 30 | number: 9090 31 | path: /kubernetes/api/v1/write 32 | pathType: ImplementationSpecific 33 | status: 34 | loadBalancer: {} 35 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingress/test/externaldns/vintage/case-2-aws-v16.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-realm: Authentication Required 8 | nginx.ingress.kubernetes.io/auth-secret: remote-write-ingress-auth 9 | nginx.ingress.kubernetes.io/auth-type: basic 10 | nginx.ingress.kubernetes.io/client-body-buffer-size: 50m 11 | nginx.ingress.kubernetes.io/proxy-body-size: 50m 12 | creationTimestamp: null 13 | labels: 14 | app.kubernetes.io/instance: alice 15 | app.kubernetes.io/managed-by: prometheus-meta-operator 16 | app.kubernetes.io/name: prometheus 17 | giantswarm.io/cluster: alice 18 | name: prometheus-alice-remote-write 19 | namespace: alice-prometheus 20 | spec: 21 | ingressClassName: nginx 22 | rules: 23 | - host: prometheus 24 | http: 25 | paths: 26 | - backend: 27 | service: 28 | name: prometheus-operated 29 | port: 30 | number: 9090 31 | path: /alice/api/v1/write 32 | pathType: ImplementationSpecific 33 | status: 34 | loadBalancer: {} 35 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingress/test/externaldns/vintage/case-3-aws-v18.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | external-dns.alpha.kubernetes.io/hostname: prometheus 6 | giantswarm.io/external-dns: managed 7 | nginx.ingress.kubernetes.io/auth-realm: Authentication Required 8 | nginx.ingress.kubernetes.io/auth-secret: remote-write-ingress-auth 9 | nginx.ingress.kubernetes.io/auth-type: basic 10 | nginx.ingress.kubernetes.io/client-body-buffer-size: 50m 11 | nginx.ingress.kubernetes.io/proxy-body-size: 50m 12 | creationTimestamp: null 13 | labels: 14 | app.kubernetes.io/instance: baz 15 | app.kubernetes.io/managed-by: prometheus-meta-operator 16 | app.kubernetes.io/name: prometheus 17 | giantswarm.io/cluster: baz 18 | name: prometheus-baz-remote-write 19 | namespace: baz-prometheus 20 | spec: 21 | ingressClassName: nginx 22 | rules: 23 | - host: prometheus 24 | http: 25 | paths: 26 | - backend: 27 | service: 28 | name: prometheus-operated 29 | port: 30 | number: 9090 31 | path: /baz/api/v1/write 32 | pathType: ImplementationSpecific 33 | status: 34 | loadBalancer: {} 35 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingressauth/create.go: -------------------------------------------------------------------------------- 1 | package remotewriteingressauth 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | 10 | "github.com/giantswarm/prometheus-meta-operator/v2/service/controller/resource/resourceutils" 11 | ) 12 | 13 | func (r *Resource) EnsureCreated(ctx context.Context, obj interface{}) error { 14 | if r.config.MimirEnabled { 15 | r.config.Logger.Debugf(ctx, "mimir is enabled, deleting heartbeat if it exists") 16 | return r.EnsureDeleted(ctx, obj) 17 | } 18 | 19 | desired, err := r.toSecret(ctx, obj) 20 | if err != nil { 21 | return microerror.Mask(err) 22 | } 23 | 24 | r.config.Logger.Debugf(ctx, "creating") 25 | current, err := r.config.K8sClient.K8sClient().CoreV1().Secrets(desired.GetNamespace()).Get(ctx, desired.GetName(), metav1.GetOptions{}) 26 | if apierrors.IsNotFound(err) { 27 | current, err = r.config.K8sClient.K8sClient().CoreV1().Secrets(desired.GetNamespace()).Create(ctx, desired, metav1.CreateOptions{}) 28 | } 29 | 30 | if err != nil { 31 | return microerror.Mask(err) 32 | } 33 | 34 | if r.hasChanged(current, desired) { 35 | resourceutils.UpdateMeta(current, desired) 36 | _, err = r.config.K8sClient.K8sClient().CoreV1().Secrets(desired.GetNamespace()).Update(ctx, desired, metav1.UpdateOptions{}) 37 | if err != nil { 38 | return microerror.Mask(err) 39 | } 40 | } 41 | r.config.Logger.Debugf(ctx, "created") 42 | 43 | return nil 44 | } 45 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingressauth/delete.go: -------------------------------------------------------------------------------- 1 | package remotewriteingressauth 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | ) 10 | 11 | func (r *Resource) EnsureDeleted(ctx context.Context, obj interface{}) error { 12 | object, err := r.getObjectMeta(obj) 13 | if err != nil { 14 | return microerror.Mask(err) 15 | } 16 | 17 | r.config.Logger.Debugf(ctx, "deleting") 18 | err = r.config.K8sClient.K8sClient().CoreV1().Secrets(object.GetNamespace()).Delete(ctx, object.GetName(), metav1.DeleteOptions{}) 19 | if apierrors.IsNotFound(err) { 20 | // fall through 21 | } else if err != nil { 22 | return microerror.Mask(err) 23 | } 24 | r.config.Logger.Debugf(ctx, "deleted") 25 | 26 | return nil 27 | } 28 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewriteingressauth/doc.go: -------------------------------------------------------------------------------- 1 | package remotewriteingressauth 2 | 3 | // This packages creates the remote write secret 4 | // to be used to secure the prometheus remote write ingress endpoint. 5 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewritesecret/delete.go: -------------------------------------------------------------------------------- 1 | package remotewritesecret 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | "k8s.io/apimachinery/pkg/types" 10 | 11 | "github.com/giantswarm/prometheus-meta-operator/v2/service/key" 12 | ) 13 | 14 | func (r *Resource) EnsureDeleted(ctx context.Context, obj interface{}) error { 15 | r.logger.Debugf(ctx, "deleting prometheus remote write secret") 16 | { 17 | cluster, err := key.ToCluster(obj) 18 | if err != nil { 19 | return microerror.Mask(err) 20 | } 21 | 22 | name := key.RemoteWriteSecretName(cluster) 23 | namespace := key.GetClusterAppsNamespace(cluster, r.Installation, r.Provider) 24 | 25 | _, err = r.k8sClient.K8sClient().CoreV1().Secrets(namespace).Get(ctx, name, metav1.GetOptions{}) 26 | if apierrors.IsNotFound(err) { 27 | // We ignore cases where the secret is not found (it it was manually deleted for instance) 28 | return nil 29 | } else if err != nil { 30 | return microerror.Mask(err) 31 | } 32 | 33 | // Delete the finalizer 34 | patch := []byte(`{"metadata":{"finalizers":null}}`) 35 | current, err := r.k8sClient.K8sClient().CoreV1().Secrets(namespace).Patch(ctx, name, types.StrategicMergePatchType, patch, metav1.PatchOptions{}) 36 | if err != nil { 37 | return microerror.Mask(err) 38 | } 39 | 40 | err = r.deleteSecret(ctx, current) 41 | if err != nil { 42 | return microerror.Mask(err) 43 | } 44 | 45 | } 46 | r.logger.Debugf(ctx, "deleted prometheus remote write secret") 47 | 48 | return nil 49 | } 50 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/remotewritesecret/error.go: -------------------------------------------------------------------------------- 1 | package remotewritesecret 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var invalidConfigError = µerror.Error{ 8 | Kind: "invalidConfigError", 9 | } 10 | 11 | // IsInvalidConfig asserts invalidConfigError. 12 | func IsInvalidConfig(err error) bool { 13 | return microerror.Cause(err) == invalidConfigError 14 | } 15 | 16 | var remoteWriteNotFound = µerror.Error{ 17 | Kind: "remoteWriteNotFound", 18 | } 19 | 20 | // IsRemoteWriteNotFound asserts remoteWriteNotFound. 21 | func IsRemoteWriteNotFound(err error) bool { 22 | return microerror.Cause(err) == remoteWriteNotFound 23 | } 24 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/scrapeconfigs/client.go: -------------------------------------------------------------------------------- 1 | package scrapeconfigs 2 | 3 | import ( 4 | "context" 5 | 6 | corev1 "k8s.io/api/core/v1" 7 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 8 | v1 "k8s.io/client-go/kubernetes/typed/core/v1" 9 | ) 10 | 11 | type wrappedClient struct { 12 | client v1.SecretInterface 13 | } 14 | 15 | func (c wrappedClient) Create(ctx context.Context, o metav1.Object, options metav1.CreateOptions) (metav1.Object, error) { 16 | return c.client.Create(ctx, o.(*corev1.Secret), options) 17 | } 18 | func (c wrappedClient) Update(ctx context.Context, o metav1.Object, options metav1.UpdateOptions) (metav1.Object, error) { 19 | return c.client.Update(ctx, o.(*corev1.Secret), options) 20 | } 21 | func (c wrappedClient) Get(ctx context.Context, name string, options metav1.GetOptions) (metav1.Object, error) { 22 | return c.client.Get(ctx, name, options) 23 | } 24 | func (c wrappedClient) Delete(ctx context.Context, name string, options *metav1.DeleteOptions) error { 25 | return c.client.Delete(ctx, name, *options) 26 | } 27 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/scrapeconfigs/error.go: -------------------------------------------------------------------------------- 1 | package scrapeconfigs 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var invalidConfigError = µerror.Error{ 8 | Kind: "invalidConfigError", 9 | } 10 | 11 | // IsInvalidConfig asserts invalidConfigError. 12 | func IsInvalidConfig(err error) bool { 13 | return microerror.Cause(err) == invalidConfigError 14 | } 15 | 16 | var wrongTypeError = µerror.Error{ 17 | Kind: "wrongTypeError", 18 | } 19 | 20 | // IsWrongType asserts wrongTypeError. 21 | func IsWrongType(err error) bool { 22 | return microerror.Cause(err) == wrongTypeError 23 | } 24 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/verticalpodautoscaler/create.go: -------------------------------------------------------------------------------- 1 | package verticalpodautoscaler 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | 10 | "github.com/giantswarm/prometheus-meta-operator/v2/service/controller/resource/resourceutils" 11 | ) 12 | 13 | func (r *Resource) EnsureCreated(ctx context.Context, obj interface{}) error { 14 | if r.config.MimirEnabled { 15 | r.config.Logger.Debugf(ctx, "mimir is enabled, deleting heartbeat if it exists") 16 | return r.EnsureDeleted(ctx, obj) 17 | } 18 | 19 | desired, err := r.getObject(ctx, obj) 20 | if err != nil { 21 | return microerror.Mask(err) 22 | } 23 | 24 | r.config.Logger.Debugf(ctx, "checking if vpa cr already exists") 25 | current, err := r.config.VpaClient.AutoscalingV1().VerticalPodAutoscalers(desired.GetNamespace()).Get(ctx, desired.GetName(), metav1.GetOptions{}) 26 | if apierrors.IsNotFound(err) { 27 | r.config.Logger.Debugf(ctx, "creating") 28 | _, err = r.config.VpaClient.AutoscalingV1().VerticalPodAutoscalers(desired.GetNamespace()).Create(ctx, desired, metav1.CreateOptions{}) 29 | if err != nil { 30 | return microerror.Mask(err) 31 | } 32 | r.config.Logger.Debugf(ctx, "created") 33 | return nil 34 | } else if err != nil { 35 | return microerror.Mask(err) 36 | } 37 | 38 | r.config.Logger.Debugf(ctx, "checking if vpa cr needs to be updated") 39 | if hasChanged(current, desired) { 40 | r.config.Logger.Debugf(ctx, "updating") 41 | resourceutils.UpdateMeta(current, desired) 42 | _, err = r.config.VpaClient.AutoscalingV1().VerticalPodAutoscalers(desired.GetNamespace()).Update(ctx, desired, metav1.UpdateOptions{}) 43 | if err != nil { 44 | return microerror.Mask(err) 45 | } 46 | r.config.Logger.Debugf(ctx, "updated") 47 | } 48 | 49 | return nil 50 | } 51 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/verticalpodautoscaler/delete.go: -------------------------------------------------------------------------------- 1 | package verticalpodautoscaler 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | ) 10 | 11 | func (r *Resource) EnsureDeleted(ctx context.Context, obj interface{}) error { 12 | object, err := r.getObjectMeta(obj) 13 | if err != nil { 14 | return microerror.Mask(err) 15 | } 16 | 17 | r.config.Logger.Debugf(ctx, "deleting") 18 | err = r.config.VpaClient.AutoscalingV1().VerticalPodAutoscalers(object.GetNamespace()).Delete(ctx, object.GetName(), metav1.DeleteOptions{}) 19 | if apierrors.IsNotFound(err) { 20 | // fall through 21 | } else if err != nil { 22 | return microerror.Mask(err) 23 | } 24 | r.config.Logger.Debugf(ctx, "deleted") 25 | 26 | return nil 27 | } 28 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/verticalpodautoscaler/error.go: -------------------------------------------------------------------------------- 1 | package verticalpodautoscaler 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var invalidConfigError = µerror.Error{ 8 | Kind: "invalidConfigError", 9 | } 10 | 11 | // IsInvalidConfig asserts invalidConfigError. 12 | func IsInvalidConfig(err error) bool { 13 | return microerror.Cause(err) == invalidConfigError 14 | } 15 | 16 | var quantityConversionError = µerror.Error{ 17 | Kind: "quantityConversionError", 18 | } 19 | 20 | // IsQuantityConversion asserts quantityConversionError. 21 | func IsQuantityConversion(err error) bool { 22 | return microerror.Cause(err) == quantityConversionError 23 | } 24 | 25 | var nodeCpuNotFoundError = µerror.Error{ 26 | Kind: "nodeCpuNotFoundError", 27 | } 28 | 29 | // IsNodeCpuNotFound asserts nodeCpuNotFoundError. 30 | func IsNodeCpuNotFound(err error) bool { 31 | return microerror.Cause(err) == nodeCpuNotFoundError 32 | } 33 | 34 | var nodeMemoryNotFoundError = µerror.Error{ 35 | Kind: "nodeMemoryNotFoundError", 36 | } 37 | 38 | // IsNodeMemoryNotFound asserts nodeMemoryNotFoundError. 39 | func IsNodeMemoryNotFound(err error) bool { 40 | return microerror.Cause(err) == nodeMemoryNotFoundError 41 | } 42 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/verticalpodautoscaler/test/capi/case-1-capa-mc.golden: -------------------------------------------------------------------------------- 1 | metadata: 2 | creationTimestamp: null 3 | labels: 4 | app.kubernetes.io/instance: test-installation 5 | app.kubernetes.io/managed-by: prometheus-meta-operator 6 | app.kubernetes.io/name: prometheus 7 | giantswarm.io/cluster: test-installation 8 | name: prometheus 9 | namespace: test-installation-prometheus 10 | spec: 11 | resourcePolicy: 12 | containerPolicies: 13 | - containerName: prometheus 14 | controlledValues: RequestsAndLimits 15 | maxAllowed: 16 | cpu: "4" 17 | memory: "13743895347" 18 | minAllowed: 19 | cpu: 100m 20 | memory: "1073741824" 21 | mode: Auto 22 | targetRef: 23 | apiVersion: apps/v1 24 | kind: StatefulSet 25 | name: prometheus-test-installation 26 | updatePolicy: 27 | updateMode: Auto 28 | status: {} 29 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/verticalpodautoscaler/test/capi/case-2-capa.golden: -------------------------------------------------------------------------------- 1 | metadata: 2 | creationTimestamp: null 3 | labels: 4 | app.kubernetes.io/instance: baz 5 | app.kubernetes.io/managed-by: prometheus-meta-operator 6 | app.kubernetes.io/name: prometheus 7 | giantswarm.io/cluster: baz 8 | name: prometheus 9 | namespace: baz-prometheus 10 | spec: 11 | resourcePolicy: 12 | containerPolicies: 13 | - containerName: prometheus 14 | controlledValues: RequestsAndLimits 15 | maxAllowed: 16 | cpu: "4" 17 | memory: "13743895347" 18 | minAllowed: 19 | cpu: 100m 20 | memory: "1073741824" 21 | mode: Auto 22 | targetRef: 23 | apiVersion: apps/v1 24 | kind: StatefulSet 25 | name: prometheus-baz 26 | updatePolicy: 27 | updateMode: Auto 28 | status: {} 29 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/verticalpodautoscaler/test/capi/case-3-capz.golden: -------------------------------------------------------------------------------- 1 | metadata: 2 | creationTimestamp: null 3 | labels: 4 | app.kubernetes.io/instance: foo 5 | app.kubernetes.io/managed-by: prometheus-meta-operator 6 | app.kubernetes.io/name: prometheus 7 | giantswarm.io/cluster: foo 8 | name: prometheus 9 | namespace: foo-prometheus 10 | spec: 11 | resourcePolicy: 12 | containerPolicies: 13 | - containerName: prometheus 14 | controlledValues: RequestsAndLimits 15 | maxAllowed: 16 | cpu: "4" 17 | memory: "13743895347" 18 | minAllowed: 19 | cpu: 100m 20 | memory: "1073741824" 21 | mode: Auto 22 | targetRef: 23 | apiVersion: apps/v1 24 | kind: StatefulSet 25 | name: prometheus-foo 26 | updatePolicy: 27 | updateMode: Auto 28 | status: {} 29 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/verticalpodautoscaler/test/capi/case-4-eks.golden: -------------------------------------------------------------------------------- 1 | metadata: 2 | creationTimestamp: null 3 | labels: 4 | app.kubernetes.io/instance: eks-sample 5 | app.kubernetes.io/managed-by: prometheus-meta-operator 6 | app.kubernetes.io/name: prometheus 7 | giantswarm.io/cluster: eks-sample 8 | name: prometheus 9 | namespace: eks-sample-prometheus 10 | spec: 11 | resourcePolicy: 12 | containerPolicies: 13 | - containerName: prometheus 14 | controlledValues: RequestsAndLimits 15 | maxAllowed: 16 | cpu: "4" 17 | memory: "13743895347" 18 | minAllowed: 19 | cpu: 100m 20 | memory: "1073741824" 21 | mode: Auto 22 | targetRef: 23 | apiVersion: apps/v1 24 | kind: StatefulSet 25 | name: prometheus-eks-sample 26 | updatePolicy: 27 | updateMode: Auto 28 | status: {} 29 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/verticalpodautoscaler/test/capi/case-5-gcp.golden: -------------------------------------------------------------------------------- 1 | metadata: 2 | creationTimestamp: null 3 | labels: 4 | app.kubernetes.io/instance: gcp-sample 5 | app.kubernetes.io/managed-by: prometheus-meta-operator 6 | app.kubernetes.io/name: prometheus 7 | giantswarm.io/cluster: gcp-sample 8 | name: prometheus 9 | namespace: gcp-sample-prometheus 10 | spec: 11 | resourcePolicy: 12 | containerPolicies: 13 | - containerName: prometheus 14 | controlledValues: RequestsAndLimits 15 | maxAllowed: 16 | cpu: "4" 17 | memory: "13743895347" 18 | minAllowed: 19 | cpu: 100m 20 | memory: "1073741824" 21 | mode: Auto 22 | targetRef: 23 | apiVersion: apps/v1 24 | kind: StatefulSet 25 | name: prometheus-gcp-sample 26 | updatePolicy: 27 | updateMode: Auto 28 | status: {} 29 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/verticalpodautoscaler/test/vintage/case-1-vintage-mc.golden: -------------------------------------------------------------------------------- 1 | metadata: 2 | creationTimestamp: null 3 | labels: 4 | app.kubernetes.io/instance: kubernetes 5 | app.kubernetes.io/managed-by: prometheus-meta-operator 6 | app.kubernetes.io/name: prometheus 7 | giantswarm.io/cluster: kubernetes 8 | name: prometheus 9 | namespace: kubernetes-prometheus 10 | spec: 11 | resourcePolicy: 12 | containerPolicies: 13 | - containerName: prometheus 14 | controlledValues: RequestsAndLimits 15 | maxAllowed: 16 | cpu: "4" 17 | memory: "13743895347" 18 | minAllowed: 19 | cpu: 100m 20 | memory: "1073741824" 21 | mode: Auto 22 | targetRef: 23 | apiVersion: apps/v1 24 | kind: StatefulSet 25 | name: prometheus-kubernetes 26 | updatePolicy: 27 | updateMode: Auto 28 | status: {} 29 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/verticalpodautoscaler/test/vintage/case-2-aws-v16.golden: -------------------------------------------------------------------------------- 1 | metadata: 2 | creationTimestamp: null 3 | labels: 4 | app.kubernetes.io/instance: alice 5 | app.kubernetes.io/managed-by: prometheus-meta-operator 6 | app.kubernetes.io/name: prometheus 7 | giantswarm.io/cluster: alice 8 | name: prometheus 9 | namespace: alice-prometheus 10 | spec: 11 | resourcePolicy: 12 | containerPolicies: 13 | - containerName: prometheus 14 | controlledValues: RequestsAndLimits 15 | maxAllowed: 16 | cpu: "4" 17 | memory: "13743895347" 18 | minAllowed: 19 | cpu: 100m 20 | memory: "1073741824" 21 | mode: Auto 22 | targetRef: 23 | apiVersion: apps/v1 24 | kind: StatefulSet 25 | name: prometheus-alice 26 | updatePolicy: 27 | updateMode: Auto 28 | status: {} 29 | -------------------------------------------------------------------------------- /service/controller/resource/monitoring/verticalpodautoscaler/test/vintage/case-3-aws-v18.golden: -------------------------------------------------------------------------------- 1 | metadata: 2 | creationTimestamp: null 3 | labels: 4 | app.kubernetes.io/instance: baz 5 | app.kubernetes.io/managed-by: prometheus-meta-operator 6 | app.kubernetes.io/name: prometheus 7 | giantswarm.io/cluster: baz 8 | name: prometheus 9 | namespace: baz-prometheus 10 | spec: 11 | resourcePolicy: 12 | containerPolicies: 13 | - containerName: prometheus 14 | controlledValues: RequestsAndLimits 15 | maxAllowed: 16 | cpu: "4" 17 | memory: "13743895347" 18 | minAllowed: 19 | cpu: 100m 20 | memory: "1073741824" 21 | mode: Auto 22 | targetRef: 23 | apiVersion: apps/v1 24 | kind: StatefulSet 25 | name: prometheus-baz 26 | updatePolicy: 27 | updateMode: Auto 28 | status: {} 29 | -------------------------------------------------------------------------------- /service/controller/resource/namespace/client.go: -------------------------------------------------------------------------------- 1 | package namespace 2 | 3 | import ( 4 | "context" 5 | 6 | corev1 "k8s.io/api/core/v1" 7 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 8 | v1 "k8s.io/client-go/kubernetes/typed/core/v1" 9 | ) 10 | 11 | type wrappedClient struct { 12 | client v1.NamespaceInterface 13 | } 14 | 15 | func (c wrappedClient) Create(ctx context.Context, o metav1.Object, options metav1.CreateOptions) (metav1.Object, error) { 16 | return c.client.Create(ctx, o.(*corev1.Namespace), options) 17 | } 18 | func (c wrappedClient) Update(ctx context.Context, o metav1.Object, options metav1.UpdateOptions) (metav1.Object, error) { 19 | return c.client.Update(ctx, o.(*corev1.Namespace), options) 20 | } 21 | func (c wrappedClient) Get(ctx context.Context, name string, options metav1.GetOptions) (metav1.Object, error) { 22 | return c.client.Get(ctx, name, options) 23 | } 24 | func (c wrappedClient) Delete(ctx context.Context, name string, options *metav1.DeleteOptions) error { 25 | return c.client.Delete(ctx, name, *options) 26 | } 27 | -------------------------------------------------------------------------------- /service/controller/resource/namespace/resource_test.go: -------------------------------------------------------------------------------- 1 | package namespace 2 | 3 | import ( 4 | "context" 5 | "flag" 6 | "path/filepath" 7 | "testing" 8 | 9 | "github.com/giantswarm/prometheus-meta-operator/v2/pkg/unittest" 10 | ) 11 | 12 | var update = flag.Bool("update", false, "update the output file") 13 | 14 | func TestNamespace(t *testing.T) { 15 | testFunc := func(v interface{}) (interface{}, error) { 16 | return toNamespace(context.Background(), v) 17 | } 18 | 19 | for _, flavor := range unittest.ProviderFlavors { 20 | outputDir, err := filepath.Abs("./test/" + flavor) 21 | if err != nil { 22 | t.Fatal(err) 23 | } 24 | 25 | c := unittest.Config{ 26 | Flavor: flavor, 27 | OutputDir: outputDir, 28 | T: t, 29 | TestFunc: testFunc, 30 | Update: *update, 31 | } 32 | runner, err := unittest.NewRunner(c) 33 | if err != nil { 34 | t.Fatal(err) 35 | } 36 | 37 | err = runner.Run() 38 | if err != nil { 39 | t.Fatal(err) 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /service/controller/resource/namespace/test/capi/case-1-capa-mc.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | creationTimestamp: null 5 | labels: 6 | app.kubernetes.io/instance: test-installation 7 | app.kubernetes.io/managed-by: prometheus-meta-operator 8 | app.kubernetes.io/name: prometheus 9 | giantswarm.io/cluster: test-installation 10 | name: test-installation-prometheus 11 | spec: {} 12 | status: {} 13 | -------------------------------------------------------------------------------- /service/controller/resource/namespace/test/capi/case-2-capa.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | creationTimestamp: null 5 | labels: 6 | app.kubernetes.io/instance: baz 7 | app.kubernetes.io/managed-by: prometheus-meta-operator 8 | app.kubernetes.io/name: prometheus 9 | giantswarm.io/cluster: baz 10 | name: baz-prometheus 11 | spec: {} 12 | status: {} 13 | -------------------------------------------------------------------------------- /service/controller/resource/namespace/test/capi/case-3-capz.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | creationTimestamp: null 5 | labels: 6 | app.kubernetes.io/instance: foo 7 | app.kubernetes.io/managed-by: prometheus-meta-operator 8 | app.kubernetes.io/name: prometheus 9 | giantswarm.io/cluster: foo 10 | name: foo-prometheus 11 | spec: {} 12 | status: {} 13 | -------------------------------------------------------------------------------- /service/controller/resource/namespace/test/capi/case-4-eks.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | creationTimestamp: null 5 | labels: 6 | app.kubernetes.io/instance: eks-sample 7 | app.kubernetes.io/managed-by: prometheus-meta-operator 8 | app.kubernetes.io/name: prometheus 9 | giantswarm.io/cluster: eks-sample 10 | name: eks-sample-prometheus 11 | spec: {} 12 | status: {} 13 | -------------------------------------------------------------------------------- /service/controller/resource/namespace/test/capi/case-5-gcp.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | creationTimestamp: null 5 | labels: 6 | app.kubernetes.io/instance: gcp-sample 7 | app.kubernetes.io/managed-by: prometheus-meta-operator 8 | app.kubernetes.io/name: prometheus 9 | giantswarm.io/cluster: gcp-sample 10 | name: gcp-sample-prometheus 11 | spec: {} 12 | status: {} 13 | -------------------------------------------------------------------------------- /service/controller/resource/namespace/test/vintage/case-1-vintage-mc.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | creationTimestamp: null 5 | labels: 6 | app.kubernetes.io/instance: kubernetes 7 | app.kubernetes.io/managed-by: prometheus-meta-operator 8 | app.kubernetes.io/name: prometheus 9 | giantswarm.io/cluster: kubernetes 10 | name: kubernetes-prometheus 11 | spec: {} 12 | status: {} 13 | -------------------------------------------------------------------------------- /service/controller/resource/namespace/test/vintage/case-2-aws-v16.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | creationTimestamp: null 5 | labels: 6 | app.kubernetes.io/instance: alice 7 | app.kubernetes.io/managed-by: prometheus-meta-operator 8 | app.kubernetes.io/name: prometheus 9 | giantswarm.io/cluster: alice 10 | name: alice-prometheus 11 | spec: {} 12 | status: {} 13 | -------------------------------------------------------------------------------- /service/controller/resource/namespace/test/vintage/case-3-aws-v18.golden: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | creationTimestamp: null 5 | labels: 6 | app.kubernetes.io/instance: baz 7 | app.kubernetes.io/managed-by: prometheus-meta-operator 8 | app.kubernetes.io/name: prometheus 9 | giantswarm.io/cluster: baz 10 | name: baz-prometheus 11 | spec: {} 12 | status: {} 13 | -------------------------------------------------------------------------------- /service/controller/resource/noop/noop.go: -------------------------------------------------------------------------------- 1 | package noop 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/micrologger" 7 | ) 8 | 9 | const ( 10 | Name = "noop" 11 | ) 12 | 13 | type Config struct { 14 | Logger micrologger.Logger 15 | } 16 | 17 | type Resource struct { 18 | logger micrologger.Logger 19 | } 20 | 21 | func New(config Config) *Resource { 22 | r := &Resource{ 23 | logger: config.Logger, 24 | } 25 | 26 | return r 27 | } 28 | 29 | func (r *Resource) Name() string { 30 | return Name 31 | } 32 | 33 | func (r *Resource) EnsureCreated(ctx context.Context, obj interface{}) error { 34 | r.logger.Debugf(ctx, "noop create") 35 | return nil 36 | } 37 | 38 | func (r *Resource) EnsureDeleted(ctx context.Context, obj interface{}) error { 39 | r.logger.Debugf(ctx, "noop delete") 40 | return nil 41 | } 42 | -------------------------------------------------------------------------------- /service/controller/resource/prometheusremotewrite/error.go: -------------------------------------------------------------------------------- 1 | package prometheusremotewrite 2 | 3 | import "github.com/giantswarm/microerror" 4 | 5 | var noSuchPrometheusForLabel = µerror.Error{ 6 | Kind: "noSuchPrometheusForLabel", 7 | } 8 | 9 | // IsNoSuchPrometheusForLabel asserts noSuchPrometheusForLabel. 10 | func IsNoSuchPrometheusForLabel(err error) bool { 11 | return microerror.Cause(err) == noSuchPrometheusForLabel 12 | } 13 | 14 | var wrongTypeError = µerror.Error{ 15 | Kind: "wrongTypeError", 16 | } 17 | 18 | // IsWrongType asserts wrongTypeError. 19 | func IsWrongType(err error) bool { 20 | return microerror.Cause(err) == wrongTypeError 21 | } 22 | -------------------------------------------------------------------------------- /service/controller/resource/rbac/create.go: -------------------------------------------------------------------------------- 1 | package rbac 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | 10 | "github.com/giantswarm/prometheus-meta-operator/v2/service/controller/resource/resourceutils" 11 | ) 12 | 13 | func (r *Resource) EnsureCreated(ctx context.Context, obj interface{}) error { 14 | if r.config.MimirEnabled { 15 | r.config.Logger.Debugf(ctx, "mimir is enabled, deleting heartbeat if it exists") 16 | return r.EnsureDeleted(ctx, obj) 17 | } 18 | r.config.Logger.Debugf(ctx, "creating") 19 | { 20 | desired, err := toClusterRoleBinding(obj) 21 | if err != nil { 22 | return microerror.Mask(err) 23 | } 24 | 25 | current, err := r.config.K8sClient.K8sClient().RbacV1().ClusterRoleBindings().Get(ctx, desired.GetName(), metav1.GetOptions{}) 26 | if apierrors.IsNotFound(err) { 27 | current, err = r.config.K8sClient.K8sClient().RbacV1().ClusterRoleBindings().Create(ctx, desired, metav1.CreateOptions{}) 28 | } 29 | if err != nil { 30 | return microerror.Mask(err) 31 | } 32 | 33 | if hasClusterRoleBindingChanged(current, desired) { 34 | resourceutils.UpdateMeta(current, desired) 35 | _, err = r.config.K8sClient.K8sClient().RbacV1().ClusterRoleBindings().Update(ctx, desired, metav1.UpdateOptions{}) 36 | if err != nil { 37 | return microerror.Mask(err) 38 | } 39 | } 40 | } 41 | r.config.Logger.Debugf(ctx, "created") 42 | 43 | return nil 44 | } 45 | -------------------------------------------------------------------------------- /service/controller/resource/rbac/delete.go: -------------------------------------------------------------------------------- 1 | package rbac 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/giantswarm/microerror" 7 | apierrors "k8s.io/apimachinery/pkg/api/errors" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | ) 10 | 11 | func (r *Resource) EnsureDeleted(ctx context.Context, obj interface{}) error { 12 | r.config.Logger.Debugf(ctx, "deleting") 13 | { 14 | desired, err := toClusterRoleBinding(obj) 15 | if err != nil { 16 | return microerror.Mask(err) 17 | } 18 | 19 | err = r.config.K8sClient.K8sClient().RbacV1().ClusterRoleBindings().Delete(ctx, desired.GetName(), metav1.DeleteOptions{}) 20 | if apierrors.IsNotFound(err) { 21 | // fall through 22 | } else if err != nil { 23 | return microerror.Mask(err) 24 | } 25 | } 26 | r.config.Logger.Debugf(ctx, "deleted") 27 | 28 | return nil 29 | } 30 | -------------------------------------------------------------------------------- /service/controller/resource/rbac/doc.go: -------------------------------------------------------------------------------- 1 | package rbac 2 | 3 | // Package prometheus contains functionnality for creating prometheus server. 4 | // 5 | // Prometheus server is setup via Prometheus CR which is reconciled 6 | // by prometheus-operator/prometheus-operator. 7 | -------------------------------------------------------------------------------- /service/controller/resource/rbac/error.go: -------------------------------------------------------------------------------- 1 | package rbac 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var invalidConfigError = µerror.Error{ 8 | Kind: "invalidConfigError", 9 | } 10 | 11 | // IsInvalidConfig asserts invalidConfigError. 12 | func IsInvalidConfig(err error) bool { 13 | return microerror.Cause(err) == invalidConfigError 14 | } 15 | 16 | var wrongTypeError = µerror.Error{ 17 | Kind: "wrongTypeError", 18 | } 19 | 20 | // IsWrongType asserts wrongTypeError. 21 | func IsWrongType(err error) bool { 22 | return microerror.Cause(err) == wrongTypeError 23 | } 24 | -------------------------------------------------------------------------------- /service/controller/resource/rbac/resource.go: -------------------------------------------------------------------------------- 1 | package rbac 2 | 3 | import ( 4 | "reflect" 5 | 6 | "github.com/giantswarm/k8sclient/v7/pkg/k8sclient" 7 | "github.com/giantswarm/microerror" 8 | "github.com/giantswarm/micrologger" 9 | v1 "k8s.io/api/rbac/v1" 10 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 11 | 12 | "github.com/giantswarm/prometheus-meta-operator/v2/service/key" 13 | ) 14 | 15 | const ( 16 | Name = "rbac" 17 | ) 18 | 19 | type Config struct { 20 | K8sClient k8sclient.Interface 21 | Logger micrologger.Logger 22 | MimirEnabled bool 23 | } 24 | 25 | type Resource struct { 26 | config Config 27 | } 28 | 29 | func New(config Config) (*Resource, error) { 30 | return &Resource{config}, nil 31 | } 32 | 33 | func (r *Resource) Name() string { 34 | return Name 35 | } 36 | 37 | func toClusterRoleBinding(v interface{}) (*v1.ClusterRoleBinding, error) { 38 | cluster, err := key.ToCluster(v) 39 | if err != nil { 40 | return nil, microerror.Mask(err) 41 | } 42 | 43 | clusterRoleBinding := &v1.ClusterRoleBinding{ 44 | ObjectMeta: metav1.ObjectMeta{ 45 | Name: key.Namespace(cluster), 46 | }, 47 | RoleRef: v1.RoleRef{ 48 | APIGroup: v1.SchemeGroupVersion.Group, 49 | Kind: "ClusterRole", 50 | Name: "prometheus", 51 | }, 52 | Subjects: []v1.Subject{ 53 | { 54 | Kind: "ServiceAccount", 55 | Name: "default", 56 | Namespace: key.Namespace(cluster), 57 | }, 58 | }, 59 | } 60 | 61 | return clusterRoleBinding, nil 62 | } 63 | 64 | func hasClusterRoleBindingChanged(current, desired *v1.ClusterRoleBinding) bool { 65 | return !reflect.DeepEqual(current.RoleRef, desired.RoleRef) || !reflect.DeepEqual(current.Subjects, desired.Subjects) 66 | } 67 | -------------------------------------------------------------------------------- /service/controller/resource/remotewritesecret/error.go: -------------------------------------------------------------------------------- 1 | package remotewritesecret 2 | -------------------------------------------------------------------------------- /service/controller/resource/resourceutils/utils.go: -------------------------------------------------------------------------------- 1 | package resourceutils 2 | 3 | import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 4 | 5 | func UpdateMeta(c, d metav1.Object) { 6 | d.SetGenerateName(c.GetGenerateName()) 7 | d.SetUID(c.GetUID()) 8 | d.SetResourceVersion(c.GetResourceVersion()) 9 | d.SetGeneration(c.GetGeneration()) 10 | d.SetSelfLink(c.GetSelfLink()) 11 | d.SetCreationTimestamp(c.GetCreationTimestamp()) 12 | d.SetDeletionTimestamp(c.GetDeletionTimestamp()) 13 | d.SetDeletionGracePeriodSeconds(c.GetDeletionGracePeriodSeconds()) 14 | // without this, it's impossible to change labels on resources 15 | if len(d.GetLabels()) == 0 { 16 | d.SetLabels(c.GetLabels()) 17 | } 18 | // without this, it's impossible to change annotations on resources 19 | if len(d.GetAnnotations()) == 0 { 20 | d.SetAnnotations(c.GetAnnotations()) 21 | } 22 | d.SetFinalizers(c.GetFinalizers()) 23 | d.SetOwnerReferences(c.GetOwnerReferences()) 24 | d.SetManagedFields(c.GetManagedFields()) 25 | } 26 | -------------------------------------------------------------------------------- /service/controller/resource/wrapper/monitoringdisabledresource/error.go: -------------------------------------------------------------------------------- 1 | package monitoringdisabledresource 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var invalidConfigError = µerror.Error{ 8 | Kind: "invalidConfigError", 9 | } 10 | 11 | // IsInvalidConfig asserts invalidConfigError. 12 | func IsInvalidConfig(err error) bool { 13 | return microerror.Cause(err) == invalidConfigError 14 | } 15 | -------------------------------------------------------------------------------- /service/controller/resource/wrapper/monitoringdisabledresource/wrap.go: -------------------------------------------------------------------------------- 1 | package monitoringdisabledresource 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | "github.com/giantswarm/micrologger" 6 | 7 | "github.com/giantswarm/operatorkit/v7/pkg/resource" 8 | ) 9 | 10 | // WrapConfig is the configuration used to wrap resources with disabled monitoring resource. 11 | type WrapConfig struct { 12 | Logger micrologger.Logger 13 | } 14 | 15 | // Wrap wraps each given resource with a disabled monitoring resource and returns the list of 16 | // wrapped resources. 17 | func Wrap(resources []resource.Interface, config WrapConfig) ([]resource.Interface, error) { 18 | var wrapped []resource.Interface 19 | 20 | for _, r := range resources { 21 | c := Config{ 22 | Resource: r, 23 | Logger: config.Logger, 24 | } 25 | 26 | monitoringDisabledResource, err := New(c) 27 | if err != nil { 28 | return nil, microerror.Mask(err) 29 | } 30 | 31 | wrapped = append(wrapped, monitoringDisabledResource) 32 | } 33 | 34 | return wrapped, nil 35 | } 36 | -------------------------------------------------------------------------------- /service/error.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var invalidConfigError = µerror.Error{ 8 | Kind: "invalidConfigError", 9 | } 10 | 11 | // IsInvalidConfig asserts invalidConfigError. 12 | func IsInvalidConfig(err error) bool { 13 | return microerror.Cause(err) == invalidConfigError 14 | } 15 | -------------------------------------------------------------------------------- /service/key/error.go: -------------------------------------------------------------------------------- 1 | package key 2 | 3 | import ( 4 | "github.com/giantswarm/microerror" 5 | ) 6 | 7 | var wrongTypeError = µerror.Error{ 8 | Kind: "wrongTypeError", 9 | } 10 | 11 | // IsWrongType asserts wrongTypeError. 12 | func IsWrongType(err error) bool { 13 | return microerror.Cause(err) == wrongTypeError 14 | } 15 | 16 | var infrastructureRefNotFoundError = µerror.Error{ 17 | Kind: "infrastructureRefNotFoundError", 18 | } 19 | 20 | // IsInvalidConfig asserts invalidConfigError. 21 | func IsInfrastructureRefNotFoundError(err error) bool { 22 | return microerror.Cause(err) == infrastructureRefNotFoundError 23 | } 24 | --------------------------------------------------------------------------------