mirror of
https://github.com/holos-run/holos.git
synced 2026-03-19 08:44:58 +00:00
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30b70e76aa | ||
|
|
ec6d112711 | ||
|
|
e796c6a763 | ||
|
|
be32201294 | ||
|
|
5ebc54b5b7 | ||
|
|
2954a57872 | ||
|
|
df705bd79f | ||
|
|
4e8ce3585d | ||
|
|
ab5f17c3d2 | ||
|
|
a8918c74d4 | ||
|
|
ae5738d82d | ||
|
|
bb99aedffa | ||
|
|
d6ee1864c8 | ||
|
|
8a4be66277 | ||
|
|
79ce2f8458 | ||
|
|
3d4ae44ddd | ||
|
|
1efb1faa40 | ||
|
|
bfd6a56397 | ||
|
|
a788f6d8e8 | ||
|
|
80fa91d74d | ||
|
|
db34562e9a | ||
|
|
d6af089ab3 | ||
|
|
b3a70c5911 | ||
|
|
bf5765c9cb | ||
|
|
6c7697648c | ||
|
|
04158485c7 | ||
|
|
cf83c77280 | ||
|
|
6e545b13dd | ||
|
|
bf258a1f41 | ||
|
|
6f06c73d6f |
26
.github/workflows/lint.yaml
vendored
26
.github/workflows/lint.yaml
vendored
@@ -17,11 +17,31 @@ jobs:
|
||||
name: lint
|
||||
runs-on: gha-rs
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: stable
|
||||
cache: false
|
||||
|
||||
- name: Install Packages
|
||||
run: sudo apt update && sudo apt -qq -y install git curl zip unzip tar bzip2 make
|
||||
|
||||
- name: Install Tools
|
||||
run: |
|
||||
set -x
|
||||
make tools
|
||||
make buf
|
||||
go generate ./...
|
||||
make frontend
|
||||
go mod tidy
|
||||
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v4
|
||||
with:
|
||||
|
||||
33
.github/workflows/release.yaml
vendored
33
.github/workflows/release.yaml
vendored
@@ -14,23 +14,46 @@ jobs:
|
||||
goreleaser:
|
||||
runs-on: gha-rs
|
||||
steps:
|
||||
# Must come before Checkout, otherwise goreleaser fails
|
||||
- name: Provide GPG and Git
|
||||
run: sudo apt update && sudo apt -qq -y install gnupg git
|
||||
run: sudo apt update && sudo apt -qq -y install gnupg git curl zip unzip tar bzip2 make
|
||||
|
||||
# Must come after git executable is provided
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: stable
|
||||
|
||||
# Necessary to run these outside of goreleaser, otherwise
|
||||
# /home/runner/_work/holos/holos/internal/frontend/node_modules/.bin/protoc-gen-connect-query is not in PATH
|
||||
- name: Install Tools
|
||||
run: |
|
||||
set -x
|
||||
make tools
|
||||
make buf
|
||||
go generate ./...
|
||||
make frontend
|
||||
go mod tidy
|
||||
|
||||
- name: Import GPG key
|
||||
uses: crazy-max/ghaction-import-gpg@v6
|
||||
with:
|
||||
gpg_private_key: ${{ secrets.GPG_CODE_SIGNING_SECRETKEY }}
|
||||
passphrase: ${{ secrets.GPG_CODE_SIGNING_PASSPHRASE }}
|
||||
|
||||
- name: List keys
|
||||
run: gpg -K
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: stable
|
||||
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v5
|
||||
with:
|
||||
|
||||
18
.github/workflows/test.yaml
vendored
18
.github/workflows/test.yaml
vendored
@@ -18,13 +18,18 @@ jobs:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: stable
|
||||
|
||||
- name: Provide unzip for Helm
|
||||
run: sudo apt update && sudo apt -qq -y install curl zip unzip tar bzip2
|
||||
- name: Install Packages
|
||||
run: sudo apt update && sudo apt -qq -y install git curl zip unzip tar bzip2 make
|
||||
|
||||
- name: Set up Helm
|
||||
uses: azure/setup-helm@v4
|
||||
@@ -32,5 +37,14 @@ jobs:
|
||||
- name: Set up Kubectl
|
||||
uses: azure/setup-kubectl@v3
|
||||
|
||||
- name: Install Tools
|
||||
run: |
|
||||
set -x
|
||||
make tools
|
||||
make buf
|
||||
go generate ./...
|
||||
make frontend
|
||||
go mod tidy
|
||||
|
||||
- name: Test
|
||||
run: ./scripts/test
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,8 +1,8 @@
|
||||
bin/
|
||||
/bin/
|
||||
vendor/
|
||||
.idea/
|
||||
coverage.out
|
||||
dist/
|
||||
/dist/
|
||||
*.hold/
|
||||
/deploy/
|
||||
.vscode/
|
||||
|
||||
@@ -10,10 +10,8 @@ version: 1
|
||||
|
||||
before:
|
||||
hooks:
|
||||
# You may remove this if you don't use go modules.
|
||||
- go mod tidy
|
||||
# you may remove this if you don't need go generate
|
||||
- go generate ./...
|
||||
- go mod tidy
|
||||
|
||||
builds:
|
||||
- main: ./cmd/holos
|
||||
@@ -23,6 +21,9 @@ builds:
|
||||
- linux
|
||||
- windows
|
||||
- darwin
|
||||
goarch:
|
||||
- amd64
|
||||
- arm64
|
||||
|
||||
signs:
|
||||
- artifacts: checksum
|
||||
|
||||
37
Makefile
37
Makefile
@@ -12,6 +12,9 @@ IMAGE_NAME=$(DOCKER_REPO)
|
||||
|
||||
$( shell mkdir -p bin)
|
||||
|
||||
# For buf plugin protoc-gen-connect-es
|
||||
export PATH := $(PWD)/internal/frontend/holos/node_modules/.bin:$(PATH)
|
||||
|
||||
GIT_COMMIT=$(shell git rev-parse HEAD)
|
||||
GIT_TREE_STATE=$(shell test -n "`git status --porcelain`" && echo "dirty" || echo "clean")
|
||||
BUILD_DATE=$(shell date -Iseconds)
|
||||
@@ -94,6 +97,40 @@ coverage: test ## Test coverage profile.
|
||||
snapshot: ## Go release snapshot
|
||||
goreleaser release --snapshot --clean
|
||||
|
||||
.PHONY: buf
|
||||
buf: ## buf generate
|
||||
cd service && buf mod update
|
||||
buf generate
|
||||
|
||||
.PHONY: tools
|
||||
tools: go-deps frontend-deps ## install tool dependencies
|
||||
|
||||
.PHONY: go-deps
|
||||
go-deps: ## tool versions pinned in tools.go
|
||||
go install github.com/bufbuild/buf/cmd/buf
|
||||
go install github.com/fullstorydev/grpcurl/cmd/grpcurl
|
||||
go install google.golang.org/protobuf/cmd/protoc-gen-go
|
||||
go install connectrpc.com/connect/cmd/protoc-gen-connect-go
|
||||
go install honnef.co/go/tools/cmd/staticcheck@latest
|
||||
# curl https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash
|
||||
|
||||
.PHONY: frontend-deps
|
||||
frontend-deps: ## Setup npm and vite
|
||||
cd internal/frontend/holos && npm install
|
||||
cd internal/frontend/holos && npm install --save-dev @bufbuild/buf @connectrpc/protoc-gen-connect-es
|
||||
cd internal/frontend/holos && npm install @connectrpc/connect @connectrpc/connect-web @bufbuild/protobuf
|
||||
# https://github.com/connectrpc/connect-query-es/blob/1350b6f07b6aead81793917954bdb1cc3ce09df9/packages/protoc-gen-connect-query/README.md?plain=1#L23
|
||||
cd internal/frontend/holos && npm install --save-dev @connectrpc/protoc-gen-connect-query @bufbuild/protoc-gen-es
|
||||
cd internal/frontend/holos && npm install @connectrpc/connect-query @bufbuild/protobuf
|
||||
|
||||
|
||||
.PHONY: frontend
|
||||
frontend: buf
|
||||
mkdir -p internal/frontend/holos/dist
|
||||
cd internal/frontend/holos/dist && rm -rf app
|
||||
cd internal/frontend/holos && ng build
|
||||
touch internal/frontend/frontend.go
|
||||
|
||||
.PHONY: help
|
||||
help: ## Display this help menu.
|
||||
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\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)
|
||||
|
||||
315
Tiltfile
Normal file
315
Tiltfile
Normal file
@@ -0,0 +1,315 @@
|
||||
# -*- mode: Python -*-
|
||||
# This Tiltfile manages a Go project with live leload in Kubernetes
|
||||
|
||||
listen_port = 3000
|
||||
metrics_port = 9090
|
||||
|
||||
# Use our wrapper to set the kube namespace
|
||||
if os.getenv('TILT_WRAPPER') != '1':
|
||||
fail("could not run, ./hack/tilt/bin/tilt was not used to start tilt")
|
||||
|
||||
# AWS Account to work in
|
||||
aws_account = '271053619184'
|
||||
aws_region = 'us-east-2'
|
||||
|
||||
# Resource ids
|
||||
holos_backend = 'Holos Backend'
|
||||
pg_admin = 'pgAdmin'
|
||||
pg_cluster = 'PostgresCluster'
|
||||
pg_svc = 'Database Pod'
|
||||
compile_id = 'Go Build'
|
||||
auth_id = 'Auth Policy'
|
||||
lint_id = 'Run Linters'
|
||||
tests_id = 'Run Tests'
|
||||
|
||||
# PostgresCluster resource name in k8s
|
||||
pg_cluster_name = 'holos'
|
||||
# Database name inside the PostgresCluster
|
||||
pg_database_name = 'holos'
|
||||
# PGAdmin name
|
||||
pg_admin_name = 'pgadmin'
|
||||
|
||||
# Default Registry.
|
||||
# See: https://github.com/tilt-dev/tilt.build/blob/master/docs/choosing_clusters.md#manual-configuration
|
||||
# Note, Tilt will append the image name to the registry uri path
|
||||
default_registry('{account}.dkr.ecr.{region}.amazonaws.com/holos-run/holos-server'.format(account=aws_account, region=aws_region))
|
||||
|
||||
# Set a name prefix specific to the user. Multiple developers share the tilt-holos namespace.
|
||||
developer = os.getenv('USER')
|
||||
holos_server = 'holos'
|
||||
# See ./hack/tilt/bin/tilt
|
||||
namespace = os.getenv('NAMESPACE')
|
||||
# We always develop against the k1 cluster.
|
||||
os.putenv('KUBECONFIG', os.path.abspath('./hack/tilt/kubeconfig'))
|
||||
# The context defined in ./hack/tilt/kubeconfig
|
||||
allow_k8s_contexts('sso@k1')
|
||||
allow_k8s_contexts('sso@k2')
|
||||
allow_k8s_contexts('sso@k3')
|
||||
allow_k8s_contexts('sso@k4')
|
||||
allow_k8s_contexts('sso@k5')
|
||||
# PG db connection for localhost -> k8s port-forward
|
||||
os.putenv('PGHOST', 'localhost')
|
||||
os.putenv('PGPORT', '15432')
|
||||
# We always develop in the dev aws account.
|
||||
os.putenv('AWS_CONFIG_FILE', os.path.abspath('./hack/tilt/aws.config'))
|
||||
os.putenv('AWS_ACCOUNT', aws_account)
|
||||
os.putenv('AWS_DEFAULT_REGION', aws_region)
|
||||
os.putenv('AWS_PROFILE', 'dev-holos')
|
||||
os.putenv('AWS_SDK_LOAD_CONFIG', '1')
|
||||
# Authenticate to AWS ECR when tilt up is run by the developer
|
||||
local_resource('AWS Credentials', './hack/tilt/aws-login.sh', auto_init=True)
|
||||
|
||||
# Extensions are open-source, pre-packaged functions that extend Tilt
|
||||
#
|
||||
# More info: https://github.com/tilt-dev/tilt-extensions
|
||||
# More info: https://docs.tilt.dev/extensions.html
|
||||
load('ext://restart_process', 'docker_build_with_restart')
|
||||
load('ext://k8s_attach', 'k8s_attach')
|
||||
load('ext://git_resource', 'git_checkout')
|
||||
load('ext://uibutton', 'cmd_button')
|
||||
|
||||
# Paths edited by the developer Tilt watches to trigger compilation.
|
||||
# Generated files should be excluded to avoid an infinite build loop.
|
||||
developer_paths = [
|
||||
'./cmd',
|
||||
'./internal/server',
|
||||
'./internal/ent/schema',
|
||||
'./frontend/package-lock.json',
|
||||
'./frontend/src',
|
||||
'./go.mod',
|
||||
'./pkg',
|
||||
'./service/holos',
|
||||
]
|
||||
|
||||
# Builds the holos-server executable
|
||||
local_resource(compile_id, 'make build', deps=developer_paths)
|
||||
|
||||
# Build Docker image
|
||||
# Tilt will automatically associate image builds with the resource(s)
|
||||
# that reference them (e.g. via Kubernetes or Docker Compose YAML).
|
||||
#
|
||||
# More info: https://docs.tilt.dev/api.html#api.docker_build
|
||||
#
|
||||
docker_build_with_restart(
|
||||
'holos',
|
||||
context='.',
|
||||
entrypoint=[
|
||||
'/app/bin/holos',
|
||||
'server',
|
||||
'--listen-port={}'.format(listen_port),
|
||||
'--oidc-issuer=https://login.ois.run',
|
||||
'--oidc-audience=262096764402729854@holos_platform',
|
||||
'--metrics-port={}'.format(metrics_port),
|
||||
],
|
||||
dockerfile='./hack/tilt/Dockerfile',
|
||||
only=['./bin'],
|
||||
# (Recommended) Updating a running container in-place
|
||||
# https://docs.tilt.dev/live_update_reference.html
|
||||
live_update=[
|
||||
# Sync files from host to container
|
||||
sync('./bin', '/app/bin'),
|
||||
# Wait for aws-login https://github.com/tilt-dev/tilt/issues/3048
|
||||
sync('./tilt/aws-login.last', '/dev/null'),
|
||||
# Execute commands in the container when paths change
|
||||
# run('/app/hack/codegen.sh', trigger=['./app/api'])
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
# Run local commands
|
||||
# Local commands can be helpful for one-time tasks like installing
|
||||
# project prerequisites. They can also manage long-lived processes
|
||||
# for non-containerized services or dependencies.
|
||||
#
|
||||
# More info: https://docs.tilt.dev/local_resource.html
|
||||
#
|
||||
# local_resource('install-helm',
|
||||
# cmd='which helm > /dev/null || brew install helm',
|
||||
# # `cmd_bat`, when present, is used instead of `cmd` on Windows.
|
||||
# cmd_bat=[
|
||||
# 'powershell.exe',
|
||||
# '-Noninteractive',
|
||||
# '-Command',
|
||||
# '& {if (!(Get-Command helm -ErrorAction SilentlyContinue)) {scoop install helm}}'
|
||||
# ]
|
||||
# )
|
||||
|
||||
# Teach tilt about our custom resources (Note, this may be intended for workloads)
|
||||
# k8s_kind('authorizationpolicy')
|
||||
# k8s_kind('requestauthentication')
|
||||
# k8s_kind('virtualservice')
|
||||
k8s_kind('pgadmin')
|
||||
|
||||
|
||||
# Troubleshooting
|
||||
def resource_name(id):
|
||||
print('resource: {}'.format(id))
|
||||
return id.name
|
||||
|
||||
|
||||
workload_to_resource_function(resource_name)
|
||||
|
||||
# Apply Kubernetes manifests
|
||||
# Tilt will build & push any necessary images, re-deploying your
|
||||
# resources as they change.
|
||||
#
|
||||
# More info: https://docs.tilt.dev/api.html#api.k8s_yaml
|
||||
#
|
||||
|
||||
def holos_yaml():
|
||||
"""Return a k8s Deployment personalized for the developer."""
|
||||
k8s_yaml_template = str(read_file('./hack/tilt/k8s.yaml'))
|
||||
return k8s_yaml_template.format(
|
||||
name=holos_server,
|
||||
developer=developer,
|
||||
namespace=namespace,
|
||||
listen_port=listen_port,
|
||||
metrics_port=metrics_port,
|
||||
tz=os.getenv('TZ'),
|
||||
)
|
||||
|
||||
# Customize a Kubernetes resource
|
||||
# By default, Kubernetes resource names are automatically assigned
|
||||
# based on objects in the YAML manifests, e.g. Deployment name.
|
||||
#
|
||||
# Tilt strives for sane defaults, so calling k8s_resource is
|
||||
# optional, and you only need to pass the arguments you want to
|
||||
# override.
|
||||
#
|
||||
# More info: https://docs.tilt.dev/api.html#api.k8s_resource
|
||||
#
|
||||
k8s_yaml(blob(holos_yaml()))
|
||||
|
||||
# Backend server process
|
||||
k8s_resource(
|
||||
workload=holos_server,
|
||||
new_name=holos_backend,
|
||||
objects=[
|
||||
'{}:serviceaccount'.format(holos_server),
|
||||
'{}:servicemonitor'.format(holos_server),
|
||||
],
|
||||
resource_deps=[compile_id],
|
||||
links=[
|
||||
link('https://{}.holos.dev.k2.ois.run/app/'.format(developer), "Holos Web UI")
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
# AuthorizationPolicy - Beyond Corp functionality
|
||||
k8s_resource(
|
||||
new_name=auth_id,
|
||||
objects=[
|
||||
'{}:virtualservice'.format(holos_server),
|
||||
'{}-allow-groups:authorizationpolicy'.format(holos_server),
|
||||
'{}-allow-nothing:authorizationpolicy'.format(holos_server),
|
||||
'{}-allow-well-known-paths:authorizationpolicy'.format(holos_server),
|
||||
'{}-auth:authorizationpolicy'.format(holos_server),
|
||||
'{}:requestauthentication'.format(holos_server),
|
||||
],
|
||||
)
|
||||
|
||||
# Database
|
||||
# Note: Tilt confuses the backup pods with the database server pods, so this code is careful to tease the pods
|
||||
# apart so logs are streamed correctly.
|
||||
# See: https://github.com/tilt-dev/tilt.specs/blob/master/resource_assembly.md
|
||||
|
||||
# pgAdmin Web UI
|
||||
k8s_resource(
|
||||
workload=pg_admin_name,
|
||||
new_name=pg_admin,
|
||||
port_forwards=[
|
||||
port_forward(15050, 5050, pg_admin),
|
||||
],
|
||||
)
|
||||
|
||||
# Disabled because these don't group resources nicely
|
||||
# k8s_kind('postgrescluster')
|
||||
|
||||
# Postgres database in-cluster
|
||||
k8s_resource(
|
||||
new_name=pg_cluster,
|
||||
objects=['holos:postgrescluster'],
|
||||
)
|
||||
|
||||
# Needed to select the database by label
|
||||
# https://docs.tilt.dev/api.html#api.k8s_custom_deploy
|
||||
k8s_custom_deploy(
|
||||
pg_svc,
|
||||
apply_cmd=['./hack/tilt/k8s-get-db-sts', pg_cluster_name],
|
||||
delete_cmd=['echo', 'Skipping delete. Object managed by custom resource.'],
|
||||
deps=[],
|
||||
)
|
||||
k8s_resource(
|
||||
pg_svc,
|
||||
port_forwards=[
|
||||
port_forward(15432, 5432, 'psql'),
|
||||
],
|
||||
resource_deps=[pg_cluster]
|
||||
)
|
||||
|
||||
|
||||
# Run tests
|
||||
local_resource(
|
||||
tests_id,
|
||||
'make test',
|
||||
allow_parallel=True,
|
||||
auto_init=False,
|
||||
deps=developer_paths,
|
||||
)
|
||||
|
||||
# Run linter
|
||||
local_resource(
|
||||
lint_id,
|
||||
'make lint',
|
||||
allow_parallel=True,
|
||||
auto_init=False,
|
||||
deps=developer_paths,
|
||||
)
|
||||
|
||||
# UI Buttons for helpful things.
|
||||
# Icons: https://fonts.google.com/icons
|
||||
os.putenv("GH_FORCE_TTY", "80%")
|
||||
cmd_button(
|
||||
'{}:go-test-failfast'.format(tests_id),
|
||||
argv=['./hack/tilt/go-test-failfast'],
|
||||
resource=tests_id,
|
||||
icon_name='quiz',
|
||||
text='Fail Fast',
|
||||
)
|
||||
cmd_button(
|
||||
'{}:issues'.format(holos_server),
|
||||
argv=['./hack/tilt/gh-issues'],
|
||||
resource=holos_backend,
|
||||
icon_name='folder_data',
|
||||
text='Issues',
|
||||
)
|
||||
cmd_button(
|
||||
'{}:gh-issue-view'.format(holos_server),
|
||||
argv=['./hack/tilt/gh-issue-view'],
|
||||
resource=holos_backend,
|
||||
icon_name='task',
|
||||
text='View Issue',
|
||||
)
|
||||
cmd_button(
|
||||
'{}:get-pgdb-creds'.format(holos_server),
|
||||
argv=['./hack/tilt/get-pgdb-creds', pg_cluster_name, pg_database_name],
|
||||
resource=pg_svc,
|
||||
icon_name='lock_open_right',
|
||||
text='DB Creds',
|
||||
)
|
||||
cmd_button(
|
||||
'{}:get-pgdb-creds'.format(pg_admin_name),
|
||||
argv=['./hack/tilt/get-pgdb-creds', pg_cluster_name, pg_database_name],
|
||||
resource=pg_admin,
|
||||
icon_name='lock_open_right',
|
||||
text='DB Creds',
|
||||
)
|
||||
cmd_button(
|
||||
'{}:get-pgadmin-creds'.format(pg_admin_name),
|
||||
argv=['./hack/tilt/get-pgadmin-creds', pg_admin_name],
|
||||
resource=pg_admin,
|
||||
icon_name='lock_open_right',
|
||||
text='pgAdmin Login',
|
||||
)
|
||||
|
||||
print("✨ Tiltfile evaluated")
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/holos-run/holos"
|
||||
"github.com/holos-run/holos/pkg/errors"
|
||||
"github.com/holos-run/holos/pkg/logger"
|
||||
"github.com/holos-run/holos/pkg/util"
|
||||
"github.com/holos-run/holos/pkg/wrapper"
|
||||
)
|
||||
|
||||
// A HelmChart represents a helm command to provide chart values in order to render kubernetes api objects.
|
||||
@@ -42,7 +42,7 @@ func (hc *HelmChart) Render(ctx context.Context, path holos.InstancePath) (*Resu
|
||||
}
|
||||
result.addObjectMap(ctx, hc.APIObjectMap)
|
||||
if err := result.kustomize(ctx); err != nil {
|
||||
return nil, wrapper.Wrap(fmt.Errorf("could not kustomize: %w", err))
|
||||
return nil, errors.Wrap(fmt.Errorf("could not kustomize: %w", err))
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
@@ -64,13 +64,13 @@ func (hc *HelmChart) helm(ctx context.Context, r *Result, path holos.InstancePat
|
||||
out, err := util.RunCmd(ctx, "helm", "repo", "add", repo.Name, repo.URL)
|
||||
if err != nil {
|
||||
log.ErrorContext(ctx, "could not run helm", "stderr", out.Stderr.String(), "stdout", out.Stdout.String())
|
||||
return wrapper.Wrap(fmt.Errorf("could not run helm repo add: %w", err))
|
||||
return errors.Wrap(fmt.Errorf("could not run helm repo add: %w", err))
|
||||
}
|
||||
// Update repository
|
||||
out, err = util.RunCmd(ctx, "helm", "repo", "update", repo.Name)
|
||||
if err != nil {
|
||||
log.ErrorContext(ctx, "could not run helm", "stderr", out.Stderr.String(), "stdout", out.Stdout.String())
|
||||
return wrapper.Wrap(fmt.Errorf("could not run helm repo update: %w", err))
|
||||
return errors.Wrap(fmt.Errorf("could not run helm repo update: %w", err))
|
||||
}
|
||||
} else {
|
||||
log.DebugContext(ctx, "no chart repository url proceeding assuming oci chart")
|
||||
@@ -85,13 +85,13 @@ func (hc *HelmChart) helm(ctx context.Context, r *Result, path holos.InstancePat
|
||||
// Write values file
|
||||
tempDir, err := os.MkdirTemp("", "holos")
|
||||
if err != nil {
|
||||
return wrapper.Wrap(fmt.Errorf("could not make temp dir: %w", err))
|
||||
return errors.Wrap(fmt.Errorf("could not make temp dir: %w", err))
|
||||
}
|
||||
defer util.Remove(ctx, tempDir)
|
||||
|
||||
valuesPath := filepath.Join(tempDir, "values.yaml")
|
||||
if err := os.WriteFile(valuesPath, []byte(hc.ValuesContent), 0644); err != nil {
|
||||
return wrapper.Wrap(fmt.Errorf("could not write values: %w", err))
|
||||
return errors.Wrap(fmt.Errorf("could not write values: %w", err))
|
||||
}
|
||||
log.DebugContext(ctx, "helm: wrote values", "path", valuesPath, "bytes", len(hc.ValuesContent))
|
||||
|
||||
@@ -112,7 +112,7 @@ func (hc *HelmChart) helm(ctx context.Context, r *Result, path holos.InstancePat
|
||||
err = fmt.Errorf("%s: %w", line, err)
|
||||
}
|
||||
}
|
||||
return wrapper.Wrap(fmt.Errorf("could not run helm template: %w", err))
|
||||
return errors.Wrap(fmt.Errorf("could not run helm template: %w", err))
|
||||
}
|
||||
|
||||
r.accumulatedOutput = helmOut.Stdout.String()
|
||||
@@ -126,7 +126,7 @@ func cacheChart(ctx context.Context, path holos.InstancePath, chartDir string, c
|
||||
|
||||
cacheTemp, err := os.MkdirTemp(string(path), chartDir)
|
||||
if err != nil {
|
||||
return wrapper.Wrap(fmt.Errorf("could not make temp dir: %w", err))
|
||||
return errors.Wrap(fmt.Errorf("could not make temp dir: %w", err))
|
||||
}
|
||||
defer util.Remove(ctx, cacheTemp)
|
||||
|
||||
@@ -136,14 +136,30 @@ func cacheChart(ctx context.Context, path holos.InstancePath, chartDir string, c
|
||||
}
|
||||
helmOut, err := util.RunCmd(ctx, "helm", "pull", "--destination", cacheTemp, "--untar=true", "--version", chart.Version, chartName)
|
||||
if err != nil {
|
||||
return wrapper.Wrap(fmt.Errorf("could not run helm pull: %w", err))
|
||||
return errors.Wrap(fmt.Errorf("could not run helm pull: %w", err))
|
||||
}
|
||||
log.Debug("helm pull", "stdout", helmOut.Stdout, "stderr", helmOut.Stderr)
|
||||
|
||||
cachePath := filepath.Join(string(path), chartDir)
|
||||
if err := os.Rename(cacheTemp, cachePath); err != nil {
|
||||
return wrapper.Wrap(fmt.Errorf("could not rename: %w", err))
|
||||
|
||||
if err := os.MkdirAll(cachePath, 0777); err != nil {
|
||||
return errors.Wrap(fmt.Errorf("could not mkdir: %w", err))
|
||||
}
|
||||
|
||||
items, err := os.ReadDir(cacheTemp)
|
||||
if err != nil {
|
||||
return errors.Wrap(fmt.Errorf("could not read directory: %w", err))
|
||||
}
|
||||
|
||||
for _, item := range items {
|
||||
src := filepath.Join(cacheTemp, item.Name())
|
||||
dst := filepath.Join(cachePath, item.Name())
|
||||
log.DebugContext(ctx, "rename", "src", src, "dst", dst)
|
||||
if err := os.Rename(src, dst); err != nil {
|
||||
return errors.Wrap(fmt.Errorf("could not rename: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
log.InfoContext(ctx, "cached", "chart", chart.Name, "version", chart.Version, "path", cachePath)
|
||||
|
||||
return nil
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/holos-run/holos"
|
||||
"github.com/holos-run/holos/pkg/errors"
|
||||
"github.com/holos-run/holos/pkg/logger"
|
||||
"github.com/holos-run/holos/pkg/util"
|
||||
"github.com/holos-run/holos/pkg/wrapper"
|
||||
)
|
||||
|
||||
const KustomizeBuildKind = "KustomizeBuild"
|
||||
@@ -37,7 +37,7 @@ func (kb *KustomizeBuild) Render(ctx context.Context, path holos.InstancePath) (
|
||||
kOut, err := util.RunCmd(ctx, "kubectl", "kustomize", string(path))
|
||||
if err != nil {
|
||||
log.ErrorContext(ctx, kOut.Stderr.String())
|
||||
return nil, wrapper.Wrap(err)
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
// Replace the accumulated output
|
||||
result.accumulatedOutput = kOut.Stdout.String()
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"path/filepath"
|
||||
"slices"
|
||||
|
||||
"github.com/holos-run/holos/pkg/errors"
|
||||
"github.com/holos-run/holos/pkg/logger"
|
||||
"github.com/holos-run/holos/pkg/util"
|
||||
"github.com/holos-run/holos/pkg/wrapper"
|
||||
)
|
||||
|
||||
// Result is the build result for display or writing. Holos components Render the Result as a data pipeline.
|
||||
@@ -82,7 +82,7 @@ func (r *Result) kustomize(ctx context.Context) error {
|
||||
}
|
||||
tempDir, err := os.MkdirTemp("", "holos.kustomize")
|
||||
if err != nil {
|
||||
return wrapper.Wrap(err)
|
||||
return errors.Wrap(err)
|
||||
}
|
||||
defer util.Remove(ctx, tempDir)
|
||||
|
||||
@@ -91,7 +91,7 @@ func (r *Result) kustomize(ctx context.Context) error {
|
||||
b := []byte(r.AccumulatedOutput())
|
||||
b = util.EnsureNewline(b)
|
||||
if err := os.WriteFile(target, b, 0644); err != nil {
|
||||
return wrapper.Wrap(fmt.Errorf("could not write resources: %w", err))
|
||||
return errors.Wrap(fmt.Errorf("could not write resources: %w", err))
|
||||
}
|
||||
log.DebugContext(ctx, "wrote: "+target, "op", "write", "path", target, "bytes", len(b))
|
||||
|
||||
@@ -99,12 +99,12 @@ func (r *Result) kustomize(ctx context.Context) error {
|
||||
for file, content := range r.KustomizeFiles {
|
||||
target := filepath.Join(tempDir, file)
|
||||
if err := os.MkdirAll(filepath.Dir(target), 0755); err != nil {
|
||||
return wrapper.Wrap(err)
|
||||
return errors.Wrap(err)
|
||||
}
|
||||
b := []byte(content)
|
||||
b = util.EnsureNewline(b)
|
||||
if err := os.WriteFile(target, b, 0644); err != nil {
|
||||
return wrapper.Wrap(fmt.Errorf("could not write: %w", err))
|
||||
return errors.Wrap(fmt.Errorf("could not write: %w", err))
|
||||
}
|
||||
log.DebugContext(ctx, "wrote: "+target, "op", "write", "path", target, "bytes", len(b))
|
||||
}
|
||||
@@ -113,7 +113,7 @@ func (r *Result) kustomize(ctx context.Context) error {
|
||||
kOut, err := util.RunCmd(ctx, "kubectl", "kustomize", tempDir)
|
||||
if err != nil {
|
||||
log.ErrorContext(ctx, kOut.Stderr.String())
|
||||
return wrapper.Wrap(err)
|
||||
return errors.Wrap(err)
|
||||
}
|
||||
// Replace the accumulated output
|
||||
r.accumulatedOutput = kOut.Stdout.String()
|
||||
@@ -126,12 +126,12 @@ func (r *Result) Save(ctx context.Context, path string, content string) error {
|
||||
dir := filepath.Dir(path)
|
||||
if err := os.MkdirAll(dir, os.FileMode(0775)); err != nil {
|
||||
log.WarnContext(ctx, "could not mkdir", "path", dir, "err", err)
|
||||
return wrapper.Wrap(err)
|
||||
return errors.Wrap(err)
|
||||
}
|
||||
// Write the kube api objects
|
||||
if err := os.WriteFile(path, []byte(content), os.FileMode(0644)); err != nil {
|
||||
log.WarnContext(ctx, "could not write", "path", path, "err", err)
|
||||
return wrapper.Wrap(err)
|
||||
return errors.Wrap(err)
|
||||
}
|
||||
log.DebugContext(ctx, "out: wrote "+path, "action", "write", "path", path, "status", "ok")
|
||||
return nil
|
||||
|
||||
24
buf.gen.yaml
Normal file
24
buf.gen.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
# Generates gRPC and ConnectRPC bindings for Go and TypeScript
|
||||
#
|
||||
# Note: protoc-gen-connect-query is the primary method of wiring up the React
|
||||
# frontend.
|
||||
version: v1
|
||||
plugins:
|
||||
- plugin: go
|
||||
out: service/gen
|
||||
opt: paths=source_relative
|
||||
- plugin: connect-go
|
||||
out: service/gen
|
||||
opt: paths=source_relative
|
||||
- plugin: es
|
||||
out: internal/frontend/holos/gen
|
||||
opt:
|
||||
- target=ts
|
||||
- plugin: connect-es
|
||||
out: internal/frontend/holos/gen
|
||||
opt:
|
||||
- target=ts
|
||||
- plugin: connect-query
|
||||
out: internal/frontend/holos/gen
|
||||
opt:
|
||||
- target=ts
|
||||
8
buf.lock
Normal file
8
buf.lock
Normal file
@@ -0,0 +1,8 @@
|
||||
# Generated by buf. DO NOT EDIT.
|
||||
version: v1
|
||||
deps:
|
||||
- remote: buf.build
|
||||
owner: bufbuild
|
||||
repository: protovalidate
|
||||
commit: b983156c5e994cc9892e0ce3e64e17e0
|
||||
digest: shake256:fb47a62989d38c2529bcc5cd86ded43d800eb84cee82b42b9e8a9e815d4ee8134a0fb9d0ce8299b27c2d2bbb7d6ade0c4ad5a8a4d467e1e2c7ca619ae9f634e2
|
||||
3
buf.work.yaml
Normal file
3
buf.work.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
version: v1
|
||||
directories:
|
||||
- service
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,546 @@
|
||||
// Code generated by timoni. DO NOT EDIT.
|
||||
|
||||
//timoni:generate timoni vendor crd -f /home/jeff/workspace/holos-run/holos-infra/deploy/clusters/k2/components/prod-platform-monitoring/prod-platform-monitoring.gen.yaml
|
||||
|
||||
package v1
|
||||
|
||||
import "strings"
|
||||
|
||||
// PodMonitor defines monitoring for a set of pods.
|
||||
#PodMonitor: {
|
||||
// APIVersion defines the versioned schema of this representation
|
||||
// of an object. Servers should convert recognized schemas to the
|
||||
// latest internal value, and may reject unrecognized values.
|
||||
// More info:
|
||||
// https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
apiVersion: "monitoring.coreos.com/v1"
|
||||
|
||||
// Kind is a string value representing the REST resource this
|
||||
// object represents. Servers may infer this from the endpoint
|
||||
// the client submits requests to. Cannot be updated. In
|
||||
// CamelCase. More info:
|
||||
// https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
kind: "PodMonitor"
|
||||
metadata!: {
|
||||
name!: strings.MaxRunes(253) & strings.MinRunes(1) & {
|
||||
string
|
||||
}
|
||||
namespace!: strings.MaxRunes(63) & strings.MinRunes(1) & {
|
||||
string
|
||||
}
|
||||
labels?: {
|
||||
[string]: string
|
||||
}
|
||||
annotations?: {
|
||||
[string]: string
|
||||
}
|
||||
}
|
||||
|
||||
// Specification of desired Pod selection for target discovery by
|
||||
// Prometheus.
|
||||
spec!: #PodMonitorSpec
|
||||
}
|
||||
|
||||
// Specification of desired Pod selection for target discovery by
|
||||
// Prometheus.
|
||||
#PodMonitorSpec: {
|
||||
attachMetadata?: {
|
||||
// When set to true, Prometheus must have the `get` permission on
|
||||
// the `Nodes` objects.
|
||||
node?: bool
|
||||
}
|
||||
|
||||
// The label to use to retrieve the job name from. `jobLabel`
|
||||
// selects the label from the associated Kubernetes `Pod` object
|
||||
// which will be used as the `job` label for all metrics.
|
||||
// For example if `jobLabel` is set to `foo` and the Kubernetes
|
||||
// `Pod` object is labeled with `foo: bar`, then Prometheus adds
|
||||
// the `job="bar"` label to all ingested metrics.
|
||||
// If the value of this field is empty, the `job` label of the
|
||||
// metrics defaults to the namespace and name of the PodMonitor
|
||||
// object (e.g. `<namespace>/<name>`).
|
||||
jobLabel?: string
|
||||
|
||||
// Per-scrape limit on the number of targets dropped by relabeling
|
||||
// that will be kept in memory. 0 means no limit.
|
||||
// It requires Prometheus >= v2.47.0.
|
||||
keepDroppedTargets?: int
|
||||
|
||||
// Per-scrape limit on number of labels that will be accepted for
|
||||
// a sample.
|
||||
// It requires Prometheus >= v2.27.0.
|
||||
labelLimit?: int
|
||||
|
||||
// Per-scrape limit on length of labels name that will be accepted
|
||||
// for a sample.
|
||||
// It requires Prometheus >= v2.27.0.
|
||||
labelNameLengthLimit?: int
|
||||
|
||||
// Per-scrape limit on length of labels value that will be
|
||||
// accepted for a sample.
|
||||
// It requires Prometheus >= v2.27.0.
|
||||
labelValueLengthLimit?: int
|
||||
|
||||
// Selector to select which namespaces the Kubernetes `Pods`
|
||||
// objects are discovered from.
|
||||
namespaceSelector?: {
|
||||
// Boolean describing whether all namespaces are selected in
|
||||
// contrast to a list restricting them.
|
||||
any?: bool
|
||||
|
||||
// List of namespace names to select from.
|
||||
matchNames?: [...string]
|
||||
}
|
||||
|
||||
// List of endpoints part of this PodMonitor.
|
||||
podMetricsEndpoints?: [...{
|
||||
// `authorization` configures the Authorization header credentials
|
||||
// to use when scraping the target.
|
||||
// Cannot be set at the same time as `basicAuth`, or `oauth2`.
|
||||
authorization?: {
|
||||
// Selects a key of a Secret in the namespace that contains the
|
||||
// credentials for authentication.
|
||||
credentials?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// Defines the authentication type. The value is case-insensitive.
|
||||
// "Basic" is not a supported value.
|
||||
// Default: "Bearer"
|
||||
type?: string
|
||||
}
|
||||
|
||||
// `basicAuth` configures the Basic Authentication credentials to
|
||||
// use when scraping the target.
|
||||
// Cannot be set at the same time as `authorization`, or `oauth2`.
|
||||
basicAuth?: {
|
||||
// `password` specifies a key of a Secret containing the password
|
||||
// for authentication.
|
||||
password?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// `username` specifies a key of a Secret containing the username
|
||||
// for authentication.
|
||||
username?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
}
|
||||
|
||||
// `bearerTokenSecret` specifies a key of a Secret containing the
|
||||
// bearer token for scraping targets. The secret needs to be in
|
||||
// the same namespace as the PodMonitor object and readable by
|
||||
// the Prometheus Operator.
|
||||
// Deprecated: use `authorization` instead.
|
||||
bearerTokenSecret?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// `enableHttp2` can be used to disable HTTP2 when scraping the
|
||||
// target.
|
||||
enableHttp2?: bool
|
||||
|
||||
// When true, the pods which are not running (e.g. either in
|
||||
// Failed or Succeeded state) are dropped during the target
|
||||
// discovery.
|
||||
// If unset, the filtering is enabled.
|
||||
// More info:
|
||||
// https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
|
||||
filterRunning?: bool
|
||||
|
||||
// `followRedirects` defines whether the scrape requests should
|
||||
// follow HTTP 3xx redirects.
|
||||
followRedirects?: bool
|
||||
|
||||
// When true, `honorLabels` preserves the metric's labels when
|
||||
// they collide with the target's labels.
|
||||
honorLabels?: bool
|
||||
|
||||
// `honorTimestamps` controls whether Prometheus preserves the
|
||||
// timestamps when exposed by the target.
|
||||
honorTimestamps?: bool
|
||||
|
||||
// Interval at which Prometheus scrapes the metrics from the
|
||||
// target.
|
||||
// If empty, Prometheus uses the global scrape interval.
|
||||
interval?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$"
|
||||
|
||||
// `metricRelabelings` configures the relabeling rules to apply to
|
||||
// the samples before ingestion.
|
||||
metricRelabelings?: [...{
|
||||
// Action to perform based on the regex matching.
|
||||
// `Uppercase` and `Lowercase` actions require Prometheus >=
|
||||
// v2.36.0. `DropEqual` and `KeepEqual` actions require
|
||||
// Prometheus >= v2.41.0.
|
||||
// Default: "Replace"
|
||||
action?: "replace" | "Replace" | "keep" | "Keep" | "drop" | "Drop" | "hashmod" | "HashMod" | "labelmap" | "LabelMap" | "labeldrop" | "LabelDrop" | "labelkeep" | "LabelKeep" | "lowercase" | "Lowercase" | "uppercase" | "Uppercase" | "keepequal" | "KeepEqual" | "dropequal" | "DropEqual" | *"replace"
|
||||
|
||||
// Modulus to take of the hash of the source label values.
|
||||
// Only applicable when the action is `HashMod`.
|
||||
modulus?: int
|
||||
|
||||
// Regular expression against which the extracted value is
|
||||
// matched.
|
||||
regex?: string
|
||||
|
||||
// Replacement value against which a Replace action is performed
|
||||
// if the regular expression matches.
|
||||
// Regex capture groups are available.
|
||||
replacement?: string
|
||||
|
||||
// Separator is the string between concatenated SourceLabels.
|
||||
separator?: string
|
||||
|
||||
// The source labels select values from existing labels. Their
|
||||
// content is concatenated using the configured Separator and
|
||||
// matched against the configured regular expression.
|
||||
sourceLabels?: [...=~"^[a-zA-Z_][a-zA-Z0-9_]*$"]
|
||||
|
||||
// Label to which the resulting string is written in a
|
||||
// replacement.
|
||||
// It is mandatory for `Replace`, `HashMod`, `Lowercase`,
|
||||
// `Uppercase`, `KeepEqual` and `DropEqual` actions.
|
||||
// Regex capture groups are available.
|
||||
targetLabel?: string
|
||||
}]
|
||||
|
||||
// `oauth2` configures the OAuth2 settings to use when scraping
|
||||
// the target.
|
||||
// It requires Prometheus >= 2.27.0.
|
||||
// Cannot be set at the same time as `authorization`, or
|
||||
// `basicAuth`.
|
||||
oauth2?: {
|
||||
// `clientId` specifies a key of a Secret or ConfigMap containing
|
||||
// the OAuth2 client's ID.
|
||||
clientId: {
|
||||
// ConfigMap containing data to use for the targets.
|
||||
configMap?: {
|
||||
// The key to select.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the ConfigMap or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// Secret containing data to use for the targets.
|
||||
secret?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
}
|
||||
|
||||
// `clientSecret` specifies a key of a Secret containing the
|
||||
// OAuth2 client's secret.
|
||||
clientSecret: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// `endpointParams` configures the HTTP parameters to append to
|
||||
// the token URL.
|
||||
endpointParams?: {
|
||||
[string]: string
|
||||
}
|
||||
|
||||
// `scopes` defines the OAuth2 scopes used for the token request.
|
||||
scopes?: [...string]
|
||||
|
||||
// `tokenURL` configures the URL to fetch the token from.
|
||||
tokenUrl: strings.MinRunes(1)
|
||||
}
|
||||
|
||||
// `params` define optional HTTP URL parameters.
|
||||
params?: {
|
||||
[string]: [...string]
|
||||
}
|
||||
|
||||
// HTTP path from which to scrape for metrics.
|
||||
// If empty, Prometheus uses the default value (e.g. `/metrics`).
|
||||
path?: string
|
||||
|
||||
// Name of the Pod port which this endpoint refers to.
|
||||
// It takes precedence over `targetPort`.
|
||||
port?: string
|
||||
|
||||
// `proxyURL` configures the HTTP Proxy URL (e.g.
|
||||
// "http://proxyserver:2195") to go through when scraping the
|
||||
// target.
|
||||
proxyUrl?: string
|
||||
|
||||
// `relabelings` configures the relabeling rules to apply the
|
||||
// target's metadata labels.
|
||||
// The Operator automatically adds relabelings for a few standard
|
||||
// Kubernetes fields.
|
||||
// The original scrape job's name is available via the
|
||||
// `__tmp_prometheus_job_name` label.
|
||||
// More info:
|
||||
// https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config
|
||||
relabelings?: [...{
|
||||
// Action to perform based on the regex matching.
|
||||
// `Uppercase` and `Lowercase` actions require Prometheus >=
|
||||
// v2.36.0. `DropEqual` and `KeepEqual` actions require
|
||||
// Prometheus >= v2.41.0.
|
||||
// Default: "Replace"
|
||||
action?: "replace" | "Replace" | "keep" | "Keep" | "drop" | "Drop" | "hashmod" | "HashMod" | "labelmap" | "LabelMap" | "labeldrop" | "LabelDrop" | "labelkeep" | "LabelKeep" | "lowercase" | "Lowercase" | "uppercase" | "Uppercase" | "keepequal" | "KeepEqual" | "dropequal" | "DropEqual" | *"replace"
|
||||
|
||||
// Modulus to take of the hash of the source label values.
|
||||
// Only applicable when the action is `HashMod`.
|
||||
modulus?: int
|
||||
|
||||
// Regular expression against which the extracted value is
|
||||
// matched.
|
||||
regex?: string
|
||||
|
||||
// Replacement value against which a Replace action is performed
|
||||
// if the regular expression matches.
|
||||
// Regex capture groups are available.
|
||||
replacement?: string
|
||||
|
||||
// Separator is the string between concatenated SourceLabels.
|
||||
separator?: string
|
||||
|
||||
// The source labels select values from existing labels. Their
|
||||
// content is concatenated using the configured Separator and
|
||||
// matched against the configured regular expression.
|
||||
sourceLabels?: [...=~"^[a-zA-Z_][a-zA-Z0-9_]*$"]
|
||||
|
||||
// Label to which the resulting string is written in a
|
||||
// replacement.
|
||||
// It is mandatory for `Replace`, `HashMod`, `Lowercase`,
|
||||
// `Uppercase`, `KeepEqual` and `DropEqual` actions.
|
||||
// Regex capture groups are available.
|
||||
targetLabel?: string
|
||||
}]
|
||||
|
||||
// HTTP scheme to use for scraping.
|
||||
// `http` and `https` are the expected values unless you rewrite
|
||||
// the `__scheme__` label via relabeling.
|
||||
// If empty, Prometheus uses the default value `http`.
|
||||
scheme?: "http" | "https"
|
||||
|
||||
// Timeout after which Prometheus considers the scrape to be
|
||||
// failed.
|
||||
// If empty, Prometheus uses the global scrape timeout unless it
|
||||
// is less than the target's scrape interval value in which the
|
||||
// latter is used.
|
||||
scrapeTimeout?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$"
|
||||
|
||||
// Name or number of the target port of the `Pod` object behind
|
||||
// the Service, the port must be specified with container port
|
||||
// property.
|
||||
// Deprecated: use 'port' instead.
|
||||
targetPort?: (int | string) & {
|
||||
string
|
||||
}
|
||||
|
||||
// TLS configuration to use when scraping the target.
|
||||
tlsConfig?: {
|
||||
// Certificate authority used when verifying server certificates.
|
||||
ca?: {
|
||||
// ConfigMap containing data to use for the targets.
|
||||
configMap?: {
|
||||
// The key to select.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the ConfigMap or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// Secret containing data to use for the targets.
|
||||
secret?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
}
|
||||
|
||||
// Client certificate to present when doing client-authentication.
|
||||
cert?: {
|
||||
// ConfigMap containing data to use for the targets.
|
||||
configMap?: {
|
||||
// The key to select.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the ConfigMap or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// Secret containing data to use for the targets.
|
||||
secret?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
}
|
||||
|
||||
// Disable target certificate validation.
|
||||
insecureSkipVerify?: bool
|
||||
|
||||
// Secret containing the client key file for the targets.
|
||||
keySecret?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// Used to verify the hostname for the targets.
|
||||
serverName?: string
|
||||
}
|
||||
|
||||
// `trackTimestampsStaleness` defines whether Prometheus tracks
|
||||
// staleness of the metrics that have an explicit timestamp
|
||||
// present in scraped data. Has no effect if `honorTimestamps` is
|
||||
// false.
|
||||
// It requires Prometheus >= v2.48.0.
|
||||
trackTimestampsStaleness?: bool
|
||||
}]
|
||||
|
||||
// `podTargetLabels` defines the labels which are transferred from
|
||||
// the associated Kubernetes `Pod` object onto the ingested
|
||||
// metrics.
|
||||
podTargetLabels?: [...string]
|
||||
|
||||
// `sampleLimit` defines a per-scrape limit on the number of
|
||||
// scraped samples that will be accepted.
|
||||
sampleLimit?: int
|
||||
|
||||
// The scrape class to apply.
|
||||
scrapeClass?: strings.MinRunes(1)
|
||||
|
||||
// `scrapeProtocols` defines the protocols to negotiate during a
|
||||
// scrape. It tells clients the protocols supported by Prometheus
|
||||
// in order of preference (from most to least preferred).
|
||||
// If unset, Prometheus uses its default value.
|
||||
// It requires Prometheus >= v2.49.0.
|
||||
scrapeProtocols?: [..."PrometheusProto" | "OpenMetricsText0.0.1" | "OpenMetricsText1.0.0" | "PrometheusText0.0.4"]
|
||||
|
||||
// Label selector to select the Kubernetes `Pod` objects.
|
||||
selector: {
|
||||
// matchExpressions is a list of label selector requirements. The
|
||||
// requirements are ANDed.
|
||||
matchExpressions?: [...{
|
||||
// key is the label key that the selector applies to.
|
||||
key: string
|
||||
|
||||
// operator represents a key's relationship to a set of values.
|
||||
// Valid operators are In, NotIn, Exists and DoesNotExist.
|
||||
operator: string
|
||||
|
||||
// values is an array of string values. If the operator is In or
|
||||
// NotIn, the values array must be non-empty. If the operator is
|
||||
// Exists or DoesNotExist, the values array must be empty. This
|
||||
// array is replaced during a strategic merge patch.
|
||||
values?: [...string]
|
||||
}]
|
||||
|
||||
// matchLabels is a map of {key,value} pairs. A single {key,value}
|
||||
// in the matchLabels map is equivalent to an element of
|
||||
// matchExpressions, whose key field is "key", the operator is
|
||||
// "In", and the values array contains only "value". The
|
||||
// requirements are ANDed.
|
||||
matchLabels?: {
|
||||
[string]: string
|
||||
}
|
||||
}
|
||||
|
||||
// `targetLimit` defines a limit on the number of scraped targets
|
||||
// that will be accepted.
|
||||
targetLimit?: int
|
||||
}
|
||||
@@ -0,0 +1,536 @@
|
||||
// Code generated by timoni. DO NOT EDIT.
|
||||
|
||||
//timoni:generate timoni vendor crd -f /home/jeff/workspace/holos-run/holos-infra/deploy/clusters/k2/components/prod-platform-monitoring/prod-platform-monitoring.gen.yaml
|
||||
|
||||
package v1
|
||||
|
||||
import "strings"
|
||||
|
||||
// Probe defines monitoring for a set of static targets or
|
||||
// ingresses.
|
||||
#Probe: {
|
||||
// APIVersion defines the versioned schema of this representation
|
||||
// of an object. Servers should convert recognized schemas to the
|
||||
// latest internal value, and may reject unrecognized values.
|
||||
// More info:
|
||||
// https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
apiVersion: "monitoring.coreos.com/v1"
|
||||
|
||||
// Kind is a string value representing the REST resource this
|
||||
// object represents. Servers may infer this from the endpoint
|
||||
// the client submits requests to. Cannot be updated. In
|
||||
// CamelCase. More info:
|
||||
// https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
kind: "Probe"
|
||||
metadata!: {
|
||||
name!: strings.MaxRunes(253) & strings.MinRunes(1) & {
|
||||
string
|
||||
}
|
||||
namespace!: strings.MaxRunes(63) & strings.MinRunes(1) & {
|
||||
string
|
||||
}
|
||||
labels?: {
|
||||
[string]: string
|
||||
}
|
||||
annotations?: {
|
||||
[string]: string
|
||||
}
|
||||
}
|
||||
|
||||
// Specification of desired Ingress selection for target discovery
|
||||
// by Prometheus.
|
||||
spec!: #ProbeSpec
|
||||
}
|
||||
|
||||
// Specification of desired Ingress selection for target discovery
|
||||
// by Prometheus.
|
||||
#ProbeSpec: {
|
||||
// Authorization section for this endpoint
|
||||
authorization?: {
|
||||
// Selects a key of a Secret in the namespace that contains the
|
||||
// credentials for authentication.
|
||||
credentials?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// Defines the authentication type. The value is case-insensitive.
|
||||
// "Basic" is not a supported value.
|
||||
// Default: "Bearer"
|
||||
type?: string
|
||||
}
|
||||
|
||||
// BasicAuth allow an endpoint to authenticate over basic
|
||||
// authentication. More info:
|
||||
// https://prometheus.io/docs/operating/configuration/#endpoint
|
||||
basicAuth?: {
|
||||
// `password` specifies a key of a Secret containing the password
|
||||
// for authentication.
|
||||
password?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// `username` specifies a key of a Secret containing the username
|
||||
// for authentication.
|
||||
username?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
}
|
||||
|
||||
// Secret to mount to read bearer token for scraping targets. The
|
||||
// secret needs to be in the same namespace as the probe and
|
||||
// accessible by the Prometheus Operator.
|
||||
bearerTokenSecret?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// Interval at which targets are probed using the configured
|
||||
// prober. If not specified Prometheus' global scrape interval is
|
||||
// used.
|
||||
interval?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$"
|
||||
|
||||
// The job name assigned to scraped metrics by default.
|
||||
jobName?: string
|
||||
|
||||
// Per-scrape limit on the number of targets dropped by relabeling
|
||||
// that will be kept in memory. 0 means no limit.
|
||||
// It requires Prometheus >= v2.47.0.
|
||||
keepDroppedTargets?: int
|
||||
|
||||
// Per-scrape limit on number of labels that will be accepted for
|
||||
// a sample. Only valid in Prometheus versions 2.27.0 and newer.
|
||||
labelLimit?: int
|
||||
|
||||
// Per-scrape limit on length of labels name that will be accepted
|
||||
// for a sample. Only valid in Prometheus versions 2.27.0 and
|
||||
// newer.
|
||||
labelNameLengthLimit?: int
|
||||
|
||||
// Per-scrape limit on length of labels value that will be
|
||||
// accepted for a sample. Only valid in Prometheus versions
|
||||
// 2.27.0 and newer.
|
||||
labelValueLengthLimit?: int
|
||||
|
||||
// MetricRelabelConfigs to apply to samples before ingestion.
|
||||
metricRelabelings?: [...{
|
||||
// Action to perform based on the regex matching.
|
||||
// `Uppercase` and `Lowercase` actions require Prometheus >=
|
||||
// v2.36.0. `DropEqual` and `KeepEqual` actions require
|
||||
// Prometheus >= v2.41.0.
|
||||
// Default: "Replace"
|
||||
action?: "replace" | "Replace" | "keep" | "Keep" | "drop" | "Drop" | "hashmod" | "HashMod" | "labelmap" | "LabelMap" | "labeldrop" | "LabelDrop" | "labelkeep" | "LabelKeep" | "lowercase" | "Lowercase" | "uppercase" | "Uppercase" | "keepequal" | "KeepEqual" | "dropequal" | "DropEqual" | *"replace"
|
||||
|
||||
// Modulus to take of the hash of the source label values.
|
||||
// Only applicable when the action is `HashMod`.
|
||||
modulus?: int
|
||||
|
||||
// Regular expression against which the extracted value is
|
||||
// matched.
|
||||
regex?: string
|
||||
|
||||
// Replacement value against which a Replace action is performed
|
||||
// if the regular expression matches.
|
||||
// Regex capture groups are available.
|
||||
replacement?: string
|
||||
|
||||
// Separator is the string between concatenated SourceLabels.
|
||||
separator?: string
|
||||
|
||||
// The source labels select values from existing labels. Their
|
||||
// content is concatenated using the configured Separator and
|
||||
// matched against the configured regular expression.
|
||||
sourceLabels?: [...=~"^[a-zA-Z_][a-zA-Z0-9_]*$"]
|
||||
|
||||
// Label to which the resulting string is written in a
|
||||
// replacement.
|
||||
// It is mandatory for `Replace`, `HashMod`, `Lowercase`,
|
||||
// `Uppercase`, `KeepEqual` and `DropEqual` actions.
|
||||
// Regex capture groups are available.
|
||||
targetLabel?: string
|
||||
}]
|
||||
|
||||
// The module to use for probing specifying how to probe the
|
||||
// target. Example module configuring in the blackbox exporter:
|
||||
// https://github.com/prometheus/blackbox_exporter/blob/master/example.yml
|
||||
module?: string
|
||||
|
||||
// OAuth2 for the URL. Only valid in Prometheus versions 2.27.0
|
||||
// and newer.
|
||||
oauth2?: {
|
||||
// `clientId` specifies a key of a Secret or ConfigMap containing
|
||||
// the OAuth2 client's ID.
|
||||
clientId: {
|
||||
// ConfigMap containing data to use for the targets.
|
||||
configMap?: {
|
||||
// The key to select.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the ConfigMap or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// Secret containing data to use for the targets.
|
||||
secret?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
}
|
||||
|
||||
// `clientSecret` specifies a key of a Secret containing the
|
||||
// OAuth2 client's secret.
|
||||
clientSecret: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// `endpointParams` configures the HTTP parameters to append to
|
||||
// the token URL.
|
||||
endpointParams?: {
|
||||
[string]: string
|
||||
}
|
||||
|
||||
// `scopes` defines the OAuth2 scopes used for the token request.
|
||||
scopes?: [...string]
|
||||
|
||||
// `tokenURL` configures the URL to fetch the token from.
|
||||
tokenUrl: strings.MinRunes(1)
|
||||
}
|
||||
|
||||
// Specification for the prober to use for probing targets. The
|
||||
// prober.URL parameter is required. Targets cannot be probed if
|
||||
// left empty.
|
||||
prober?: {
|
||||
// Path to collect metrics from. Defaults to `/probe`.
|
||||
path?: string | *"/probe"
|
||||
|
||||
// Optional ProxyURL.
|
||||
proxyUrl?: string
|
||||
|
||||
// HTTP scheme to use for scraping. `http` and `https` are the
|
||||
// expected values unless you rewrite the `__scheme__` label via
|
||||
// relabeling. If empty, Prometheus uses the default value
|
||||
// `http`.
|
||||
scheme?: "http" | "https"
|
||||
|
||||
// Mandatory URL of the prober.
|
||||
url: string
|
||||
}
|
||||
|
||||
// SampleLimit defines per-scrape limit on number of scraped
|
||||
// samples that will be accepted.
|
||||
sampleLimit?: int
|
||||
|
||||
// The scrape class to apply.
|
||||
scrapeClass?: strings.MinRunes(1)
|
||||
|
||||
// `scrapeProtocols` defines the protocols to negotiate during a
|
||||
// scrape. It tells clients the protocols supported by Prometheus
|
||||
// in order of preference (from most to least preferred).
|
||||
// If unset, Prometheus uses its default value.
|
||||
// It requires Prometheus >= v2.49.0.
|
||||
scrapeProtocols?: [..."PrometheusProto" | "OpenMetricsText0.0.1" | "OpenMetricsText1.0.0" | "PrometheusText0.0.4"]
|
||||
|
||||
// Timeout for scraping metrics from the Prometheus exporter. If
|
||||
// not specified, the Prometheus global scrape timeout is used.
|
||||
scrapeTimeout?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$"
|
||||
|
||||
// TargetLimit defines a limit on the number of scraped targets
|
||||
// that will be accepted.
|
||||
targetLimit?: int
|
||||
|
||||
// Targets defines a set of static or dynamically discovered
|
||||
// targets to probe.
|
||||
targets?: {
|
||||
// ingress defines the Ingress objects to probe and the relabeling
|
||||
// configuration. If `staticConfig` is also defined,
|
||||
// `staticConfig` takes precedence.
|
||||
ingress?: {
|
||||
// From which namespaces to select Ingress objects.
|
||||
namespaceSelector?: {
|
||||
// Boolean describing whether all namespaces are selected in
|
||||
// contrast to a list restricting them.
|
||||
any?: bool
|
||||
|
||||
// List of namespace names to select from.
|
||||
matchNames?: [...string]
|
||||
}
|
||||
|
||||
// RelabelConfigs to apply to the label set of the target before
|
||||
// it gets scraped. The original ingress address is available via
|
||||
// the `__tmp_prometheus_ingress_address` label. It can be used
|
||||
// to customize the probed URL. The original scrape job's name is
|
||||
// available via the `__tmp_prometheus_job_name` label. More
|
||||
// info:
|
||||
// https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config
|
||||
relabelingConfigs?: [...{
|
||||
// Action to perform based on the regex matching.
|
||||
// `Uppercase` and `Lowercase` actions require Prometheus >=
|
||||
// v2.36.0. `DropEqual` and `KeepEqual` actions require
|
||||
// Prometheus >= v2.41.0.
|
||||
// Default: "Replace"
|
||||
action?: "replace" | "Replace" | "keep" | "Keep" | "drop" | "Drop" | "hashmod" | "HashMod" | "labelmap" | "LabelMap" | "labeldrop" | "LabelDrop" | "labelkeep" | "LabelKeep" | "lowercase" | "Lowercase" | "uppercase" | "Uppercase" | "keepequal" | "KeepEqual" | "dropequal" | "DropEqual" | *"replace"
|
||||
|
||||
// Modulus to take of the hash of the source label values.
|
||||
// Only applicable when the action is `HashMod`.
|
||||
modulus?: int
|
||||
|
||||
// Regular expression against which the extracted value is
|
||||
// matched.
|
||||
regex?: string
|
||||
|
||||
// Replacement value against which a Replace action is performed
|
||||
// if the regular expression matches.
|
||||
// Regex capture groups are available.
|
||||
replacement?: string
|
||||
|
||||
// Separator is the string between concatenated SourceLabels.
|
||||
separator?: string
|
||||
|
||||
// The source labels select values from existing labels. Their
|
||||
// content is concatenated using the configured Separator and
|
||||
// matched against the configured regular expression.
|
||||
sourceLabels?: [...=~"^[a-zA-Z_][a-zA-Z0-9_]*$"]
|
||||
|
||||
// Label to which the resulting string is written in a
|
||||
// replacement.
|
||||
// It is mandatory for `Replace`, `HashMod`, `Lowercase`,
|
||||
// `Uppercase`, `KeepEqual` and `DropEqual` actions.
|
||||
// Regex capture groups are available.
|
||||
targetLabel?: string
|
||||
}]
|
||||
|
||||
// Selector to select the Ingress objects.
|
||||
selector?: {
|
||||
// matchExpressions is a list of label selector requirements. The
|
||||
// requirements are ANDed.
|
||||
matchExpressions?: [...{
|
||||
// key is the label key that the selector applies to.
|
||||
key: string
|
||||
|
||||
// operator represents a key's relationship to a set of values.
|
||||
// Valid operators are In, NotIn, Exists and DoesNotExist.
|
||||
operator: string
|
||||
|
||||
// values is an array of string values. If the operator is In or
|
||||
// NotIn, the values array must be non-empty. If the operator is
|
||||
// Exists or DoesNotExist, the values array must be empty. This
|
||||
// array is replaced during a strategic merge patch.
|
||||
values?: [...string]
|
||||
}]
|
||||
|
||||
// matchLabels is a map of {key,value} pairs. A single {key,value}
|
||||
// in the matchLabels map is equivalent to an element of
|
||||
// matchExpressions, whose key field is "key", the operator is
|
||||
// "In", and the values array contains only "value". The
|
||||
// requirements are ANDed.
|
||||
matchLabels?: {
|
||||
[string]: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// staticConfig defines the static list of targets to probe and
|
||||
// the relabeling configuration. If `ingress` is also defined,
|
||||
// `staticConfig` takes precedence. More info:
|
||||
// https://prometheus.io/docs/prometheus/latest/configuration/configuration/#static_config.
|
||||
staticConfig?: {
|
||||
// Labels assigned to all metrics scraped from the targets.
|
||||
labels?: {
|
||||
[string]: string
|
||||
}
|
||||
|
||||
// RelabelConfigs to apply to the label set of the targets before
|
||||
// it gets scraped. More info:
|
||||
// https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config
|
||||
relabelingConfigs?: [...{
|
||||
// Action to perform based on the regex matching.
|
||||
// `Uppercase` and `Lowercase` actions require Prometheus >=
|
||||
// v2.36.0. `DropEqual` and `KeepEqual` actions require
|
||||
// Prometheus >= v2.41.0.
|
||||
// Default: "Replace"
|
||||
action?: "replace" | "Replace" | "keep" | "Keep" | "drop" | "Drop" | "hashmod" | "HashMod" | "labelmap" | "LabelMap" | "labeldrop" | "LabelDrop" | "labelkeep" | "LabelKeep" | "lowercase" | "Lowercase" | "uppercase" | "Uppercase" | "keepequal" | "KeepEqual" | "dropequal" | "DropEqual" | *"replace"
|
||||
|
||||
// Modulus to take of the hash of the source label values.
|
||||
// Only applicable when the action is `HashMod`.
|
||||
modulus?: int
|
||||
|
||||
// Regular expression against which the extracted value is
|
||||
// matched.
|
||||
regex?: string
|
||||
|
||||
// Replacement value against which a Replace action is performed
|
||||
// if the regular expression matches.
|
||||
// Regex capture groups are available.
|
||||
replacement?: string
|
||||
|
||||
// Separator is the string between concatenated SourceLabels.
|
||||
separator?: string
|
||||
|
||||
// The source labels select values from existing labels. Their
|
||||
// content is concatenated using the configured Separator and
|
||||
// matched against the configured regular expression.
|
||||
sourceLabels?: [...=~"^[a-zA-Z_][a-zA-Z0-9_]*$"]
|
||||
|
||||
// Label to which the resulting string is written in a
|
||||
// replacement.
|
||||
// It is mandatory for `Replace`, `HashMod`, `Lowercase`,
|
||||
// `Uppercase`, `KeepEqual` and `DropEqual` actions.
|
||||
// Regex capture groups are available.
|
||||
targetLabel?: string
|
||||
}]
|
||||
|
||||
// The list of hosts to probe.
|
||||
static?: [...string]
|
||||
}
|
||||
}
|
||||
|
||||
// TLS configuration to use when scraping the endpoint.
|
||||
tlsConfig?: {
|
||||
// Certificate authority used when verifying server certificates.
|
||||
ca?: {
|
||||
// ConfigMap containing data to use for the targets.
|
||||
configMap?: {
|
||||
// The key to select.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the ConfigMap or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// Secret containing data to use for the targets.
|
||||
secret?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
}
|
||||
|
||||
// Client certificate to present when doing client-authentication.
|
||||
cert?: {
|
||||
// ConfigMap containing data to use for the targets.
|
||||
configMap?: {
|
||||
// The key to select.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the ConfigMap or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// Secret containing data to use for the targets.
|
||||
secret?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
}
|
||||
|
||||
// Disable target certificate validation.
|
||||
insecureSkipVerify?: bool
|
||||
|
||||
// Secret containing the client key file for the targets.
|
||||
keySecret?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// Used to verify the hostname for the targets.
|
||||
serverName?: string
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,100 @@
|
||||
// Code generated by timoni. DO NOT EDIT.
|
||||
|
||||
//timoni:generate timoni vendor crd -f /home/jeff/workspace/holos-run/holos-infra/deploy/clusters/k2/components/prod-platform-monitoring/prod-platform-monitoring.gen.yaml
|
||||
|
||||
package v1
|
||||
|
||||
import "strings"
|
||||
|
||||
// PrometheusRule defines recording and alerting rules for a
|
||||
// Prometheus instance
|
||||
#PrometheusRule: {
|
||||
// APIVersion defines the versioned schema of this representation
|
||||
// of an object. Servers should convert recognized schemas to the
|
||||
// latest internal value, and may reject unrecognized values.
|
||||
// More info:
|
||||
// https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
apiVersion: "monitoring.coreos.com/v1"
|
||||
|
||||
// Kind is a string value representing the REST resource this
|
||||
// object represents. Servers may infer this from the endpoint
|
||||
// the client submits requests to. Cannot be updated. In
|
||||
// CamelCase. More info:
|
||||
// https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
kind: "PrometheusRule"
|
||||
metadata!: {
|
||||
name!: strings.MaxRunes(253) & strings.MinRunes(1) & {
|
||||
string
|
||||
}
|
||||
namespace!: strings.MaxRunes(63) & strings.MinRunes(1) & {
|
||||
string
|
||||
}
|
||||
labels?: {
|
||||
[string]: string
|
||||
}
|
||||
annotations?: {
|
||||
[string]: string
|
||||
}
|
||||
}
|
||||
|
||||
// Specification of desired alerting rule definitions for
|
||||
// Prometheus.
|
||||
spec!: #PrometheusRuleSpec
|
||||
}
|
||||
#PrometheusRuleSpec: {
|
||||
// Content of Prometheus rule file
|
||||
groups?: [...{
|
||||
// Interval determines how often rules in the group are evaluated.
|
||||
interval?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$"
|
||||
|
||||
// Limit the number of alerts an alerting rule and series a
|
||||
// recording rule can produce. Limit is supported starting with
|
||||
// Prometheus >= 2.31 and Thanos Ruler >= 0.24.
|
||||
limit?: int
|
||||
|
||||
// Name of the rule group.
|
||||
name: strings.MinRunes(1)
|
||||
|
||||
// PartialResponseStrategy is only used by ThanosRuler and will be
|
||||
// ignored by Prometheus instances. More info:
|
||||
// https://github.com/thanos-io/thanos/blob/main/docs/components/rule.md#partial-response
|
||||
partial_response_strategy?: =~"^(?i)(abort|warn)?$"
|
||||
|
||||
// List of alerting and recording rules.
|
||||
rules?: [...{
|
||||
// Name of the alert. Must be a valid label value. Only one of
|
||||
// `record` and `alert` must be set.
|
||||
alert?: string
|
||||
|
||||
// Annotations to add to each alert. Only valid for alerting
|
||||
// rules.
|
||||
annotations?: {
|
||||
[string]: string
|
||||
}
|
||||
|
||||
// PromQL expression to evaluate.
|
||||
expr: (int | string) & {
|
||||
string
|
||||
}
|
||||
|
||||
// Alerts are considered firing once they have been returned for
|
||||
// this long.
|
||||
for?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$"
|
||||
|
||||
// KeepFiringFor defines how long an alert will continue firing
|
||||
// after the condition that triggered it has cleared.
|
||||
keep_firing_for?: strings.MinRunes(1) & {
|
||||
=~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$"
|
||||
}
|
||||
|
||||
// Labels to add or overwrite.
|
||||
labels?: {
|
||||
[string]: string
|
||||
}
|
||||
|
||||
// Name of the time series to output to. Must be a valid metric
|
||||
// name. Only one of `record` and `alert` must be set.
|
||||
record?: string
|
||||
}]
|
||||
}]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,566 @@
|
||||
// Code generated by timoni. DO NOT EDIT.
|
||||
|
||||
//timoni:generate timoni vendor crd -f /home/jeff/workspace/holos-run/holos-infra/deploy/clusters/k2/components/prod-platform-monitoring/prod-platform-monitoring.gen.yaml
|
||||
|
||||
package v1
|
||||
|
||||
import "strings"
|
||||
|
||||
// ServiceMonitor defines monitoring for a set of services.
|
||||
#ServiceMonitor: {
|
||||
// APIVersion defines the versioned schema of this representation
|
||||
// of an object. Servers should convert recognized schemas to the
|
||||
// latest internal value, and may reject unrecognized values.
|
||||
// More info:
|
||||
// https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
apiVersion: "monitoring.coreos.com/v1"
|
||||
|
||||
// Kind is a string value representing the REST resource this
|
||||
// object represents. Servers may infer this from the endpoint
|
||||
// the client submits requests to. Cannot be updated. In
|
||||
// CamelCase. More info:
|
||||
// https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
kind: "ServiceMonitor"
|
||||
metadata!: {
|
||||
name!: strings.MaxRunes(253) & strings.MinRunes(1) & {
|
||||
string
|
||||
}
|
||||
namespace!: strings.MaxRunes(63) & strings.MinRunes(1) & {
|
||||
string
|
||||
}
|
||||
labels?: {
|
||||
[string]: string
|
||||
}
|
||||
annotations?: {
|
||||
[string]: string
|
||||
}
|
||||
}
|
||||
|
||||
// Specification of desired Service selection for target discovery
|
||||
// by Prometheus.
|
||||
spec!: #ServiceMonitorSpec
|
||||
}
|
||||
|
||||
// Specification of desired Service selection for target discovery
|
||||
// by Prometheus.
|
||||
#ServiceMonitorSpec: {
|
||||
attachMetadata?: {
|
||||
// When set to true, Prometheus must have the `get` permission on
|
||||
// the `Nodes` objects.
|
||||
node?: bool
|
||||
}
|
||||
|
||||
// List of endpoints part of this ServiceMonitor.
|
||||
endpoints?: [...{
|
||||
// `authorization` configures the Authorization header credentials
|
||||
// to use when scraping the target.
|
||||
// Cannot be set at the same time as `basicAuth`, or `oauth2`.
|
||||
authorization?: {
|
||||
// Selects a key of a Secret in the namespace that contains the
|
||||
// credentials for authentication.
|
||||
credentials?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// Defines the authentication type. The value is case-insensitive.
|
||||
// "Basic" is not a supported value.
|
||||
// Default: "Bearer"
|
||||
type?: string
|
||||
}
|
||||
|
||||
// `basicAuth` configures the Basic Authentication credentials to
|
||||
// use when scraping the target.
|
||||
// Cannot be set at the same time as `authorization`, or `oauth2`.
|
||||
basicAuth?: {
|
||||
// `password` specifies a key of a Secret containing the password
|
||||
// for authentication.
|
||||
password?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// `username` specifies a key of a Secret containing the username
|
||||
// for authentication.
|
||||
username?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
}
|
||||
|
||||
// File to read bearer token for scraping the target.
|
||||
// Deprecated: use `authorization` instead.
|
||||
bearerTokenFile?: string
|
||||
|
||||
// `bearerTokenSecret` specifies a key of a Secret containing the
|
||||
// bearer token for scraping targets. The secret needs to be in
|
||||
// the same namespace as the ServiceMonitor object and readable
|
||||
// by the Prometheus Operator.
|
||||
// Deprecated: use `authorization` instead.
|
||||
bearerTokenSecret?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// `enableHttp2` can be used to disable HTTP2 when scraping the
|
||||
// target.
|
||||
enableHttp2?: bool
|
||||
|
||||
// When true, the pods which are not running (e.g. either in
|
||||
// Failed or Succeeded state) are dropped during the target
|
||||
// discovery.
|
||||
// If unset, the filtering is enabled.
|
||||
// More info:
|
||||
// https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
|
||||
filterRunning?: bool
|
||||
|
||||
// `followRedirects` defines whether the scrape requests should
|
||||
// follow HTTP 3xx redirects.
|
||||
followRedirects?: bool
|
||||
|
||||
// When true, `honorLabels` preserves the metric's labels when
|
||||
// they collide with the target's labels.
|
||||
honorLabels?: bool
|
||||
|
||||
// `honorTimestamps` controls whether Prometheus preserves the
|
||||
// timestamps when exposed by the target.
|
||||
honorTimestamps?: bool
|
||||
|
||||
// Interval at which Prometheus scrapes the metrics from the
|
||||
// target.
|
||||
// If empty, Prometheus uses the global scrape interval.
|
||||
interval?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$"
|
||||
|
||||
// `metricRelabelings` configures the relabeling rules to apply to
|
||||
// the samples before ingestion.
|
||||
metricRelabelings?: [...{
|
||||
// Action to perform based on the regex matching.
|
||||
// `Uppercase` and `Lowercase` actions require Prometheus >=
|
||||
// v2.36.0. `DropEqual` and `KeepEqual` actions require
|
||||
// Prometheus >= v2.41.0.
|
||||
// Default: "Replace"
|
||||
action?: "replace" | "Replace" | "keep" | "Keep" | "drop" | "Drop" | "hashmod" | "HashMod" | "labelmap" | "LabelMap" | "labeldrop" | "LabelDrop" | "labelkeep" | "LabelKeep" | "lowercase" | "Lowercase" | "uppercase" | "Uppercase" | "keepequal" | "KeepEqual" | "dropequal" | "DropEqual" | *"replace"
|
||||
|
||||
// Modulus to take of the hash of the source label values.
|
||||
// Only applicable when the action is `HashMod`.
|
||||
modulus?: int
|
||||
|
||||
// Regular expression against which the extracted value is
|
||||
// matched.
|
||||
regex?: string
|
||||
|
||||
// Replacement value against which a Replace action is performed
|
||||
// if the regular expression matches.
|
||||
// Regex capture groups are available.
|
||||
replacement?: string
|
||||
|
||||
// Separator is the string between concatenated SourceLabels.
|
||||
separator?: string
|
||||
|
||||
// The source labels select values from existing labels. Their
|
||||
// content is concatenated using the configured Separator and
|
||||
// matched against the configured regular expression.
|
||||
sourceLabels?: [...=~"^[a-zA-Z_][a-zA-Z0-9_]*$"]
|
||||
|
||||
// Label to which the resulting string is written in a
|
||||
// replacement.
|
||||
// It is mandatory for `Replace`, `HashMod`, `Lowercase`,
|
||||
// `Uppercase`, `KeepEqual` and `DropEqual` actions.
|
||||
// Regex capture groups are available.
|
||||
targetLabel?: string
|
||||
}]
|
||||
|
||||
// `oauth2` configures the OAuth2 settings to use when scraping
|
||||
// the target.
|
||||
// It requires Prometheus >= 2.27.0.
|
||||
// Cannot be set at the same time as `authorization`, or
|
||||
// `basicAuth`.
|
||||
oauth2?: {
|
||||
// `clientId` specifies a key of a Secret or ConfigMap containing
|
||||
// the OAuth2 client's ID.
|
||||
clientId: {
|
||||
// ConfigMap containing data to use for the targets.
|
||||
configMap?: {
|
||||
// The key to select.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the ConfigMap or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// Secret containing data to use for the targets.
|
||||
secret?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
}
|
||||
|
||||
// `clientSecret` specifies a key of a Secret containing the
|
||||
// OAuth2 client's secret.
|
||||
clientSecret: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// `endpointParams` configures the HTTP parameters to append to
|
||||
// the token URL.
|
||||
endpointParams?: {
|
||||
[string]: string
|
||||
}
|
||||
|
||||
// `scopes` defines the OAuth2 scopes used for the token request.
|
||||
scopes?: [...string]
|
||||
|
||||
// `tokenURL` configures the URL to fetch the token from.
|
||||
tokenUrl: strings.MinRunes(1)
|
||||
}
|
||||
|
||||
// params define optional HTTP URL parameters.
|
||||
params?: {
|
||||
[string]: [...string]
|
||||
}
|
||||
|
||||
// HTTP path from which to scrape for metrics.
|
||||
// If empty, Prometheus uses the default value (e.g. `/metrics`).
|
||||
path?: string
|
||||
|
||||
// Name of the Service port which this endpoint refers to.
|
||||
// It takes precedence over `targetPort`.
|
||||
port?: string
|
||||
|
||||
// `proxyURL` configures the HTTP Proxy URL (e.g.
|
||||
// "http://proxyserver:2195") to go through when scraping the
|
||||
// target.
|
||||
proxyUrl?: string
|
||||
|
||||
// `relabelings` configures the relabeling rules to apply the
|
||||
// target's metadata labels.
|
||||
// The Operator automatically adds relabelings for a few standard
|
||||
// Kubernetes fields.
|
||||
// The original scrape job's name is available via the
|
||||
// `__tmp_prometheus_job_name` label.
|
||||
// More info:
|
||||
// https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config
|
||||
relabelings?: [...{
|
||||
// Action to perform based on the regex matching.
|
||||
// `Uppercase` and `Lowercase` actions require Prometheus >=
|
||||
// v2.36.0. `DropEqual` and `KeepEqual` actions require
|
||||
// Prometheus >= v2.41.0.
|
||||
// Default: "Replace"
|
||||
action?: "replace" | "Replace" | "keep" | "Keep" | "drop" | "Drop" | "hashmod" | "HashMod" | "labelmap" | "LabelMap" | "labeldrop" | "LabelDrop" | "labelkeep" | "LabelKeep" | "lowercase" | "Lowercase" | "uppercase" | "Uppercase" | "keepequal" | "KeepEqual" | "dropequal" | "DropEqual" | *"replace"
|
||||
|
||||
// Modulus to take of the hash of the source label values.
|
||||
// Only applicable when the action is `HashMod`.
|
||||
modulus?: int
|
||||
|
||||
// Regular expression against which the extracted value is
|
||||
// matched.
|
||||
regex?: string
|
||||
|
||||
// Replacement value against which a Replace action is performed
|
||||
// if the regular expression matches.
|
||||
// Regex capture groups are available.
|
||||
replacement?: string
|
||||
|
||||
// Separator is the string between concatenated SourceLabels.
|
||||
separator?: string
|
||||
|
||||
// The source labels select values from existing labels. Their
|
||||
// content is concatenated using the configured Separator and
|
||||
// matched against the configured regular expression.
|
||||
sourceLabels?: [...=~"^[a-zA-Z_][a-zA-Z0-9_]*$"]
|
||||
|
||||
// Label to which the resulting string is written in a
|
||||
// replacement.
|
||||
// It is mandatory for `Replace`, `HashMod`, `Lowercase`,
|
||||
// `Uppercase`, `KeepEqual` and `DropEqual` actions.
|
||||
// Regex capture groups are available.
|
||||
targetLabel?: string
|
||||
}]
|
||||
|
||||
// HTTP scheme to use for scraping.
|
||||
// `http` and `https` are the expected values unless you rewrite
|
||||
// the `__scheme__` label via relabeling.
|
||||
// If empty, Prometheus uses the default value `http`.
|
||||
scheme?: "http" | "https"
|
||||
|
||||
// Timeout after which Prometheus considers the scrape to be
|
||||
// failed.
|
||||
// If empty, Prometheus uses the global scrape timeout unless it
|
||||
// is less than the target's scrape interval value in which the
|
||||
// latter is used.
|
||||
scrapeTimeout?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$"
|
||||
|
||||
// Name or number of the target port of the `Pod` object behind
|
||||
// the Service. The port must be specified with the container's
|
||||
// port property.
|
||||
targetPort?: (int | string) & {
|
||||
string
|
||||
}
|
||||
|
||||
// TLS configuration to use when scraping the target.
|
||||
tlsConfig?: {
|
||||
// Certificate authority used when verifying server certificates.
|
||||
ca?: {
|
||||
// ConfigMap containing data to use for the targets.
|
||||
configMap?: {
|
||||
// The key to select.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the ConfigMap or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// Secret containing data to use for the targets.
|
||||
secret?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
}
|
||||
|
||||
// Path to the CA cert in the Prometheus container to use for the
|
||||
// targets.
|
||||
caFile?: string
|
||||
|
||||
// Client certificate to present when doing client-authentication.
|
||||
cert?: {
|
||||
// ConfigMap containing data to use for the targets.
|
||||
configMap?: {
|
||||
// The key to select.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the ConfigMap or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// Secret containing data to use for the targets.
|
||||
secret?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
}
|
||||
|
||||
// Path to the client cert file in the Prometheus container for
|
||||
// the targets.
|
||||
certFile?: string
|
||||
|
||||
// Disable target certificate validation.
|
||||
insecureSkipVerify?: bool
|
||||
|
||||
// Path to the client key file in the Prometheus container for the
|
||||
// targets.
|
||||
keyFile?: string
|
||||
|
||||
// Secret containing the client key file for the targets.
|
||||
keySecret?: {
|
||||
// The key of the secret to select from. Must be a valid secret
|
||||
// key.
|
||||
key: string
|
||||
|
||||
// Name of the referent. More info:
|
||||
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
name?: string
|
||||
|
||||
// Specify whether the Secret or its key must be defined
|
||||
optional?: bool
|
||||
}
|
||||
|
||||
// Used to verify the hostname for the targets.
|
||||
serverName?: string
|
||||
}
|
||||
|
||||
// `trackTimestampsStaleness` defines whether Prometheus tracks
|
||||
// staleness of the metrics that have an explicit timestamp
|
||||
// present in scraped data. Has no effect if `honorTimestamps` is
|
||||
// false.
|
||||
// It requires Prometheus >= v2.48.0.
|
||||
trackTimestampsStaleness?: bool
|
||||
}]
|
||||
|
||||
// `jobLabel` selects the label from the associated Kubernetes
|
||||
// `Service` object which will be used as the `job` label for all
|
||||
// metrics.
|
||||
// For example if `jobLabel` is set to `foo` and the Kubernetes
|
||||
// `Service` object is labeled with `foo: bar`, then Prometheus
|
||||
// adds the `job="bar"` label to all ingested metrics.
|
||||
// If the value of this field is empty or if the label doesn't
|
||||
// exist for the given Service, the `job` label of the metrics
|
||||
// defaults to the name of the associated Kubernetes `Service`.
|
||||
jobLabel?: string
|
||||
|
||||
// Per-scrape limit on the number of targets dropped by relabeling
|
||||
// that will be kept in memory. 0 means no limit.
|
||||
// It requires Prometheus >= v2.47.0.
|
||||
keepDroppedTargets?: int
|
||||
|
||||
// Per-scrape limit on number of labels that will be accepted for
|
||||
// a sample.
|
||||
// It requires Prometheus >= v2.27.0.
|
||||
labelLimit?: int
|
||||
|
||||
// Per-scrape limit on length of labels name that will be accepted
|
||||
// for a sample.
|
||||
// It requires Prometheus >= v2.27.0.
|
||||
labelNameLengthLimit?: int
|
||||
|
||||
// Per-scrape limit on length of labels value that will be
|
||||
// accepted for a sample.
|
||||
// It requires Prometheus >= v2.27.0.
|
||||
labelValueLengthLimit?: int
|
||||
|
||||
// Selector to select which namespaces the Kubernetes `Endpoints`
|
||||
// objects are discovered from.
|
||||
namespaceSelector?: {
|
||||
// Boolean describing whether all namespaces are selected in
|
||||
// contrast to a list restricting them.
|
||||
any?: bool
|
||||
|
||||
// List of namespace names to select from.
|
||||
matchNames?: [...string]
|
||||
}
|
||||
|
||||
// `podTargetLabels` defines the labels which are transferred from
|
||||
// the associated Kubernetes `Pod` object onto the ingested
|
||||
// metrics.
|
||||
podTargetLabels?: [...string]
|
||||
|
||||
// `sampleLimit` defines a per-scrape limit on the number of
|
||||
// scraped samples that will be accepted.
|
||||
sampleLimit?: int
|
||||
|
||||
// The scrape class to apply.
|
||||
scrapeClass?: strings.MinRunes(1)
|
||||
|
||||
// `scrapeProtocols` defines the protocols to negotiate during a
|
||||
// scrape. It tells clients the protocols supported by Prometheus
|
||||
// in order of preference (from most to least preferred).
|
||||
// If unset, Prometheus uses its default value.
|
||||
// It requires Prometheus >= v2.49.0.
|
||||
scrapeProtocols?: [..."PrometheusProto" | "OpenMetricsText0.0.1" | "OpenMetricsText1.0.0" | "PrometheusText0.0.4"]
|
||||
|
||||
// Label selector to select the Kubernetes `Endpoints` objects.
|
||||
selector: {
|
||||
// matchExpressions is a list of label selector requirements. The
|
||||
// requirements are ANDed.
|
||||
matchExpressions?: [...{
|
||||
// key is the label key that the selector applies to.
|
||||
key: string
|
||||
|
||||
// operator represents a key's relationship to a set of values.
|
||||
// Valid operators are In, NotIn, Exists and DoesNotExist.
|
||||
operator: string
|
||||
|
||||
// values is an array of string values. If the operator is In or
|
||||
// NotIn, the values array must be non-empty. If the operator is
|
||||
// Exists or DoesNotExist, the values array must be empty. This
|
||||
// array is replaced during a strategic merge patch.
|
||||
values?: [...string]
|
||||
}]
|
||||
|
||||
// matchLabels is a map of {key,value} pairs. A single {key,value}
|
||||
// in the matchLabels map is equivalent to an element of
|
||||
// matchExpressions, whose key field is "key", the operator is
|
||||
// "In", and the values array contains only "value". The
|
||||
// requirements are ANDed.
|
||||
matchLabels?: {
|
||||
[string]: string
|
||||
}
|
||||
}
|
||||
|
||||
// `targetLabels` defines the labels which are transferred from
|
||||
// the associated Kubernetes `Service` object onto the ingested
|
||||
// metrics.
|
||||
targetLabels?: [...string]
|
||||
|
||||
// `targetLimit` defines a limit on the number of scraped targets
|
||||
// that will be accepted.
|
||||
targetLimit?: int
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
26
docs/examples/managednamespaces.cue
Normal file
26
docs/examples/managednamespaces.cue
Normal file
@@ -0,0 +1,26 @@
|
||||
package holos
|
||||
|
||||
// NOTE: Beyond the base reference platform, services should typically be added to #OptionalServices instead of directly to a managed namespace.
|
||||
|
||||
// ManagedNamespace is a namespace to manage across all clusters in the holos platform.
|
||||
#ManagedNamespace: {
|
||||
namespace: {
|
||||
metadata: {
|
||||
name: string
|
||||
labels: [string]: string
|
||||
}
|
||||
}
|
||||
// clusterNames represents the set of clusters the namespace is managed on. Usually all clusters.
|
||||
clusterNames: [...string]
|
||||
for cluster in clusterNames {
|
||||
clusters: (cluster): name: cluster
|
||||
}
|
||||
}
|
||||
|
||||
// #ManagedNamepsaces is the union of all namespaces across all cluster types and optional services.
|
||||
// Holos adopts the namespace sameness position of SIG Multicluster, refer to https://github.com/kubernetes/community/blob/dd4c8b704ef1c9c3bfd928c6fa9234276d61ad18/sig-multicluster/namespace-sameness-position-statement.md
|
||||
#ManagedNamespaces: {
|
||||
[Name=_]: #ManagedNamespace & {
|
||||
namespace: metadata: name: Name
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
// Controls optional feature flags for services distributed across multiple holos components.
|
||||
// For example, enable issuing certificates in the provisioner cluster when an optional service is
|
||||
// enabled for a workload cluster.
|
||||
// enabled for a workload cluster. Another example is NATS, which isn't necessary on all clusters,
|
||||
// but is necessary on clusters with a project like holos which depends on NATS.
|
||||
|
||||
package holos
|
||||
|
||||
import "list"
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
To deploy monitoring:
|
||||
|
||||
> **_NOTE:_** For more detailed instructions on deploying, see the [documentation on installing Monitoring](https://access.crunchydata.com/documentation/postgres-operator/latest/installation/monitoring/kustomize).
|
||||
|
||||
1. verify the namespace is correct in kustomization.yaml
|
||||
2. If you are deploying in openshift, comment out the fsGroup line under securityContext in the following files:
|
||||
- `alertmanager/deployment.yaml`
|
||||
- `grafana/deployment.yaml`
|
||||
- `prometheus/deployment.yaml`
|
||||
3. kubectl apply -k .
|
||||
@@ -0,0 +1,78 @@
|
||||
###
|
||||
#
|
||||
# Copyright © 2017-2024 Crunchy Data Solutions, Inc. All Rights Reserved.
|
||||
#
|
||||
###
|
||||
|
||||
# Based on upstream example file found here: https://github.com/prometheus/alertmanager/blob/master/doc/examples/simple.yml
|
||||
global:
|
||||
smtp_smarthost: 'localhost: 25'
|
||||
smtp_require_tls: false
|
||||
smtp_from: 'Alertmanager <abc@yahoo.com>'
|
||||
# smtp_smarthost: 'smtp.example.com:587'
|
||||
# smtp_from: 'Alertmanager <abc@yahoo.com>'
|
||||
# smtp_auth_username: '<username>'
|
||||
# smtp_auth_password: '<password>'
|
||||
|
||||
# templates:
|
||||
# - '/etc/alertmanager/template/*.tmpl'
|
||||
|
||||
inhibit_rules:
|
||||
# Apply inhibition of warning if the alertname for the same system and service is already critical
|
||||
- source_match:
|
||||
severity: 'critical'
|
||||
target_match:
|
||||
severity: 'warning'
|
||||
equal: ['alertname', 'job', 'service']
|
||||
|
||||
receivers:
|
||||
- name: 'default-receiver'
|
||||
email_configs:
|
||||
- to: 'example@crunchydata.com'
|
||||
send_resolved: true
|
||||
|
||||
## Examples of alternative alert receivers. See documentation for more info on how to configure these fully
|
||||
#- name: 'pagerduty-dba'
|
||||
# pagerduty_configs:
|
||||
# - service_key: <RANDOMKEYSTUFF>
|
||||
|
||||
#- name: 'pagerduty-sre'
|
||||
# pagerduty_configs:
|
||||
# - service_key: <RANDOMKEYSTUFF>
|
||||
|
||||
#- name: 'dba-team'
|
||||
# email_configs:
|
||||
# - to: 'example-dba-team@crunchydata.com'
|
||||
# send_resolved: true
|
||||
|
||||
#- name: 'sre-team'
|
||||
# email_configs:
|
||||
# - to: 'example-sre-team@crunchydata.com'
|
||||
# send_resolved: true
|
||||
|
||||
route:
|
||||
receiver: default-receiver
|
||||
group_by: [severity, service, job, alertname]
|
||||
group_wait: 30s
|
||||
group_interval: 5m
|
||||
repeat_interval: 24h
|
||||
|
||||
## Example routes to show how to route outgoing alerts based on the content of that alert
|
||||
# routes:
|
||||
# - match_re:
|
||||
# service: ^(postgresql|mysql|oracle)$
|
||||
# receiver: dba-team
|
||||
# # sub route to send critical dba alerts to pagerduty
|
||||
# routes:
|
||||
# - match:
|
||||
# severity: critical
|
||||
# receiver: pagerduty-dba
|
||||
#
|
||||
# - match:
|
||||
# service: system
|
||||
# receiver: sre-team
|
||||
# # sub route to send critical sre alerts to pagerduty
|
||||
# routes:
|
||||
# - match:
|
||||
# severity: critical
|
||||
# receiver: pagerduty-sre
|
||||
@@ -0,0 +1,46 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: crunchy-alertmanager
|
||||
spec:
|
||||
selector: {}
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: alertmanager
|
||||
image: prom/alertmanager:v0.24.0
|
||||
args:
|
||||
- --config.file=/etc/alertmanager/alertmanager.yml
|
||||
- --storage.path=/alertmanager
|
||||
- --log.level=info
|
||||
- --cluster.advertise-address=0.0.0.0:9093
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /-/healthy
|
||||
port: 9093
|
||||
initialDelaySeconds: 25
|
||||
periodSeconds: 20
|
||||
ports:
|
||||
- containerPort: 9093
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /-/ready
|
||||
port: 9093
|
||||
volumeMounts:
|
||||
- mountPath: /etc/alertmanager
|
||||
name: alertmanagerconf
|
||||
- mountPath: /alertmanager
|
||||
name: alertmanagerdata
|
||||
securityContext:
|
||||
fsGroup: 26
|
||||
# supplementalGroups:
|
||||
# - 65534
|
||||
serviceAccountName: alertmanager
|
||||
volumes:
|
||||
- name: alertmanagerdata
|
||||
persistentVolumeClaim:
|
||||
claimName: alertmanagerdata
|
||||
- name: alertmanagerconf
|
||||
configMap:
|
||||
defaultMode: 420
|
||||
name: alertmanager-config
|
||||
@@ -0,0 +1,21 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
labels:
|
||||
- includeSelectors: true
|
||||
pairs:
|
||||
app.kubernetes.io/component: crunchy-alertmanager
|
||||
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- pvc.yaml
|
||||
- service.yaml
|
||||
- serviceaccount.yaml
|
||||
|
||||
configMapGenerator:
|
||||
- name: alertmanager-config
|
||||
files:
|
||||
- config/alertmanager.yml
|
||||
|
||||
generatorOptions:
|
||||
disableNameSuffixHash: true
|
||||
@@ -0,0 +1,10 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: alertmanagerdata
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 5Gi
|
||||
@@ -0,0 +1,9 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: crunchy-alertmanager
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- name: alertmanager
|
||||
port: 9093
|
||||
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: alertmanager
|
||||
@@ -0,0 +1,16 @@
|
||||
###
|
||||
#
|
||||
# Copyright © 2017-2024 Crunchy Data Solutions, Inc. All Rights Reserved.
|
||||
#
|
||||
###
|
||||
apiVersion: 1
|
||||
|
||||
providers:
|
||||
- name: 'crunchy_dashboards'
|
||||
orgId: 1
|
||||
folder: ''
|
||||
type: file
|
||||
disableDeletion: false
|
||||
updateIntervalSeconds: 3 #how often Grafana will scan for changed dashboards
|
||||
options:
|
||||
path: /etc/grafana/provisioning/dashboards
|
||||
@@ -0,0 +1,18 @@
|
||||
###
|
||||
#
|
||||
# Copyright © 2017-2024 Crunchy Data Solutions, Inc. All Rights Reserved.
|
||||
#
|
||||
###
|
||||
|
||||
# config file version
|
||||
apiVersion: 1
|
||||
|
||||
datasources:
|
||||
- name: PROMETHEUS
|
||||
type: prometheus
|
||||
access: proxy
|
||||
url: http://$PROM_HOST:$PROM_PORT
|
||||
isDefault: True
|
||||
editable: False
|
||||
orgId: 1
|
||||
version: 1
|
||||
@@ -0,0 +1,16 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
configMapGenerator:
|
||||
- name: grafana-dashboards
|
||||
files:
|
||||
- pgbackrest.json
|
||||
- pod_details.json
|
||||
- postgresql_overview.json
|
||||
- postgresql_details.json
|
||||
- postgresql_service_health.json
|
||||
- prometheus_alerts.json
|
||||
- query_statistics.json
|
||||
|
||||
generatorOptions:
|
||||
disableNameSuffixHash: true
|
||||
@@ -0,0 +1,687 @@
|
||||
{
|
||||
"__inputs": [
|
||||
{
|
||||
"name": "DS_PROMETHEUS",
|
||||
"label": "PROMETHEUS",
|
||||
"description": "",
|
||||
"type": "datasource",
|
||||
"pluginId": "prometheus",
|
||||
"pluginName": "Prometheus"
|
||||
}
|
||||
],
|
||||
"__requires": [
|
||||
{
|
||||
"type": "grafana",
|
||||
"id": "grafana",
|
||||
"name": "Grafana",
|
||||
"version": "7.4.5"
|
||||
},
|
||||
{
|
||||
"type": "panel",
|
||||
"id": "graph",
|
||||
"name": "Graph",
|
||||
"version": ""
|
||||
},
|
||||
{
|
||||
"type": "datasource",
|
||||
"id": "prometheus",
|
||||
"name": "Prometheus",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
{
|
||||
"type": "panel",
|
||||
"id": "stat",
|
||||
"name": "Stat",
|
||||
"version": ""
|
||||
}
|
||||
],
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": false,
|
||||
"gnetId": null,
|
||||
"graphTooltip": 0,
|
||||
"id": null,
|
||||
"iteration": 1625069660860,
|
||||
"links": [
|
||||
{
|
||||
"asDropdown": false,
|
||||
"icon": "external link",
|
||||
"includeVars": true,
|
||||
"keepTime": true,
|
||||
"tags": [
|
||||
"vendor=crunchydata"
|
||||
],
|
||||
"title": "",
|
||||
"type": "dashboards"
|
||||
}
|
||||
],
|
||||
"panels": [
|
||||
{
|
||||
"datasource": "PROMETHEUS",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"custom": {},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "semi-dark-blue",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "dtdhms"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 3,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 8,
|
||||
"options": {
|
||||
"colorMode": "background",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
"last"
|
||||
],
|
||||
"fields": "/^Value$/",
|
||||
"values": false
|
||||
},
|
||||
"text": {
|
||||
"valueSize": 45
|
||||
},
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "7.4.5",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "time()-ccp_backrest_oldest_full_backup_time_seconds{pg_cluster=\"[[cluster]]\", role=\"master\"}",
|
||||
"format": "table",
|
||||
"instant": true,
|
||||
"interval": "",
|
||||
"legendFormat": "Recovery window",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Recovery Window",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Differential": "dark-blue",
|
||||
"Differential Backup": "dark-blue",
|
||||
"Full": "dark-green",
|
||||
"Full Backup": "dark-green",
|
||||
"Incremental": "light-blue",
|
||||
"Incremental Backup": "light-blue"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "PROMETHEUS",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {},
|
||||
"links": []
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 3
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 2,
|
||||
"legend": {
|
||||
"alignAsTable": true,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": true,
|
||||
"show": true,
|
||||
"sideWidth": 150,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": false
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "7.4.5",
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "min(ccp_backrest_last_incr_backup_time_since_completion_seconds{pg_cluster=\"[[cluster]]\", role=\"master\"}) without(deployment,instance,ip,pod)",
|
||||
"format": "time_series",
|
||||
"instant": false,
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Incremental Backup",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "min(ccp_backrest_last_diff_backup_time_since_completion_seconds{pg_cluster=\"[[cluster]]\", role=\"master\"}) without(deployment, instance,ip,pod)",
|
||||
"hide": false,
|
||||
"interval": "",
|
||||
"legendFormat": "Differential Backup",
|
||||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"expr": "min(ccp_backrest_last_full_backup_time_since_completion_seconds{pg_cluster=\"[[cluster]]\", role=\"master\"}) without(deployment, instance,ip,pod)",
|
||||
"hide": false,
|
||||
"interval": "",
|
||||
"legendFormat": "Full Backup",
|
||||
"refId": "C"
|
||||
},
|
||||
{
|
||||
"expr": "min(ccp_archive_command_status_seconds_since_last_archive{pg_cluster=\"[[cluster]]\", role=\"master\"}) without(deployment, instance,ip,pod)",
|
||||
"hide": false,
|
||||
"interval": "",
|
||||
"legendFormat": "WAL Archive",
|
||||
"refId": "D"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "Time Since",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "s",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Differential": "dark-blue",
|
||||
"Full": "dark-green",
|
||||
"Incremental": "light-blue"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "PROMETHEUS",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {},
|
||||
"links": []
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 3
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 4,
|
||||
"legend": {
|
||||
"alignAsTable": true,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"hideEmpty": false,
|
||||
"hideZero": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": true,
|
||||
"show": true,
|
||||
"sideWidth": 150,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "7.4.5",
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "min(ccp_backrest_last_info_backup_runtime_seconds{pg_cluster=\"[[cluster]]\", role=\"master\", backup_type=\"incr\"}) without (deployment,instance,pod,ip)",
|
||||
"format": "time_series",
|
||||
"instant": false,
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Incremental",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "min(ccp_backrest_last_info_backup_runtime_seconds{pg_cluster=\"[[cluster]]\", role=\"master\", backup_type=\"diff\"}) without (deployment,instance,pod,ip)",
|
||||
"hide": false,
|
||||
"interval": "",
|
||||
"legendFormat": "Differential",
|
||||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"expr": "min(ccp_backrest_last_info_backup_runtime_seconds{pg_cluster=\"[[cluster]]\", role=\"master\", backup_type=\"full\"}) without (deployment,instance,pod,ip)",
|
||||
"hide": false,
|
||||
"interval": "",
|
||||
"legendFormat": "Full",
|
||||
"refId": "C"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "Backup Runtimes",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "s",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 2,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Differential": "dark-blue",
|
||||
"Full": "dark-green",
|
||||
"Incremental": "light-blue"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "PROMETHEUS",
|
||||
"description": "",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {},
|
||||
"links": []
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 10
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 5,
|
||||
"legend": {
|
||||
"alignAsTable": true,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"hideEmpty": false,
|
||||
"hideZero": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": true,
|
||||
"show": true,
|
||||
"sideWidth": 150,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "7.4.5",
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "min(ccp_backrest_last_info_repo_backup_size_bytes{pg_cluster=\"[[cluster]]\", role=\"master\", backup_type=\"incr\"}) without (deployment, instance,pod,ip)",
|
||||
"format": "time_series",
|
||||
"instant": false,
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Incremental",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "min(ccp_backrest_last_info_repo_backup_size_bytes{pg_cluster=\"[[cluster]]\", role=\"master\", backup_type=\"diff\"}) without (deployment,instance,pod,ip)",
|
||||
"hide": false,
|
||||
"interval": "",
|
||||
"legendFormat": "Differential",
|
||||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"expr": "min(ccp_backrest_last_info_repo_backup_size_bytes{pg_cluster=\"[[cluster]]\", role=\"master\", backup_type=\"full\"}) without (deployment,instance,pod,ip)",
|
||||
"hide": false,
|
||||
"interval": "",
|
||||
"legendFormat": "Full",
|
||||
"refId": "C"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "Backup Size",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "bytes",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 2,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Archive age": "blue",
|
||||
"Archive count": "green",
|
||||
"Differential": "dark-blue",
|
||||
"Failed count": "red",
|
||||
"Full": "dark-green",
|
||||
"Incremental": "light-blue"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "PROMETHEUS",
|
||||
"description": "",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {},
|
||||
"links": []
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"fill": 3,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 10
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 6,
|
||||
"legend": {
|
||||
"alignAsTable": true,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"hideEmpty": false,
|
||||
"hideZero": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": true,
|
||||
"show": true,
|
||||
"sideWidth": 150,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "7.4.5",
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "avg(idelta(ccp_archive_command_status_failed_count{pg_cluster=\"[[cluster]]\", role=\"master\"}[1m])) without (instance,ip)",
|
||||
"format": "time_series",
|
||||
"instant": false,
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Failed count",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "avg(idelta(ccp_archive_command_status_archived_count{pg_cluster=\"[[cluster]]\", role=\"master\"}[1m])) without (instance,pod, ip)",
|
||||
"hide": false,
|
||||
"interval": "",
|
||||
"legendFormat": "Archive count",
|
||||
"refId": "B"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "WAL Stats",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "short",
|
||||
"label": "",
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": "0",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": "0",
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"refresh": "5m",
|
||||
"schemaVersion": 27,
|
||||
"style": "dark",
|
||||
"tags": [
|
||||
"vendor=crunchydata"
|
||||
],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"allValue": null,
|
||||
"current": {},
|
||||
"datasource": "PROMETHEUS",
|
||||
"definition": "label_values(pg_cluster)",
|
||||
"description": null,
|
||||
"error": null,
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"label": "cluster",
|
||||
"multi": false,
|
||||
"name": "cluster",
|
||||
"options": [],
|
||||
"query": {
|
||||
"query": "label_values(pg_cluster)",
|
||||
"refId": "PROMETHEUS-cluster-Variable-Query"
|
||||
},
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"sort": 1,
|
||||
"tagValuesQuery": "",
|
||||
"tags": [],
|
||||
"tagsQuery": "",
|
||||
"type": "query",
|
||||
"useTags": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-2w",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"timezone": "browser",
|
||||
"title": "pgBackRest",
|
||||
"uid": "2fcFZ6PGk",
|
||||
"version": 1
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,237 @@
|
||||
{
|
||||
"__inputs": [
|
||||
{
|
||||
"name": "DS_PROMETHEUS",
|
||||
"label": "PROMETHEUS",
|
||||
"description": "",
|
||||
"type": "datasource",
|
||||
"pluginId": "prometheus",
|
||||
"pluginName": "Prometheus"
|
||||
}
|
||||
],
|
||||
"__requires": [
|
||||
{
|
||||
"type": "grafana",
|
||||
"id": "grafana",
|
||||
"name": "Grafana",
|
||||
"version": "7.4.5"
|
||||
},
|
||||
{
|
||||
"type": "datasource",
|
||||
"id": "prometheus",
|
||||
"name": "Prometheus",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
{
|
||||
"type": "panel",
|
||||
"id": "stat",
|
||||
"name": "Stat",
|
||||
"version": ""
|
||||
}
|
||||
],
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": false,
|
||||
"gnetId": null,
|
||||
"graphTooltip": 0,
|
||||
"id": null,
|
||||
"iteration": 1625069480601,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"cacheTimeout": null,
|
||||
"datasource": "PROMETHEUS",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"custom": {},
|
||||
"links": [
|
||||
{
|
||||
"targetBlank": true,
|
||||
"title": "Cluster Details",
|
||||
"url": "d/fMip0cuMk/postgresqldetails?$__all_variables"
|
||||
},
|
||||
{
|
||||
"targetBlank": true,
|
||||
"title": "Backup Details",
|
||||
"url": "d/2fcFZ6PGk/pgbackrest?$__all_variables"
|
||||
},
|
||||
{
|
||||
"targetBlank": true,
|
||||
"title": "Pod Details",
|
||||
"url": "d/4auP6Mk7k/pod-details?$__all_variables"
|
||||
},
|
||||
{
|
||||
"targetBlank": true,
|
||||
"title": "Query Statistics",
|
||||
"url": "d/ZKoTOHDGk/query-statistics?$__all_variables"
|
||||
},
|
||||
{
|
||||
"targetBlank": true,
|
||||
"title": "Service Health",
|
||||
"url": "d/dhG1wgsMz/postgresql-service-health?$__all_variables"
|
||||
}
|
||||
],
|
||||
"mappings": [
|
||||
{
|
||||
"from": "0",
|
||||
"id": 0,
|
||||
"text": "DOWN",
|
||||
"to": "99",
|
||||
"type": 2
|
||||
},
|
||||
{
|
||||
"from": "100",
|
||||
"id": 1,
|
||||
"text": "Standalone Cluster",
|
||||
"to": "199",
|
||||
"type": 2
|
||||
},
|
||||
{
|
||||
"from": "200",
|
||||
"id": 2,
|
||||
"text": "HA CLUSTER",
|
||||
"to": "1000",
|
||||
"type": 2
|
||||
}
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "#bf1b00",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "#eab839",
|
||||
"value": 10
|
||||
},
|
||||
{
|
||||
"color": "#56A64B",
|
||||
"value": 100
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 2,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 1,
|
||||
"interval": null,
|
||||
"links": [],
|
||||
"maxDataPoints": 100,
|
||||
"maxPerRow": 2,
|
||||
"options": {
|
||||
"colorMode": "background",
|
||||
"graphMode": "none",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "horizontal",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
"lastNotNull"
|
||||
],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"text": {
|
||||
"valueSize": 30
|
||||
},
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "7.4.5",
|
||||
"repeat": "cluster",
|
||||
"repeatDirection": "h",
|
||||
"targets": [
|
||||
{
|
||||
"$hashKey": "object:243",
|
||||
"expr": "sum(pg_up{pg_cluster=~\"$cluster\"})*100+sum(ccp_is_in_recovery_status{pg_cluster=~\"$cluster\"})",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "{{cluster}}",
|
||||
"metric": "up",
|
||||
"refId": "A",
|
||||
"step": 2
|
||||
}
|
||||
],
|
||||
"title": "$cluster - Overview",
|
||||
"type": "stat"
|
||||
}
|
||||
],
|
||||
"refresh": "5m",
|
||||
"schemaVersion": 27,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"allFormat": "glob",
|
||||
"allValue": null,
|
||||
"current": {},
|
||||
"datasource": "PROMETHEUS",
|
||||
"definition": "label_values(pg_cluster)",
|
||||
"description": null,
|
||||
"error": null,
|
||||
"hide": 1,
|
||||
"includeAll": true,
|
||||
"label": "cluster",
|
||||
"multi": true,
|
||||
"name": "cluster",
|
||||
"options": [],
|
||||
"query": {
|
||||
"query": "label_values(pg_cluster)",
|
||||
"refId": "PROMETHEUS-cluster-Variable-Query"
|
||||
},
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"sort": 0,
|
||||
"tagValuesQuery": "",
|
||||
"tags": [],
|
||||
"tagsQuery": "",
|
||||
"type": "query",
|
||||
"useTags": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-5m",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"timezone": "browser",
|
||||
"title": "PostgreSQL Overview",
|
||||
"uid": "D2X39SlGk",
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,649 @@
|
||||
{
|
||||
"__inputs": [
|
||||
{
|
||||
"name": "DS_PROMETHEUS",
|
||||
"label": "PROMETHEUS",
|
||||
"description": "",
|
||||
"type": "datasource",
|
||||
"pluginId": "prometheus",
|
||||
"pluginName": "Prometheus"
|
||||
}
|
||||
],
|
||||
"__requires": [
|
||||
{
|
||||
"type": "grafana",
|
||||
"id": "grafana",
|
||||
"name": "Grafana",
|
||||
"version": "7.4.5"
|
||||
},
|
||||
{
|
||||
"type": "panel",
|
||||
"id": "graph",
|
||||
"name": "Graph",
|
||||
"version": ""
|
||||
},
|
||||
{
|
||||
"type": "datasource",
|
||||
"id": "prometheus",
|
||||
"name": "Prometheus",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
],
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": false,
|
||||
"gnetId": null,
|
||||
"graphTooltip": 0,
|
||||
"id": null,
|
||||
"iteration": 1625069909806,
|
||||
"links": [
|
||||
{
|
||||
"asDropdown": false,
|
||||
"icon": "external link",
|
||||
"includeVars": true,
|
||||
"keepTime": true,
|
||||
"tags": [
|
||||
"vendor=crunchydata"
|
||||
],
|
||||
"title": "",
|
||||
"type": "dashboards"
|
||||
}
|
||||
],
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "PROMETHEUS",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {},
|
||||
"links": []
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 5,
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 6,
|
||||
"legend": {
|
||||
"alignAsTable": true,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": true,
|
||||
"show": true,
|
||||
"sideWidth": 150,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "7.4.5",
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(ccp_connection_stats_total{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}) without (pod,instance,ip) / sum(ccp_connection_stats_max_connections{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}) without (pod,instance,ip)",
|
||||
"format": "time_series",
|
||||
"instant": false,
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Connections",
|
||||
"refId": "C"
|
||||
},
|
||||
{
|
||||
"expr": "100 - 100 * avg(ccp_nodemx_data_disk_available_bytes{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}) without (pod,instance,ip) / avg(ccp_nodemx_data_disk_total_bytes{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}) without (pod,instance,ip)",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Mount:{{mount_point}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "Saturation (pct used)",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"decimals": null,
|
||||
"format": "percent",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": "100",
|
||||
"min": "0",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"cacheTimeout": null,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "PROMETHEUS",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {},
|
||||
"links": []
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 5,
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 0
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 18,
|
||||
"legend": {
|
||||
"alignAsTable": true,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": true,
|
||||
"show": true,
|
||||
"sideWidth": 150,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "7.4.5",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"exemplar": false,
|
||||
"expr": " sum(irate(ccp_stat_database_xact_commit{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}[1m])) \n+ sum(irate(ccp_stat_database_xact_rollback{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}[1m]))",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Transactions",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "max(ccp_connection_stats_active{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}) without (pod,instance,ip,dbname)",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Active connections",
|
||||
"refId": "C"
|
||||
},
|
||||
{
|
||||
"expr": "sum(irate(ccp_pg_stat_statements_total_calls_count{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}[1m]))",
|
||||
"format": "time_series",
|
||||
"hide": false,
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Queries",
|
||||
"refId": "B"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "Traffic",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "short",
|
||||
"label": "",
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": "0.001",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "PROMETHEUS",
|
||||
"description": "Errors",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {},
|
||||
"links": []
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 5,
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 7
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 4,
|
||||
"legend": {
|
||||
"alignAsTable": true,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": true,
|
||||
"show": true,
|
||||
"sideWidth": 150,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "7.4.5",
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(irate(ccp_stat_database_xact_rollback{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}[1m]) without(pod,instance,ip))",
|
||||
"format": "time_series",
|
||||
"hide": true,
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Rollbacks",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "sum(irate(ccp_stat_database_deadlocks{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}[1m])) without(pod,instance,ip,dbname)",
|
||||
"format": "time_series",
|
||||
"hide": false,
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Deadlock ",
|
||||
"refId": "D"
|
||||
},
|
||||
{
|
||||
"expr": "sum(irate(ccp_stat_database_conflicts{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}[1m])) without(pod,instance,ip,dbname)",
|
||||
"format": "time_series",
|
||||
"hide": false,
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Conflicts",
|
||||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"expr": "max(pg_exporter_last_scrape_error{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}) without(pod,instance,ip,dbname)",
|
||||
"format": "time_series",
|
||||
"hide": false,
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "scrape error",
|
||||
"refId": "C"
|
||||
},
|
||||
{
|
||||
"expr": "max(clamp_max(ccp_archive_command_status_seconds_since_last_fail{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"},1)) without (instance,pod,ip)",
|
||||
"format": "time_series",
|
||||
"hide": false,
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "archive error",
|
||||
"refId": "E"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "Errors",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"decimals": null,
|
||||
"format": "short",
|
||||
"label": "",
|
||||
"logBase": 2,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "PROMETHEUS",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {},
|
||||
"links": []
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 1,
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 7
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 10,
|
||||
"legend": {
|
||||
"alignAsTable": true,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": true,
|
||||
"show": true,
|
||||
"sideWidth": 150,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "7.4.5",
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [
|
||||
{
|
||||
"alias": "/Max:/",
|
||||
"color": "#E02F44",
|
||||
"nullPointMode": "null as zero"
|
||||
},
|
||||
{
|
||||
"alias": "/Avg:/",
|
||||
"color": "#8AB8FF"
|
||||
}
|
||||
],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "max(ccp_pg_stat_statements_total_mean_exec_time_ms{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}) without (pod,instance,ip)",
|
||||
"format": "time_series",
|
||||
"hide": false,
|
||||
"instant": false,
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Avg: {{exported_role}}({{dbname}})",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "max(ccp_pg_stat_statements_top_max_exec_time_ms{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}) without (pod,instance,ip,query,queryid)",
|
||||
"format": "time_series",
|
||||
"hide": false,
|
||||
"instant": false,
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Max: {{exported_role}}({{dbname}})",
|
||||
"refId": "B"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "Query Duration",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"decimals": null,
|
||||
"format": "ms",
|
||||
"label": null,
|
||||
"logBase": 2,
|
||||
"max": null,
|
||||
"min": "0",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"refresh": "5m",
|
||||
"schemaVersion": 27,
|
||||
"style": "dark",
|
||||
"tags": [
|
||||
"vendor=crunchydata"
|
||||
],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"allValue": null,
|
||||
"current": {},
|
||||
"datasource": "PROMETHEUS",
|
||||
"definition": "label_values(pg_cluster)",
|
||||
"description": null,
|
||||
"error": null,
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"label": null,
|
||||
"multi": false,
|
||||
"name": "cluster",
|
||||
"options": [],
|
||||
"query": {
|
||||
"query": "label_values(pg_cluster)",
|
||||
"refId": "PROMETHEUS-cluster-Variable-Query"
|
||||
},
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"sort": 0,
|
||||
"tagValuesQuery": "",
|
||||
"tags": [],
|
||||
"tagsQuery": "",
|
||||
"type": "query",
|
||||
"useTags": false
|
||||
},
|
||||
{
|
||||
"allValue": null,
|
||||
"current": {},
|
||||
"datasource": "PROMETHEUS",
|
||||
"definition": "label_values({pg_cluster=\"[[cluster]]\"},role)",
|
||||
"description": null,
|
||||
"error": null,
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"label": null,
|
||||
"multi": false,
|
||||
"name": "role",
|
||||
"options": [],
|
||||
"query": {
|
||||
"query": "label_values({pg_cluster=\"[[cluster]]\"},role)",
|
||||
"refId": "PROMETHEUS-role-Variable-Query"
|
||||
},
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"sort": 0,
|
||||
"tagValuesQuery": "",
|
||||
"tags": [],
|
||||
"tagsQuery": "",
|
||||
"type": "query",
|
||||
"useTags": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-1h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"timezone": "browser",
|
||||
"title": "PostgreSQL Service Health",
|
||||
"uid": "dhG1wgsMz",
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,961 @@
|
||||
{
|
||||
"__inputs": [
|
||||
{
|
||||
"name": "DS_PROMETHEUS",
|
||||
"label": "PROMETHEUS",
|
||||
"description": "",
|
||||
"type": "datasource",
|
||||
"pluginId": "prometheus",
|
||||
"pluginName": "Prometheus"
|
||||
}
|
||||
],
|
||||
"__requires": [
|
||||
{
|
||||
"type": "grafana",
|
||||
"id": "grafana",
|
||||
"name": "Grafana",
|
||||
"version": "7.4.5"
|
||||
},
|
||||
{
|
||||
"type": "datasource",
|
||||
"id": "prometheus",
|
||||
"name": "Prometheus",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
{
|
||||
"type": "panel",
|
||||
"id": "stat",
|
||||
"name": "Stat",
|
||||
"version": ""
|
||||
},
|
||||
{
|
||||
"type": "panel",
|
||||
"id": "table",
|
||||
"name": "Table",
|
||||
"version": ""
|
||||
}
|
||||
],
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": "Show current firing and pending alerts, and severity alert counts.",
|
||||
"editable": false,
|
||||
"gnetId": 4181,
|
||||
"graphTooltip": 0,
|
||||
"id": null,
|
||||
"links": [
|
||||
{
|
||||
"icon": "external link",
|
||||
"tags": [
|
||||
"vendor=crunchydata"
|
||||
],
|
||||
"type": "dashboards"
|
||||
}
|
||||
],
|
||||
"panels": [
|
||||
{
|
||||
"collapsed": false,
|
||||
"datasource": "PROMETHEUS",
|
||||
"gridPos": {
|
||||
"h": 1,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 10,
|
||||
"panels": [],
|
||||
"repeat": null,
|
||||
"title": "Environment Summary",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"cacheTimeout": null,
|
||||
"datasource": "PROMETHEUS",
|
||||
"description": "",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"custom": {},
|
||||
"mappings": [
|
||||
{
|
||||
"id": 0,
|
||||
"op": "=",
|
||||
"text": "N/A",
|
||||
"type": 1,
|
||||
"value": "null"
|
||||
}
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "semi-dark-blue",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "none"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 2,
|
||||
"w": 4,
|
||||
"x": 0,
|
||||
"y": 1
|
||||
},
|
||||
"id": 6,
|
||||
"interval": null,
|
||||
"links": [],
|
||||
"maxDataPoints": 100,
|
||||
"options": {
|
||||
"colorMode": "background",
|
||||
"graphMode": "none",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "horizontal",
|
||||
"reduceOptions": {
|
||||
"calcs": [],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"text": {},
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "7.4.5",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "count(count by (kubernetes_namespace) (pg_up))",
|
||||
"format": "time_series",
|
||||
"instant": true,
|
||||
"interval": "",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "Namespaces",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Namespaces",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"cacheTimeout": null,
|
||||
"datasource": "PROMETHEUS",
|
||||
"description": "",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"custom": {},
|
||||
"mappings": [
|
||||
{
|
||||
"id": 0,
|
||||
"op": "=",
|
||||
"text": "N/A",
|
||||
"type": 1,
|
||||
"value": "null"
|
||||
}
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "semi-dark-blue",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "none"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 2,
|
||||
"w": 4,
|
||||
"x": 4,
|
||||
"y": 1
|
||||
},
|
||||
"id": 13,
|
||||
"interval": null,
|
||||
"links": [],
|
||||
"maxDataPoints": 100,
|
||||
"options": {
|
||||
"colorMode": "background",
|
||||
"graphMode": "none",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "horizontal",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
"mean"
|
||||
],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"text": {},
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "7.4.5",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "count(count by (pg_cluster) (pg_up))",
|
||||
"format": "time_series",
|
||||
"instant": true,
|
||||
"interval": "",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "PostgreSQL Clusters",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "PG Clusters",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"cacheTimeout": null,
|
||||
"datasource": "PROMETHEUS",
|
||||
"description": "",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"custom": {},
|
||||
"mappings": [
|
||||
{
|
||||
"id": 0,
|
||||
"op": "=",
|
||||
"text": "N/A",
|
||||
"type": 1,
|
||||
"value": "null"
|
||||
}
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "semi-dark-blue",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "none"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 2,
|
||||
"w": 4,
|
||||
"x": 8,
|
||||
"y": 1
|
||||
},
|
||||
"id": 14,
|
||||
"interval": null,
|
||||
"links": [],
|
||||
"maxDataPoints": 100,
|
||||
"options": {
|
||||
"colorMode": "background",
|
||||
"graphMode": "none",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "horizontal",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
"mean"
|
||||
],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"text": {},
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "7.4.5",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "count(pg_up)",
|
||||
"format": "time_series",
|
||||
"instant": true,
|
||||
"interval": "",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "PostgreSQL Clusters",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "PG Instances",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"datasource": "PROMETHEUS",
|
||||
"gridPos": {
|
||||
"h": 1,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 3
|
||||
},
|
||||
"id": 11,
|
||||
"panels": [],
|
||||
"repeat": null,
|
||||
"title": "Alert Summary",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"cacheTimeout": null,
|
||||
"datasource": "PROMETHEUS",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"custom": {},
|
||||
"mappings": [
|
||||
{
|
||||
"id": 0,
|
||||
"op": "=",
|
||||
"text": "N/A",
|
||||
"type": 1,
|
||||
"value": "null"
|
||||
}
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "semi-dark-red",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "#F2495C",
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"color": "#F2495C"
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "none"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 2,
|
||||
"w": 4,
|
||||
"x": 0,
|
||||
"y": 4
|
||||
},
|
||||
"id": 2,
|
||||
"interval": null,
|
||||
"links": [],
|
||||
"maxDataPoints": 100,
|
||||
"options": {
|
||||
"colorMode": "background",
|
||||
"graphMode": "none",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "horizontal",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
"mean"
|
||||
],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"text": {},
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "7.4.5",
|
||||
"targets": [
|
||||
{
|
||||
"bucketAggs": [
|
||||
{
|
||||
"id": "2",
|
||||
"settings": {
|
||||
"interval": "auto",
|
||||
"min_doc_count": 0,
|
||||
"trimEdges": 0
|
||||
},
|
||||
"type": "date_histogram"
|
||||
}
|
||||
],
|
||||
"dsType": "elasticsearch",
|
||||
"expr": "sum(ALERTS{alertstate=\"firing\",severity=\"critical\"} > 0) OR on() vector(0)",
|
||||
"format": "time_series",
|
||||
"instant": true,
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Critical",
|
||||
"metrics": [
|
||||
{
|
||||
"field": "select field",
|
||||
"id": "1",
|
||||
"type": "count"
|
||||
}
|
||||
],
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Critical",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"cacheTimeout": null,
|
||||
"datasource": "PROMETHEUS",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"custom": {},
|
||||
"mappings": [
|
||||
{
|
||||
"id": 0,
|
||||
"op": "=",
|
||||
"text": "N/A",
|
||||
"type": 1,
|
||||
"value": "null"
|
||||
}
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "semi-dark-orange",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "none"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 2,
|
||||
"w": 4,
|
||||
"x": 4,
|
||||
"y": 4
|
||||
},
|
||||
"id": 5,
|
||||
"interval": null,
|
||||
"links": [],
|
||||
"maxDataPoints": 100,
|
||||
"options": {
|
||||
"colorMode": "background",
|
||||
"graphMode": "none",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "horizontal",
|
||||
"reduceOptions": {
|
||||
"calcs": [],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"text": {},
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "7.4.5",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(ALERTS{alertstate=\"firing\",severity=\"warning\"} > 0) OR on() vector(0)",
|
||||
"format": "time_series",
|
||||
"instant": true,
|
||||
"interval": "",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Warning",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"cacheTimeout": null,
|
||||
"datasource": "PROMETHEUS",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"custom": {},
|
||||
"mappings": [
|
||||
{
|
||||
"id": 0,
|
||||
"op": "=",
|
||||
"text": "N/A",
|
||||
"type": 1,
|
||||
"value": "null"
|
||||
}
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "#299c46",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "none"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 2,
|
||||
"w": 4,
|
||||
"x": 8,
|
||||
"y": 4
|
||||
},
|
||||
"id": 9,
|
||||
"interval": null,
|
||||
"links": [],
|
||||
"maxDataPoints": 100,
|
||||
"options": {
|
||||
"colorMode": "background",
|
||||
"graphMode": "none",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "horizontal",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
"mean"
|
||||
],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"text": {},
|
||||
"textMode": "auto"
|
||||
},
|
||||
"pluginVersion": "7.4.5",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(ALERTS{alertstate=\"firing\",severity=\"info\"} > 0) OR on() vector(0)",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Info",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"datasource": "PROMETHEUS",
|
||||
"gridPos": {
|
||||
"h": 1,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 6
|
||||
},
|
||||
"id": 12,
|
||||
"panels": [],
|
||||
"repeat": null,
|
||||
"title": "Alerts",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": "PROMETHEUS",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"custom": {
|
||||
"align": null,
|
||||
"displayMode": "auto",
|
||||
"filterable": true
|
||||
},
|
||||
"decimals": 2,
|
||||
"displayName": "",
|
||||
"mappings": [
|
||||
{
|
||||
"from": "",
|
||||
"id": 1,
|
||||
"text": "",
|
||||
"to": "",
|
||||
"type": 1,
|
||||
"value": ""
|
||||
}
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "blue",
|
||||
"value": 100
|
||||
},
|
||||
{
|
||||
"color": "#EAB839",
|
||||
"value": 200
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 300
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "severity_num"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.displayMode",
|
||||
"value": "color-background"
|
||||
},
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": 124
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Time"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": 170
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "severity"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": 119
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "alertname"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": 206
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "alertstate"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": 128
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 5,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 7
|
||||
},
|
||||
"id": 1,
|
||||
"links": [],
|
||||
"options": {
|
||||
"showHeader": true,
|
||||
"sortBy": []
|
||||
},
|
||||
"pluginVersion": "7.4.5",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "ALERTS{alertstate='firing'} > 0",
|
||||
"format": "table",
|
||||
"instant": true,
|
||||
"interval": "2s",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Firing",
|
||||
"transformations": [
|
||||
{
|
||||
"id": "merge",
|
||||
"options": {
|
||||
"reducers": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "organize",
|
||||
"options": {
|
||||
"excludeByName": {
|
||||
"Value": true,
|
||||
"__name__": true,
|
||||
"alertstate": false,
|
||||
"deployment": false,
|
||||
"exp_type": true,
|
||||
"fs_type": true,
|
||||
"instance": true,
|
||||
"job": true,
|
||||
"kubernetes_namespace": true,
|
||||
"mount_point": true,
|
||||
"server": true,
|
||||
"service": true,
|
||||
"severity_num": false
|
||||
},
|
||||
"indexByName": {
|
||||
"Time": 0,
|
||||
"Value": 16,
|
||||
"__name__": 3,
|
||||
"alertname": 4,
|
||||
"alertstate": 5,
|
||||
"deployment": 7,
|
||||
"exp_type": 9,
|
||||
"instance": 10,
|
||||
"ip": 11,
|
||||
"job": 12,
|
||||
"kubernetes_namespace": 13,
|
||||
"pg_cluster": 6,
|
||||
"pod": 8,
|
||||
"role": 14,
|
||||
"service": 15,
|
||||
"severity": 2,
|
||||
"severity_num": 1
|
||||
},
|
||||
"renameByName": {
|
||||
"Time": "",
|
||||
"__name__": "",
|
||||
"severity": "",
|
||||
"severity_num": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"type": "table"
|
||||
},
|
||||
{
|
||||
"datasource": "PROMETHEUS",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"custom": {
|
||||
"align": null,
|
||||
"filterable": true
|
||||
},
|
||||
"decimals": 2,
|
||||
"displayName": "",
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byRegexp",
|
||||
"options": "/(instance|__name__|Time|alertstate|job|type|Value)/"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "unit",
|
||||
"value": "short"
|
||||
},
|
||||
{
|
||||
"id": "decimals",
|
||||
"value": 2
|
||||
},
|
||||
{
|
||||
"id": "custom.align",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Time"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "severity_num"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": 126
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "severity"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": 115
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "alertname"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": 207
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "alertstate"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": 131
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 12
|
||||
},
|
||||
"id": 3,
|
||||
"links": [],
|
||||
"options": {
|
||||
"showHeader": true,
|
||||
"sortBy": []
|
||||
},
|
||||
"pluginVersion": "7.4.5",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "ALERTS{alertstate=\"pending\"}",
|
||||
"format": "table",
|
||||
"instant": false,
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Alerts (1 week)",
|
||||
"transformations": [
|
||||
{
|
||||
"id": "organize",
|
||||
"options": {
|
||||
"excludeByName": {
|
||||
"Value": true,
|
||||
"__name__": true,
|
||||
"exp_type": true,
|
||||
"instance": true,
|
||||
"job": true,
|
||||
"kubernetes_namespace": true,
|
||||
"service": true
|
||||
},
|
||||
"indexByName": {
|
||||
"Time": 0,
|
||||
"Value": 16,
|
||||
"__name__": 3,
|
||||
"alertname": 4,
|
||||
"alertstate": 5,
|
||||
"deployment": 7,
|
||||
"exp_type": 8,
|
||||
"instance": 9,
|
||||
"ip": 11,
|
||||
"job": 12,
|
||||
"kubernetes_namespace": 13,
|
||||
"pg_cluster": 6,
|
||||
"pod": 10,
|
||||
"role": 14,
|
||||
"service": 15,
|
||||
"severity": 2,
|
||||
"severity_num": 1
|
||||
},
|
||||
"renameByName": {}
|
||||
}
|
||||
}
|
||||
],
|
||||
"type": "table"
|
||||
}
|
||||
],
|
||||
"refresh": "15m",
|
||||
"schemaVersion": 27,
|
||||
"style": "dark",
|
||||
"tags": [
|
||||
"vendor=crunchydata"
|
||||
],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-1h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"timezone": "browser",
|
||||
"title": "Prometheus Alerts",
|
||||
"uid": "lwxXsZsMk",
|
||||
"version": 1
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,64 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: crunchy-grafana
|
||||
spec:
|
||||
selector: {}
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: grafana
|
||||
image: grafana/grafana:9.2.20
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
env:
|
||||
- name: GF_PATHS_DATA
|
||||
value: /data/grafana/data
|
||||
- name: GF_SECURITY_ADMIN_USER__FILE
|
||||
value: /conf/admin/username
|
||||
- name: GF_SECURITY_ADMIN_PASSWORD__FILE
|
||||
value: /conf/admin/password
|
||||
- name: PROM_HOST
|
||||
value: crunchy-prometheus
|
||||
- name: PROM_PORT
|
||||
value: "9090"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /api/health
|
||||
port: 3000
|
||||
initialDelaySeconds: 25
|
||||
periodSeconds: 20
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /api/health
|
||||
port: 3000
|
||||
volumeMounts:
|
||||
- mountPath: /data
|
||||
name: grafanadata
|
||||
- mountPath: /conf/admin
|
||||
name: grafana-admin
|
||||
- mountPath: /etc/grafana/provisioning/datasources
|
||||
name: grafana-datasources
|
||||
- mountPath: /etc/grafana/provisioning/dashboards
|
||||
name: grafana-dashboards
|
||||
securityContext:
|
||||
fsGroup: 26
|
||||
# supplementalGroups:
|
||||
# - 65534
|
||||
serviceAccountName: grafana
|
||||
volumes:
|
||||
- name: grafanadata
|
||||
persistentVolumeClaim:
|
||||
claimName: grafanadata
|
||||
- name: grafana-admin
|
||||
secret:
|
||||
defaultMode: 420
|
||||
secretName: grafana-admin
|
||||
- name: grafana-datasources
|
||||
configMap:
|
||||
defaultMode: 420
|
||||
name: grafana-datasources
|
||||
- name: grafana-dashboards
|
||||
configMap:
|
||||
defaultMode: 420
|
||||
name: grafana-dashboards
|
||||
@@ -0,0 +1,33 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
labels:
|
||||
- includeSelectors: true
|
||||
pairs:
|
||||
app.kubernetes.io/component: crunchy-grafana
|
||||
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- pvc.yaml
|
||||
- service.yaml
|
||||
- serviceaccount.yaml
|
||||
- dashboards
|
||||
|
||||
configMapGenerator:
|
||||
- name: grafana-datasources
|
||||
files:
|
||||
- config/crunchy_grafana_datasource.yml
|
||||
- name: grafana-dashboards
|
||||
behavior: merge
|
||||
files:
|
||||
- config/crunchy_grafana_dashboards.yml
|
||||
|
||||
secretGenerator:
|
||||
- name: grafana-admin
|
||||
literals:
|
||||
- password=admin
|
||||
- username=admin
|
||||
type: Opaque
|
||||
|
||||
generatorOptions:
|
||||
disableNameSuffixHash: true
|
||||
@@ -0,0 +1,10 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: grafanadata
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 5Gi
|
||||
@@ -0,0 +1,9 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: crunchy-grafana
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- name: grafana
|
||||
port: 3000
|
||||
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: grafana
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: prod-iam
|
||||
|
||||
labels:
|
||||
- includeSelectors: true
|
||||
pairs:
|
||||
app.kubernetes.io/name: prod-iam-obs
|
||||
vendor: holos
|
||||
|
||||
resources:
|
||||
- grafana
|
||||
- prometheus
|
||||
- alertmanager
|
||||
@@ -0,0 +1,9 @@
|
||||
package holos
|
||||
|
||||
spec: components: KustomizeBuildList: [
|
||||
#KustomizeBuild & {
|
||||
_dependsOn: "prod-secrets-stores": _
|
||||
|
||||
metadata: name: "prod-iam-obs"
|
||||
},
|
||||
]
|
||||
@@ -0,0 +1,13 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: prometheus
|
||||
rules:
|
||||
- resources:
|
||||
- pods
|
||||
apiGroups:
|
||||
- ""
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
@@ -0,0 +1,11 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: prometheus
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: prometheus
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: prometheus
|
||||
@@ -0,0 +1,418 @@
|
||||
###
|
||||
#
|
||||
# Copyright © 2017-2024 Crunchy Data Solutions, Inc. All Rights Reserved.
|
||||
#
|
||||
###
|
||||
|
||||
groups:
|
||||
- name: alert-rules
|
||||
rules:
|
||||
|
||||
########## EXPORTER RULES ##########
|
||||
- alert: PGExporterScrapeError
|
||||
expr: pg_exporter_last_scrape_error > 0
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: critical
|
||||
severity_num: 300
|
||||
annotations:
|
||||
summary: 'Postgres Exporter running on {{ $labels.job }} (instance: {{ $labels.instance }}) is encountering scrape errors processing queries. Error count: ( {{ $value }} )'
|
||||
|
||||
|
||||
########## SYSTEM RULES ##########
|
||||
- alert: ExporterDown
|
||||
expr: avg_over_time(up[5m]) < 0.5
|
||||
for: 10s
|
||||
labels:
|
||||
service: system
|
||||
severity: critical
|
||||
severity_num: 300
|
||||
annotations:
|
||||
description: 'Metrics exporter service for {{ $labels.job }} running on {{ $labels.instance }} has been down at least 50% of the time for the last 5 minutes. Service may be flapping or down.'
|
||||
summary: 'Prometheus Exporter Service Down'
|
||||
|
||||
|
||||
########## POSTGRESQL RULES ##########
|
||||
- alert: PGIsUp
|
||||
expr: pg_up < 1
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: critical
|
||||
severity_num: 300
|
||||
annotations:
|
||||
summary: 'postgres_exporter running on {{ $labels.job }} is unable to communicate with the configured database'
|
||||
|
||||
|
||||
# Example to check for current version of PostgreSQL. Metric returns the version that the exporter is running on, so you can set a rule to check for the minimum version you'd like all systems to be on. Number returned is the 6 digit integer representation contained in the setting "server_version_num".
|
||||
#
|
||||
# - alert: PGMinimumVersion
|
||||
# expr: ccp_postgresql_version_current < 110005
|
||||
# for: 60s
|
||||
# labels:
|
||||
# service: postgresql
|
||||
# severity: critical
|
||||
# severity_num: 300
|
||||
# annotations:
|
||||
# summary: '{{ $labels.job }} is not running at least version 11.5 of PostgreSQL'
|
||||
|
||||
|
||||
# Whether a system switches from primary to replica or vice versa must be configured per named job.
|
||||
# No way to tell what value a system is supposed to be without a rule expression for that specific system
|
||||
# 2 to 1 means it changed from primary to replica. 1 to 2 means it changed from replica to primary
|
||||
# Set this alert for each system that you want to monitor a recovery status change
|
||||
# Below is an example for a target job called "Replica" and watches for the value to change above 1 which means it's no longer a replica
|
||||
#
|
||||
# - alert: PGRecoveryStatusSwitch_Replica
|
||||
# expr: ccp_is_in_recovery_status{job="Replica"} > 1
|
||||
# for: 60s
|
||||
# labels:
|
||||
# service: postgresql
|
||||
# severity: critical
|
||||
# severity_num: 300
|
||||
# annotations:
|
||||
# summary: '{{ $labels.job }} has changed from replica to primary'
|
||||
|
||||
|
||||
# Absence alerts must be configured per named job, otherwise there's no way to know which job is down
|
||||
# Below is an example for a target job called "Prod"
|
||||
# - alert: PGConnectionAbsent_Prod
|
||||
# expr: absent(ccp_connection_stats_max_connections{job="Prod"})
|
||||
# for: 10s
|
||||
# labels:
|
||||
# service: postgresql
|
||||
# severity: critical
|
||||
# severity_num: 300
|
||||
# annotations:
|
||||
# description: 'Connection metric is absent from target (Prod). Check that postgres_exporter can connect to PostgreSQL.'
|
||||
|
||||
|
||||
# Optional monitor for changes to pg_settings (postgresql.conf) system catalog.
|
||||
# A similar metric is available for monitoring pg_hba.conf. See ccp_hba_settings_checksum().
|
||||
# If metric returns 0, then NO settings have changed for either pg_settings since last known valid state
|
||||
# If metric returns 1, then pg_settings have changed since last known valid state
|
||||
# To see what may have changed, check the monitor.pg_settings_checksum table for a history of config state.
|
||||
# - alert: PGSettingsChecksum
|
||||
# expr: ccp_pg_settings_checksum > 0
|
||||
# for 60s
|
||||
# labels:
|
||||
# service: postgresql
|
||||
# severity: critical
|
||||
# severity_num: 300
|
||||
# annotations:
|
||||
# description: 'Configuration settings on {{ $labels.job }} have changed from previously known valid state. To reset current config to a valid state after alert fires, run monitor.pg_settings_checksum_set_valid().'
|
||||
# summary: 'PGSQL Instance settings checksum'
|
||||
|
||||
|
||||
# Monitor for data block checksum failures. Only works in PG12+
|
||||
# - alert: PGDataChecksum
|
||||
# expr: ccp_data_checksum_failure > 0
|
||||
# for 60s
|
||||
# labels:
|
||||
# service: postgresql
|
||||
# severity: critical
|
||||
# severity_num: 300
|
||||
# annotations:
|
||||
# description: '{{ $labels.job }} has at least one data checksum failure in database {{ $labels.dbname }}. See pg_stat_database system catalog for more information.'
|
||||
# summary: 'PGSQL Data Checksum failure'
|
||||
|
||||
- alert: PGIdleTxn
|
||||
expr: ccp_connection_stats_max_idle_in_txn_time > 300
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: warning
|
||||
severity_num: 200
|
||||
annotations:
|
||||
description: '{{ $labels.job }} has at least one session idle in transaction for over 5 minutes.'
|
||||
summary: 'PGSQL Instance idle transactions'
|
||||
|
||||
- alert: PGIdleTxn
|
||||
expr: ccp_connection_stats_max_idle_in_txn_time > 900
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: critical
|
||||
severity_num: 300
|
||||
annotations:
|
||||
description: '{{ $labels.job }} has at least one session idle in transaction for over 15 minutes.'
|
||||
summary: 'PGSQL Instance idle transactions'
|
||||
|
||||
- alert: PGQueryTime
|
||||
expr: ccp_connection_stats_max_query_time > 43200
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: warning
|
||||
severity_num: 200
|
||||
annotations:
|
||||
description: '{{ $labels.job }} has at least one query running for over 12 hours.'
|
||||
summary: 'PGSQL Max Query Runtime'
|
||||
|
||||
- alert: PGQueryTime
|
||||
expr: ccp_connection_stats_max_query_time > 86400
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: critical
|
||||
severity_num: 300
|
||||
annotations:
|
||||
description: '{{ $labels.job }} has at least one query running for over 1 day.'
|
||||
summary: 'PGSQL Max Query Runtime'
|
||||
|
||||
- alert: PGConnPerc
|
||||
expr: 100 * (ccp_connection_stats_total / ccp_connection_stats_max_connections) > 75
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: warning
|
||||
severity_num: 200
|
||||
annotations:
|
||||
description: '{{ $labels.job }} is using 75% or more of available connections ({{ $value }}%)'
|
||||
summary: 'PGSQL Instance connections'
|
||||
|
||||
- alert: PGConnPerc
|
||||
expr: 100 * (ccp_connection_stats_total / ccp_connection_stats_max_connections) > 90
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: critical
|
||||
severity_num: 300
|
||||
annotations:
|
||||
description: '{{ $labels.job }} is using 90% or more of available connections ({{ $value }}%)'
|
||||
summary: 'PGSQL Instance connections'
|
||||
|
||||
- alert: DiskFillPredict
|
||||
expr: predict_linear(ccp_nodemx_data_disk_available_bytes{mount_point!~"tmpfs"}[1h], 24 * 3600) < 0 and 100 * ((ccp_nodemx_data_disk_total_bytes - ccp_nodemx_data_disk_available_bytes) / ccp_nodemx_data_disk_total_bytes) > 70
|
||||
for: 5m
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: warning
|
||||
severity_num: 200
|
||||
annotations:
|
||||
summary: 'Disk predicted to be full in 24 hours'
|
||||
description: 'Disk on {{ $labels.pg_cluster }}:{{ $labels.kubernetes_pod_name }} is predicted to fill in 24 hrs based on current usage'
|
||||
|
||||
- alert: PGClusterRoleChange
|
||||
expr: count by (pg_cluster) (ccp_is_in_recovery_status != ignoring(instance,ip,pod,role) (ccp_is_in_recovery_status offset 5m)) >= 1
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: critical
|
||||
severity_num: 300
|
||||
annotations:
|
||||
summary: '{{ $labels.pg_cluster }} has had a switchover/failover event. Please check this cluster for more details'
|
||||
|
||||
- alert: PGDiskSize
|
||||
expr: 100 * ((ccp_nodemx_data_disk_total_bytes - ccp_nodemx_data_disk_available_bytes) / ccp_nodemx_data_disk_total_bytes) > 75
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: warning
|
||||
severity_num: 200
|
||||
annotations:
|
||||
description: 'PGSQL Instance {{ $labels.deployment }} over 75% disk usage at mount point "{{ $labels.mount_point }}": {{ $value }}%'
|
||||
summary: PGSQL Instance usage warning
|
||||
|
||||
- alert: PGDiskSize
|
||||
expr: 100 * ((ccp_nodemx_data_disk_total_bytes - ccp_nodemx_data_disk_available_bytes) / ccp_nodemx_data_disk_total_bytes) > 90
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: critical
|
||||
severity_num: 300
|
||||
annotations:
|
||||
description: 'PGSQL Instance {{ $labels.deployment }} over 90% disk usage at mount point "{{ $labels.mount_point }}": {{ $value }}%'
|
||||
summary: 'PGSQL Instance size critical'
|
||||
|
||||
- alert: PGReplicationByteLag
|
||||
expr: ccp_replication_lag_size_bytes > 5.24288e+07
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: warning
|
||||
severity_num: 200
|
||||
annotations:
|
||||
description: 'PGSQL Instance {{ $labels.job }} has at least one replica lagging over 50MB behind.'
|
||||
summary: 'PGSQL Instance replica lag warning'
|
||||
|
||||
- alert: PGReplicationByteLag
|
||||
expr: ccp_replication_lag_size_bytes > 1.048576e+08
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: critical
|
||||
severity_num: 300
|
||||
annotations:
|
||||
description: 'PGSQL Instance {{ $labels.job }} has at least one replica lagging over 100MB behind.'
|
||||
summary: 'PGSQL Instance replica lag warning'
|
||||
|
||||
- alert: PGReplicationSlotsInactive
|
||||
expr: ccp_replication_slots_active == 0
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: critical
|
||||
severity_num: 300
|
||||
annotations:
|
||||
description: 'PGSQL Instance {{ $labels.job }} has one or more inactive replication slots'
|
||||
summary: 'PGSQL Instance inactive replication slot'
|
||||
|
||||
- alert: PGXIDWraparound
|
||||
expr: ccp_transaction_wraparound_percent_towards_wraparound > 50
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: warning
|
||||
severity_num: 200
|
||||
annotations:
|
||||
description: 'PGSQL Instance {{ $labels.job }} is over 50% towards transaction id wraparound.'
|
||||
summary: 'PGSQL Instance {{ $labels.job }} transaction id wraparound imminent'
|
||||
|
||||
- alert: PGXIDWraparound
|
||||
expr: ccp_transaction_wraparound_percent_towards_wraparound > 75
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: critical
|
||||
severity_num: 300
|
||||
annotations:
|
||||
description: 'PGSQL Instance {{ $labels.job }} is over 75% towards transaction id wraparound.'
|
||||
summary: 'PGSQL Instance transaction id wraparound imminent'
|
||||
|
||||
- alert: PGEmergencyVacuum
|
||||
expr: ccp_transaction_wraparound_percent_towards_emergency_autovac > 110
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: warning
|
||||
severity_num: 200
|
||||
annotations:
|
||||
description: 'PGSQL Instance {{ $labels.job }} is over 110% beyond autovacuum_freeze_max_age value. Autovacuum may need tuning to better keep up.'
|
||||
summary: 'PGSQL Instance emergency vacuum imminent'
|
||||
|
||||
- alert: PGEmergencyVacuum
|
||||
expr: ccp_transaction_wraparound_percent_towards_emergency_autovac > 125
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: critical
|
||||
severity_num: 300
|
||||
annotations:
|
||||
description: 'PGSQL Instance {{ $labels.job }} is over 125% beyond autovacuum_freeze_max_age value. Autovacuum needs tuning to better keep up.'
|
||||
summary: 'PGSQL Instance emergency vacuum imminent'
|
||||
|
||||
- alert: PGArchiveCommandStatus
|
||||
expr: ccp_archive_command_status_seconds_since_last_fail > 300
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: critical
|
||||
severity_num: 300
|
||||
annotations:
|
||||
description: 'PGSQL Instance {{ $labels.job }} has a recent failing archive command'
|
||||
summary: 'Seconds since the last recorded failure of the archive_command'
|
||||
|
||||
- alert: PGSequenceExhaustion
|
||||
expr: ccp_sequence_exhaustion_count > 0
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: critical
|
||||
severity_num: 300
|
||||
annotations:
|
||||
description: 'Count of sequences on instance {{ $labels.job }} at over 75% usage: {{ $value }}. Run following query to see full sequence status: SELECT * FROM monitor.sequence_status() WHERE percent >= 75'
|
||||
|
||||
- alert: PGSettingsPendingRestart
|
||||
expr: ccp_settings_pending_restart_count > 0
|
||||
for: 60s
|
||||
labels:
|
||||
service: postgresql
|
||||
severity: critical
|
||||
severity_num: 300
|
||||
annotations:
|
||||
description: 'One or more settings in the pg_settings system catalog on system {{ $labels.job }} are in a pending_restart state. Check the system catalog for which settings are pending and review postgresql.conf for changes.'
|
||||
|
||||
########## PGBACKREST RULES ##########
|
||||
#
|
||||
# Uncomment and customize one or more of these rules to monitor your pgbackrest backups.
|
||||
# Full backups are considered the equivalent of both differentials and incrementals since both are based on the last full
|
||||
# And differentials are considered incrementals since incrementals will be based off the last diff if one exists
|
||||
# This avoid false alerts, for example when you don't run diff/incr backups on the days that you run a full
|
||||
# Stanza should also be set if different intervals are expected for each stanza.
|
||||
# Otherwise rule will be applied to all stanzas returned on target system if not set.
|
||||
#
|
||||
# Relevant metric names are:
|
||||
# ccp_backrest_last_full_backup_time_since_completion_seconds
|
||||
# ccp_backrest_last_incr_backup_time_since_completion_seconds
|
||||
# ccp_backrest_last_diff_backup_time_since_completion_seconds
|
||||
#
|
||||
# To avoid false positives on backup time alerts, 12 hours are added onto each threshold to allow a buffer if the backup runtime varies from day to day.
|
||||
# Further adjustment may be needed depending on your backup runtimes/schedule.
|
||||
#
|
||||
# - alert: PGBackRestLastCompletedFull_main
|
||||
# expr: ccp_backrest_last_full_backup_time_since_completion_seconds{stanza="main"} > 648000
|
||||
# for: 60s
|
||||
# labels:
|
||||
# service: postgresql
|
||||
# severity: critical
|
||||
# severity_num: 300
|
||||
# annotations:
|
||||
# summary: 'Full backup for stanza [main] on system {{ $labels.job }} has not completed in the last week.'
|
||||
#
|
||||
# - alert: PGBackRestLastCompletedIncr_main
|
||||
# expr: ccp_backrest_last_incr_backup_time_since_completion_seconds{stanza="main"} > 129600
|
||||
# for: 60s
|
||||
# labels:
|
||||
# service: postgresql
|
||||
# severity: critical
|
||||
# severity_num: 300
|
||||
# annotations:
|
||||
# summary: 'Incremental backup for stanza [main] on system {{ $labels.job }} has not completed in the last 24 hours.'
|
||||
#
|
||||
#
|
||||
# Runtime monitoring is handled with a single metric:
|
||||
#
|
||||
# ccp_backrest_last_info_backup_runtime_seconds
|
||||
#
|
||||
# Runtime monitoring should have the "backup_type" label set.
|
||||
# Otherwise the rule will apply to the last run of all backup types returned (full, diff, incr)
|
||||
# Stanza should also be set if runtimes per stanza have different expected times
|
||||
#
|
||||
# - alert: PGBackRestLastRuntimeFull_main
|
||||
# expr: ccp_backrest_last_info_backup_runtime_seconds{backup_type="full", stanza="main"} > 14400
|
||||
# for: 60s
|
||||
# labels:
|
||||
# service: postgresql
|
||||
# severity: critical
|
||||
# severity_num: 300
|
||||
# annotations:
|
||||
# summary: 'Expected runtime of full backup for stanza [main] has exceeded 4 hours'
|
||||
#
|
||||
# - alert: PGBackRestLastRuntimeDiff_main
|
||||
# expr: ccp_backrest_last_info_backup_runtime_seconds{backup_type="diff", stanza="main"} > 3600
|
||||
# for: 60s
|
||||
# labels:
|
||||
# service: postgresql
|
||||
# severity: critical
|
||||
# severity_num: 300
|
||||
# annotations:
|
||||
# summary: 'Expected runtime of diff backup for stanza [main] has exceeded 1 hour'
|
||||
##
|
||||
#
|
||||
## If the pgbackrest command fails to run, the metric disappears from the exporter output and the alert never fires.
|
||||
## An absence alert must be configured explicitly for each target (job) that backups are being monitored.
|
||||
## Checking for absence of just the full backup type should be sufficient (no need for diff/incr).
|
||||
## Note that while the backrest check command failing will likely also cause a scrape error alert, the addition of this
|
||||
## check gives a clearer answer as to what is causing it and that something is wrong with the backups.
|
||||
#
|
||||
# - alert: PGBackrestAbsentFull_Prod
|
||||
# expr: absent(ccp_backrest_last_full_backup_time_since_completion_seconds{job="Prod"})
|
||||
# for: 10s
|
||||
# labels:
|
||||
# service: postgresql
|
||||
# severity: critical
|
||||
# severity_num: 300
|
||||
# annotations:
|
||||
# description: 'Backup Full status missing for Prod. Check that pgbackrest info command is working on target system.'
|
||||
@@ -0,0 +1,85 @@
|
||||
###
|
||||
#
|
||||
# Copyright © 2017-2024 Crunchy Data Solutions, Inc. All Rights Reserved.
|
||||
#
|
||||
###
|
||||
---
|
||||
global:
|
||||
scrape_interval: 15s
|
||||
scrape_timeout: 15s
|
||||
evaluation_interval: 5s
|
||||
|
||||
scrape_configs:
|
||||
- job_name: 'crunchy-postgres-exporter'
|
||||
kubernetes_sd_configs:
|
||||
- role: pod
|
||||
selectors:
|
||||
- role: pod
|
||||
label: postgres-operator.crunchydata.com/crunchy-postgres-exporter=true
|
||||
relabel_configs:
|
||||
# Keep exporter port and drop all others
|
||||
- source_labels: [__meta_kubernetes_pod_container_port_number]
|
||||
action: keep
|
||||
regex: 9187
|
||||
# Set label for namespace
|
||||
- source_labels: [__meta_kubernetes_namespace]
|
||||
target_label: kubernetes_namespace
|
||||
# Set label for pod name
|
||||
- source_labels: [__meta_kubernetes_pod_name]
|
||||
target_label: pod
|
||||
# Convert namespace and cluster name to pg_cluster=namespace:cluster
|
||||
- source_labels: [__meta_kubernetes_namespace,__meta_kubernetes_pod_label_postgres_operator_crunchydata_com_cluster]
|
||||
target_label: pg_cluster
|
||||
separator: ":"
|
||||
replacement: '$1$2'
|
||||
# Convert kubernetes pod ip to ip
|
||||
- source_labels: [__meta_kubernetes_pod_ip]
|
||||
target_label: ip
|
||||
# Convert postgres-operator.crunchydata.com/instance to deployment
|
||||
- source_labels: [__meta_kubernetes_pod_label_postgres_operator_crunchydata_com_instance]
|
||||
target_label: deployment
|
||||
# Convert postgres-operator.crunchydata.com/role to role
|
||||
- source_labels: [__meta_kubernetes_pod_label_postgres_operator_crunchydata_com_role]
|
||||
target_label: role
|
||||
|
||||
- job_name: 'crunchy-postgres-exporter-v4'
|
||||
kubernetes_sd_configs:
|
||||
- role: pod
|
||||
selectors:
|
||||
- role: pod
|
||||
label: crunchy-postgres-exporter=true
|
||||
|
||||
relabel_configs:
|
||||
# Keep exporter port and drop all others
|
||||
- source_labels: [__meta_kubernetes_pod_container_port_number]
|
||||
action: keep
|
||||
regex: 9187
|
||||
# Set label for namespace
|
||||
- source_labels: [__meta_kubernetes_namespace]
|
||||
target_label: kubernetes_namespace
|
||||
# Set label for pod name
|
||||
- source_labels: [__meta_kubernetes_pod_name]
|
||||
target_label: pod
|
||||
# Convert namespace and cluster name to pg_cluster=namespace:cluster
|
||||
- source_labels: [__meta_kubernetes_namespace,__meta_kubernetes_pod_label_pg_cluster]
|
||||
target_label: pg_cluster
|
||||
separator: ":"
|
||||
replacement: '$1$2'
|
||||
# Convert kubernetes pod ip to ip
|
||||
- source_labels: [__meta_kubernetes_pod_ip]
|
||||
target_label: ip
|
||||
# Set deployment_name as deployment label
|
||||
- source_labels: [__meta_kubernetes_pod_label_deployment_name]
|
||||
target_label: deployment
|
||||
# Set label for role
|
||||
- source_labels: [__meta_kubernetes_pod_label_role]
|
||||
target_label: role
|
||||
rule_files:
|
||||
- /etc/prometheus/alert-rules.d/*.yml
|
||||
alerting:
|
||||
alertmanagers:
|
||||
- kubernetes_sd_configs:
|
||||
- role: pod
|
||||
selectors:
|
||||
- role: pod
|
||||
label: app.kubernetes.io/component=crunchy-alertmanager
|
||||
@@ -0,0 +1,47 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: crunchy-prometheus
|
||||
spec:
|
||||
selector: {}
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: prometheus
|
||||
image: prom/prometheus:v2.39.2
|
||||
ports:
|
||||
- containerPort: 9090
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /-/healthy
|
||||
port: 9090
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 20
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /-/ready
|
||||
port: 9090
|
||||
volumeMounts:
|
||||
- mountPath: /etc/prometheus
|
||||
name: prometheusconf
|
||||
- mountPath: /prometheus
|
||||
name: prometheusdata
|
||||
- mountPath: /etc/prometheus/alert-rules.d
|
||||
name: alertmanagerrules
|
||||
securityContext:
|
||||
fsGroup: 26
|
||||
# supplementalGroups:
|
||||
# - 65534
|
||||
serviceAccountName: prometheus
|
||||
volumes:
|
||||
- name: prometheusconf
|
||||
configMap:
|
||||
defaultMode: 420
|
||||
name: crunchy-prometheus
|
||||
- name: prometheusdata
|
||||
persistentVolumeClaim:
|
||||
claimName: prometheusdata
|
||||
- name: alertmanagerrules
|
||||
configMap:
|
||||
defaultMode: 420
|
||||
name: alert-rules-config
|
||||
@@ -0,0 +1,26 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
labels:
|
||||
- includeSelectors: true
|
||||
pairs:
|
||||
app.kubernetes.io/component: crunchy-prometheus
|
||||
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- pvc.yaml
|
||||
- service.yaml
|
||||
- serviceaccount.yaml
|
||||
- clusterrole.yaml
|
||||
- clusterrolebinding.yaml
|
||||
|
||||
configMapGenerator:
|
||||
- name: crunchy-prometheus
|
||||
files:
|
||||
- config/prometheus.yml
|
||||
- name: alert-rules-config
|
||||
files:
|
||||
- config/crunchy-alert-rules-pg.yml
|
||||
|
||||
generatorOptions:
|
||||
disableNameSuffixHash: true
|
||||
@@ -0,0 +1,10 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: prometheusdata
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 5Gi
|
||||
@@ -0,0 +1,9 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: crunchy-prometheus
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- name: prometheus
|
||||
port: 9090
|
||||
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: prometheus
|
||||
@@ -80,6 +80,8 @@ let OBJECTS = #APIObjects & {
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
// Monitoring configuration
|
||||
monitoring: pgmonitor: exporter: image: "registry.developers.crunchydata.com/crunchydata/crunchy-postgres-exporter:ubi8-5.5.1-0"
|
||||
// Restore from backup if and only if the cluster is primary
|
||||
if Cluster.primary {
|
||||
dataSource: pgbackrest: {
|
||||
|
||||
@@ -74,7 +74,7 @@ package holos
|
||||
repository: "ghcr.io/zitadel/zitadel"
|
||||
pullPolicy: "IfNotPresent"
|
||||
// Overrides the image tag whose default is the chart appVersion.
|
||||
tag: ""
|
||||
tag: string | *""
|
||||
}
|
||||
|
||||
chownImage: {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package holos
|
||||
|
||||
#Values: {
|
||||
// https://github.com/zitadel/zitadel/releases
|
||||
// Overrides the image tag whose default is the chart appVersion.
|
||||
image: tag: "v2.49.1"
|
||||
|
||||
// Database credentials
|
||||
// Refer to https://access.crunchydata.com/documentation/postgres-operator/5.2.0/architecture/user-management/
|
||||
// Refer to https://zitadel.com/docs/self-hosting/manage/database#postgres
|
||||
@@ -74,6 +78,12 @@ package holos
|
||||
ExternalPort: 443
|
||||
TLS: Enabled: false
|
||||
|
||||
// Fix AuthProxy JWKS Error - Jwks doesn't have key to match kid or alg from Jwt
|
||||
// Refer to: https://github.com/holos-run/holos/issues/96
|
||||
// Refer to: https://github.com/zitadel/zitadel/discussions/7464
|
||||
SystemDefaults: KeyConfig: PrivateKeyLifetime: "999999h"
|
||||
SystemDefaults: KeyConfig: PublicKeyLifetime: "999999h"
|
||||
|
||||
// Database connection credentials are injected via environment variables from the db-pguser-db secret.
|
||||
Database: postgres: {
|
||||
MaxOpenConns: 25
|
||||
|
||||
@@ -16,7 +16,7 @@ spec: components: HelmChartList: [
|
||||
enableHooks: true
|
||||
chart: {
|
||||
name: Name
|
||||
version: "7.9.0"
|
||||
version: "7.11.0"
|
||||
repository: {
|
||||
name: Name
|
||||
url: "https://charts.zitadel.com"
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package holos
|
||||
|
||||
// https://cert-manager.io/docs/
|
||||
|
||||
#TargetNamespace: "cert-manager"
|
||||
|
||||
spec: components: HelmChartList: [
|
||||
#HelmChart & {
|
||||
metadata: name: "prod-mesh-certmanager"
|
||||
|
||||
_dependsOn: "prod-secrets-namespaces": _
|
||||
namespace: #TargetNamespace
|
||||
_values: #Values & {
|
||||
installCRDs: true
|
||||
startupapicheck: enabled: false
|
||||
// Must not use kube-system on gke autopilot. GKE Warden authz blocks access.
|
||||
global: leaderElection: namespace: #TargetNamespace
|
||||
}
|
||||
chart: {
|
||||
name: "cert-manager"
|
||||
version: "1.14.3"
|
||||
repository: {
|
||||
name: "jetstack"
|
||||
url: "https://charts.jetstack.io"
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
// https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-resource-requests#min-max-requests
|
||||
#PodResources: {
|
||||
requests: {
|
||||
cpu: string | *"250m"
|
||||
memory: string | *"512Mi"
|
||||
"ephemeral-storage": string | *"100Mi"
|
||||
}
|
||||
}
|
||||
|
||||
// https://cloud.google.com/kubernetes-engine/docs/how-to/autopilot-spot-pods
|
||||
#NodeSelector: {
|
||||
// "kubernetes.io/os": "linux"
|
||||
// "cloud.google.com/gke-spot": "true"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,132 @@
|
||||
package holos
|
||||
|
||||
// import "encoding/yaml"
|
||||
|
||||
let Namespace = "prod-platform"
|
||||
|
||||
// FYI: kube-prometheus-stack is a large umbrella chart what brings in other large charts like
|
||||
// [grafana](https://github.com/grafana/helm-charts/tree/main/charts/grafana).
|
||||
// This may make affect maintainability. Consider breaking the integration down into
|
||||
// constituent charts represented as holos component instances.
|
||||
spec: components: HelmChartList: [
|
||||
#HelmChart & {
|
||||
_dependsOn: "prod-secrets-stores": _
|
||||
namespace: Namespace
|
||||
|
||||
metadata: name: "\(namespace)-obs"
|
||||
|
||||
chart: {
|
||||
name: "kube-prometheus-stack"
|
||||
release: "obs"
|
||||
version: "57.2.0"
|
||||
repository: {
|
||||
name: "prometheus-community"
|
||||
url: "https://prometheus-community.github.io/helm-charts"
|
||||
}
|
||||
}
|
||||
|
||||
_values: #KubePromStackValues & {
|
||||
fullnameOverride: "obs"
|
||||
|
||||
// https://github.com/prometheus-community/helm-charts/tree/kube-prometheus-stack-57.2.0/charts/kube-prometheus-stack#alternatives
|
||||
prometheusOperator: admissionWebhooks: certManager: enabled: true
|
||||
|
||||
prometheus: prometheusSpec: {
|
||||
// Pick up all ServiceMonitors in the monitoring namespace. Note this means
|
||||
// only one Prometheus should be installed in the monitoring namespace.
|
||||
// See https://github.com/prometheus-community/helm-charts/issues/1911
|
||||
serviceMonitorSelectorNilUsesHelmValues: false
|
||||
|
||||
// Unnecessary?
|
||||
// externalUrl: "https://\(Hosts.prometheus.name)"
|
||||
|
||||
storageSpec: volumeClaimTemplate: spec: {
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources: requests: storage: "10Gi"
|
||||
}
|
||||
}
|
||||
|
||||
grafana: {
|
||||
enabled: true
|
||||
persistence: {
|
||||
enabled: true
|
||||
type: "sts"
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
size: "4Gi"
|
||||
finalizers: ["kubernetes.io/pvc-protection"]
|
||||
}
|
||||
|
||||
"grafana.ini": {
|
||||
analytics: check_for_updates: false
|
||||
grafana_net: url: "https://\(#Platform.org.emailDomain)"
|
||||
server: domain: "\(Hosts.grafana.name)"
|
||||
// necessary to get the correct oidc redirect uri
|
||||
server: root_url: "https://\(server.domain)/"
|
||||
auth: oauth_auto_login: true
|
||||
auth: disable_login_form: true
|
||||
auth: disable_signout_menu: true
|
||||
"auth.generic_oauth": {
|
||||
let OIDC = #Platform.oauthClients.grafana.spec
|
||||
enabled: true
|
||||
name: "Holos Platform"
|
||||
enable_login_token: true
|
||||
auto_sign_up: true
|
||||
client_id: OIDC.clientID
|
||||
scopes: OIDC.scopes
|
||||
auth_url: OIDC.authorization_endpoint
|
||||
token_url: OIDC.token_endpoint
|
||||
api_url: OIDC.userinfo_endpoint
|
||||
use_pkce: true
|
||||
name_attribute_path: name
|
||||
// TODO: Lift the admin, editor, and viewer group names up to the plaform config struct.
|
||||
role_attribute_path: "contains(groups[*], 'prod-cluster-admin') && 'Admin' || contains(groups[*], 'prod-cluster-editor') && 'Editor' || 'Viewer'"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Holos overlay objects
|
||||
apiObjectMap: OBJECTS.apiObjectMap
|
||||
},
|
||||
]
|
||||
|
||||
let OBJECTS = #APIObjects & {
|
||||
apiObjects: {
|
||||
// ExternalSecret: "deploy-key": _
|
||||
VirtualService: (Hosts.prometheus.service): {
|
||||
metadata: name: Hosts.prometheus.service
|
||||
metadata: namespace: Namespace
|
||||
spec: hosts: [for host in Hosts.prometheus.hosts {host.name}]
|
||||
spec: gateways: ["istio-ingress/default"]
|
||||
spec: http: [{route: [{destination: {
|
||||
host: "obs-prometheus.\(Namespace).svc.cluster.local"
|
||||
port: number: 9090
|
||||
}}]}]
|
||||
}
|
||||
VirtualService: (Hosts.grafana.service): {
|
||||
metadata: name: Hosts.grafana.service
|
||||
metadata: namespace: Namespace
|
||||
spec: hosts: [for host in Hosts.grafana.hosts {host.name}]
|
||||
spec: gateways: ["istio-ingress/default"]
|
||||
spec: http: [{route: [{destination: {
|
||||
host: "obs-grafana.\(Namespace).svc.cluster.local"
|
||||
port: number: 80
|
||||
}}]}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let Hosts = {
|
||||
[Service=_]: {
|
||||
name: string | *"\(service).\(#ClusterName).\(#Platform.org.domain)"
|
||||
let Name = name
|
||||
hosts: {
|
||||
cluster: name: Name
|
||||
platform: name: "\(service).\(#Platform.org.domain)"
|
||||
}
|
||||
service: Service
|
||||
}
|
||||
|
||||
prometheus: _
|
||||
grafana: _
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1011
docs/examples/platforms/reference/clusters/holos/nats/crds/crds.yml
Normal file
1011
docs/examples/platforms/reference/clusters/holos/nats/crds/crds.yml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
# curl -LO https://github.com/nats-io/nack/releases/latest/download/crds.yml
|
||||
resources:
|
||||
- crds.yml
|
||||
@@ -0,0 +1,8 @@
|
||||
package holos
|
||||
|
||||
// NATS NetStream Controller (NACK)
|
||||
spec: components: KustomizeBuildList: [
|
||||
#KustomizeBuild & {
|
||||
metadata: name: "prod-nack-crds"
|
||||
},
|
||||
]
|
||||
@@ -0,0 +1,37 @@
|
||||
package holos
|
||||
|
||||
// for Project in _Projects {
|
||||
// spec: components: resources: (#ProjectTemplate & {project: Project}).workload.resources
|
||||
// }
|
||||
|
||||
let Namespace = "jeff-holos"
|
||||
|
||||
#Kustomization: spec: targetNamespace: Namespace
|
||||
|
||||
spec: components: HelmChartList: [
|
||||
#HelmChart & {
|
||||
metadata: name: "jeff-holos-nats"
|
||||
namespace: Namespace
|
||||
_dependsOn: "prod-secrets-stores": _
|
||||
chart: {
|
||||
name: "nats"
|
||||
version: "1.1.10"
|
||||
repository: NatsRepository
|
||||
}
|
||||
},
|
||||
#HelmChart & {
|
||||
metadata: name: "jeff-holos-nack"
|
||||
namespace: Namespace
|
||||
_dependsOn: "jeff-holos-nats": _
|
||||
chart: {
|
||||
name: "nack"
|
||||
version: "0.25.2"
|
||||
repository: NatsRepository
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
let NatsRepository = {
|
||||
name: "nats"
|
||||
url: "https://nats-io.github.io/k8s/helm/charts/"
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# Holos
|
||||
|
||||
This subtree contains holos components for holos itself. We strive for minimal dependencies, so this is likely going to contain NATS and/or Postgres resources.
|
||||
|
||||
Components depend on the holos project and may iterate over the defined environments in the project stages.
|
||||
@@ -1,5 +1,7 @@
|
||||
package holos
|
||||
|
||||
import "strings"
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
@@ -180,7 +182,7 @@ _apiVersion: "holos.run/v1alpha1"
|
||||
pool?: string
|
||||
// region is the geographic region of the cluster.
|
||||
region?: string
|
||||
// primary is true if name matches the primaryCluster name
|
||||
// primary is true if the cluster is the primary cluster among a group of related clusters.
|
||||
primary: bool
|
||||
}
|
||||
|
||||
@@ -192,6 +194,8 @@ _apiVersion: "holos.run/v1alpha1"
|
||||
name: string
|
||||
// e.g. "example.com"
|
||||
domain: string
|
||||
// e.g. "example.com"
|
||||
emailDomain: string | *domain
|
||||
// e.g. "Example"
|
||||
displayName: string
|
||||
// e.g. "platform@example.com"
|
||||
@@ -215,6 +219,7 @@ _apiVersion: "holos.run/v1alpha1"
|
||||
primary: false
|
||||
}
|
||||
}
|
||||
// TODO: Remove stages, they're in the subdomain of projects.
|
||||
stages: [ID=_]: {
|
||||
name: string & ID
|
||||
environments: [...{name: string}]
|
||||
@@ -222,14 +227,36 @@ _apiVersion: "holos.run/v1alpha1"
|
||||
projects: [ID=_]: {
|
||||
name: string & ID
|
||||
}
|
||||
// TODO: Remove services, they're in the subdomain of projects.
|
||||
services: [ID=_]: {
|
||||
name: string & ID
|
||||
}
|
||||
|
||||
// authproxy configures the auth proxy attached to the default ingress gateway in the istio-ingress namespace.
|
||||
authproxy: #AuthProxySpec & {
|
||||
namespace: "istio-ingress"
|
||||
provider: "ingressauth"
|
||||
}
|
||||
|
||||
oauthClients: [Name=_]: #OAuthClientSpec & {name: Name}
|
||||
}
|
||||
|
||||
#OAuthClientSpec: {
|
||||
name: string
|
||||
orgDomain: string | *#Platform.org.emailDomain
|
||||
spec: {
|
||||
issuer: string | *"https://login.\(#Platform.org.domain)"
|
||||
clientID: string | *name
|
||||
scopes: string | *strings.Join(scopesList, " ")
|
||||
scopesList: ["openid", "profile", "email", "groups", "urn:zitadel:iam:org:domain:primary:\(orgDomain)"]
|
||||
jwks_uri: string | *"\(issuer)/oauth/v2/keys"
|
||||
authorization_endpoint: string | *"\(issuer)/oauth/v2/authorize"
|
||||
token_endpoint: string | *"\(issuer)/oauth/v2/token"
|
||||
introspection_endpoint: string | *"\(issuer)/oauth/v2/introspect"
|
||||
userinfo_endpoint: string | *"\(issuer)/oauth/v1/userinfo"
|
||||
revocation_endpoint: string | *"\(issuer)/oauth/v2/revoke"
|
||||
end_session_endpoint: string | *"\(issuer)/oauth/v1/end_session"
|
||||
}
|
||||
}
|
||||
|
||||
#AuthProxySpec: {
|
||||
@@ -253,29 +280,6 @@ _apiVersion: "holos.run/v1alpha1"
|
||||
idTokenHeader: string | *"x-oidc-id-token"
|
||||
}
|
||||
|
||||
// ManagedNamespace is a namespace to manage across all clusters in the holos platform.
|
||||
#ManagedNamespace: {
|
||||
namespace: {
|
||||
metadata: {
|
||||
name: string
|
||||
labels: [string]: string
|
||||
}
|
||||
}
|
||||
// clusterNames represents the set of clusters the namespace is managed on. Usually all clusters.
|
||||
clusterNames: [...string]
|
||||
for cluster in clusterNames {
|
||||
clusters: (cluster): name: cluster
|
||||
}
|
||||
}
|
||||
|
||||
// #ManagedNamepsaces is the union of all namespaces across all cluster types and optional services.
|
||||
// Holos adopts the namespace sameness position of SIG Multicluster, refer to https://github.com/kubernetes/community/blob/dd4c8b704ef1c9c3bfd928c6fa9234276d61ad18/sig-multicluster/namespace-sameness-position-statement.md
|
||||
#ManagedNamespaces: {
|
||||
[Name=_]: #ManagedNamespace & {
|
||||
namespace: metadata: name: Name
|
||||
}
|
||||
}
|
||||
|
||||
// #Backups defines backup configuration.
|
||||
// TODO: Consider the best place for this, possibly as part of the site platform config. This represents the primary location for backups.
|
||||
#Backups: {
|
||||
|
||||
150
docs/runbooks/postgres-backup.md
Normal file
150
docs/runbooks/postgres-backup.md
Normal file
@@ -0,0 +1,150 @@
|
||||
# Postgres Full Backup
|
||||
|
||||
Suppose you delete all objects in the S3 bucket hosting all postgres backups. You want to take a full backup ASAP of an existing PostgreSQL database.
|
||||
|
||||
The normal method of annotating the `postgrescluster` resource will not work because the job will error:
|
||||
|
||||
```
|
||||
❯ kubectl annotate postgrescluster zitadel postgres-operator.crunchydata.com/pgbackrest-backup="$(date)" --overwrite
|
||||
postgrescluster.postgres-operator.crunchydata.com/zitadel annotated
|
||||
```
|
||||
|
||||
Backup fails:
|
||||
|
||||
```
|
||||
❯ k get pods
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
zitadel-backup-hk7w-76bfk 0/1 Error 0 65s
|
||||
zitadel-backup-hk7w-d55v6 0/1 Error 0 44s
|
||||
zitadel-backup-hk7w-l9dwm 0/1 Error 0 76s
|
||||
zitadel-backup-hk7w-zcg69 0/1 Error 0 3s
|
||||
zitadel-pgbouncer-d9f8cffc-nx8lq 2/2 Running 0 49m
|
||||
zitadel-pgbouncer-d9f8cffc-s7g7x 2/2 Running 0 49m
|
||||
zitadel-pgha1-2xv2-0 5/5 Running 0 48m
|
||||
zitadel-pgha1-78f4-0 5/5 Running 0 49m
|
||||
zitadel-repo-host-0 2/2 Running 0 49m
|
||||
```
|
||||
|
||||
Error is: `FileMissingError: unable to open missing file '/pgbackrest/prod-iam/zitadel/repo2/backup/db/backup.info.copy' for read`
|
||||
|
||||
```
|
||||
time="2024-04-08T00:02:11Z" level=info msg="crunchy-pgbackrest starts"
|
||||
time="2024-04-08T00:02:11Z" level=info msg="debug flag set to false"
|
||||
time="2024-04-08T00:02:12Z" level=info msg="backrest backup command requested"
|
||||
time="2024-04-08T00:02:12Z" level=info msg="command to execute is [pgbackrest backup --stanza=db --repo=2 --type=full]"
|
||||
time="2024-04-08T00:02:12Z" level=info msg="output=[]"
|
||||
time="2024-04-08T00:02:12Z" level=info msg="stderr=[ERROR: [055]: unable to load info file '/pgbackrest/prod-iam/zitadel/repo2/backup/db/backup.info' or '/pgbackrest/prod-iam/zitadel/repo2/backup/db/backup.info.copy':\n FileMissingError: unable to open missing file '/pgbackrest/prod-iam/zitadel/repo2/backup/db/backup.info' for read\n FileMissingError: unable to open missing file '/pgbackrest/prod-iam/zitadel/repo2/backup/db/backup.info.copy' for read\n HINT: backup.info cannot be opened and is required to perform a backup.\n HINT: has a stanza-create been performed?\n]"
|
||||
time="2024-04-08T00:02:12Z" level=fatal msg="command terminated with exit code 55"
|
||||
```
|
||||
|
||||
## Fix Process
|
||||
|
||||
We need to edit the postgrescluster. We're going to have the controller re-initialize the backup repository from scratch by removing it and re-adding it.
|
||||
|
||||
First, suspend flux:
|
||||
|
||||
```
|
||||
flux suspend ks prod-iam-zitadel prod-iam-postgres
|
||||
```
|
||||
|
||||
Save the config to two files:
|
||||
|
||||
```
|
||||
kubectl get postgresclusters.postgres-operator.crunchydata.com zitadel -o yaml > orig.yaml
|
||||
cp orig.yaml new.yaml
|
||||
```
|
||||
|
||||
Remove the follow fields and re-apply the cluster. This will leave the cluster running and available while the controller reconciles the repo configuration:
|
||||
|
||||
```diff
|
||||
--- orig.yaml 2024-04-07 17:08:26.834715820 -0700
|
||||
+++ new.yaml 2024-04-07 17:08:57.418546067 -0700
|
||||
@@ -4,6 +4,4 @@
|
||||
annotations:
|
||||
holos.run/description: ""
|
||||
- postgres-operator.crunchydata.com/pgbackrest-backup: Sun 07 Apr 2024 05:01:35
|
||||
- PM PDT
|
||||
creationTimestamp: "2024-04-07T23:10:44Z"
|
||||
finalizers:
|
||||
@@ -26,12 +24,5 @@
|
||||
repo1-retention-full: "1"
|
||||
repo2-cipher-type: aes-256-cbc
|
||||
- repo2-path: /pgbackrest/prod-iam/zitadel/repo2
|
||||
- repo2-retention-full: "14"
|
||||
- repo2-retention-full-type: time
|
||||
image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.49-0
|
||||
- manual:
|
||||
- options:
|
||||
- - --type=full
|
||||
- repoName: repo2
|
||||
repos:
|
||||
- name: repo1
|
||||
@@ -43,12 +34,4 @@
|
||||
requests:
|
||||
storage: 4Gi
|
||||
- - name: repo2
|
||||
- s3:
|
||||
- bucket: ois-zitadel-backups
|
||||
- endpoint: s3.dualstack.us-east-2.amazonaws.com
|
||||
- region: us-east-2
|
||||
- schedules:
|
||||
- differential: 0 1 * * 1-6
|
||||
- full: 0 1 * * 0
|
||||
restore:
|
||||
enabled: true
|
||||
```
|
||||
|
||||
Apply the config and wait for the controller to reconcile:
|
||||
|
||||
```
|
||||
k apply --server-side=true -f new.yaml --force-conflicts
|
||||
```
|
||||
|
||||
Check for reconciliation:
|
||||
|
||||
```
|
||||
kubectl -n postgres-operator logs -l app.kubernetes.io/name=pgo | tail -1
|
||||
```
|
||||
|
||||
```
|
||||
time="2024-04-08T00:10:03Z" level=debug msg="reconciled cluster" controller=postgrescluster controllerGroup=postgres-operator.crunchydata.com controllerKind=PostgresCluster name=zitadel namespace=prod-iam postgresCluster=prod-iam/zitadel reconcileID=cc8c8eb7-9787-4504-8ecd-a04ec84fbc0b version=5.5.1-0-amd64
|
||||
```
|
||||
|
||||
Re-add the repo host configuration
|
||||
|
||||
```
|
||||
grep -v 'resourceVersion:' orig.yaml | k apply --server-side=true --force-conflicts -f-
|
||||
```
|
||||
|
||||
```
|
||||
postgrescluster.postgres-operator.crunchydata.com/zitadel serverside-applied
|
||||
```
|
||||
|
||||
The full backup should be running and writing to S3 now:
|
||||
|
||||
```
|
||||
kubectl logs -l postgres-operator.crunchydata.com/pgbackrest-backup=manual
|
||||
```
|
||||
|
||||
```
|
||||
time="2024-04-08T00:12:54Z" level=info msg="crunchy-pgbackrest starts"
|
||||
time="2024-04-08T00:12:54Z" level=info msg="debug flag set to false"
|
||||
time="2024-04-08T00:12:54Z" level=info msg="backrest backup command requested"
|
||||
time="2024-04-08T00:12:54Z" level=info msg="command to execute is [pgbackrest backup --stanza=db --repo=2 --type=full]"
|
||||
time="2024-04-08T00:16:02Z" level=info msg="output=[]"
|
||||
time="2024-04-08T00:16:02Z" level=info msg="stderr=[]"
|
||||
time="2024-04-08T00:16:02Z" level=info msg="crunchy-pgbackrest ends"
|
||||
```
|
||||
|
||||
Finally, resume flux:
|
||||
|
||||
```
|
||||
flux resume ks prod-iam-postgres prod-iam-zitadel
|
||||
```
|
||||
|
||||
```
|
||||
► resuming kustomization prod-iam-postgres in flux-system namespace
|
||||
✔ kustomization resumed
|
||||
► resuming kustomization prod-iam-zitadel in flux-system namespace
|
||||
✔ kustomization resumed
|
||||
```
|
||||
127
go.mod
127
go.mod
@@ -3,65 +3,182 @@ module github.com/holos-run/holos
|
||||
go 1.21.5
|
||||
|
||||
require (
|
||||
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240401165935-b983156c5e99.1
|
||||
connectrpc.com/connect v1.16.0
|
||||
connectrpc.com/validate v0.1.0
|
||||
cuelang.org/go v0.8.0
|
||||
entgo.io/ent v0.13.1
|
||||
github.com/bufbuild/buf v1.30.1
|
||||
github.com/coreos/go-oidc/v3 v3.10.0
|
||||
github.com/fullstorydev/grpcurl v1.9.1
|
||||
github.com/go-jose/go-jose/v3 v3.0.3
|
||||
github.com/gofrs/uuid v4.4.0+incompatible
|
||||
github.com/int128/kubelogin v1.28.0
|
||||
github.com/jackc/pgx/v5 v5.5.5
|
||||
github.com/lmittmann/tint v1.0.4
|
||||
github.com/mattn/go-isatty v0.0.20
|
||||
github.com/mattn/go-runewidth v0.0.9
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/prometheus/client_golang v1.19.0
|
||||
github.com/rogpeppe/go-internal v1.12.0
|
||||
github.com/sethvargo/go-retry v0.2.4
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.9.0
|
||||
golang.org/x/net v0.22.0
|
||||
golang.org/x/tools v0.19.0
|
||||
google.golang.org/protobuf v1.33.1-0.20240408130810-98873a205002
|
||||
honnef.co/go/tools v0.4.7
|
||||
k8s.io/api v0.29.2
|
||||
k8s.io/apimachinery v0.29.2
|
||||
k8s.io/client-go v0.29.2
|
||||
k8s.io/kubectl v0.29.2
|
||||
modernc.org/sqlite v1.29.6
|
||||
sigs.k8s.io/yaml v1.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
ariga.io/atlas v0.19.1-0.20240203083654-5948b60a8e43 // indirect
|
||||
cloud.google.com/go/compute v1.23.3 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
connectrpc.com/otelconnect v0.7.0 // indirect
|
||||
cuelabs.dev/go/oci/ociregistry v0.0.0-20240314152124-224736b49f2e // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
||||
github.com/BurntSushi/toml v1.2.1 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/agext/levenshtein v1.2.1 // indirect
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bufbuild/protocompile v0.10.0 // indirect
|
||||
github.com/bufbuild/protovalidate-go v0.6.0 // indirect
|
||||
github.com/bufbuild/protoyaml-go v0.1.8 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe // indirect
|
||||
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa // indirect
|
||||
github.com/cockroachdb/apd/v3 v3.2.1 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/docker/cli v26.0.0+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||
github.com/docker/docker v26.0.0+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.8.1 // indirect
|
||||
github.com/docker/go-connections v0.5.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||
github.com/emicklei/proto v1.10.0 // indirect
|
||||
github.com/envoyproxy/go-control-plane v0.12.0 // indirect
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect
|
||||
github.com/evanphx/json-patch v5.7.0+incompatible // indirect
|
||||
github.com/go-logr/logr v1.3.0 // indirect
|
||||
github.com/felixge/fgprof v0.9.4 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/go-chi/chi/v5 v5.0.12 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.0.1 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/inflect v0.19.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.20.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/swag v0.22.4 // indirect
|
||||
github.com/gofrs/uuid/v5 v5.0.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/cel-go v0.20.1 // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/go-containerregistry v0.19.1 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/uuid v1.5.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20240327155427-868f304927ed // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/google/wire v0.5.0 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/hashicorp/hcl/v2 v2.13.0 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/int128/listener v1.1.0 // indirect
|
||||
github.com/int128/oauth2cli v1.14.0 // indirect
|
||||
github.com/int128/oauth2dev v1.0.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||
github.com/jdx/go-netrc v1.0.0 // indirect
|
||||
github.com/jhump/protoreflect v1.16.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.17.7 // indirect
|
||||
github.com/klauspost/pgzip v1.2.6 // indirect
|
||||
github.com/lib/pq v1.10.9 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/term v0.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.15.0 // indirect
|
||||
github.com/onsi/gomega v1.31.1 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pkg/profile v1.7.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.48.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/protocolbuffers/txtpbfmt v0.0.0-20230328191034-3462fbc510c0 // indirect
|
||||
golang.org/x/net v0.22.0 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rs/cors v1.10.1 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/stoewer/go-strcase v1.3.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/vbatts/tar-split v0.11.5 // indirect
|
||||
github.com/zclconf/go-cty v1.8.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
|
||||
go.opentelemetry.io/otel v1.25.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.25.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.25.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.25.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.25.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.1.0 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/crypto v0.21.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect
|
||||
golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a // indirect
|
||||
golang.org/x/mod v0.16.0 // indirect
|
||||
golang.org/x/oauth2 v0.18.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sys v0.18.0 // indirect
|
||||
golang.org/x/term v0.18.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240325203815-454cdb8f5daa // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240325203815-454cdb8f5daa // indirect
|
||||
google.golang.org/grpc v1.62.1 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/klog/v2 v2.110.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20231206194836-bf4651e18aa8 // indirect
|
||||
k8s.io/utils v0.0.0-20231127182322-b307cd553661 // indirect
|
||||
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
|
||||
modernc.org/libc v1.41.0 // indirect
|
||||
modernc.org/mathutil v1.6.0 // indirect
|
||||
modernc.org/memory v1.7.2 // indirect
|
||||
modernc.org/strutil v1.2.0 // indirect
|
||||
modernc.org/token v1.1.0 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
||||
)
|
||||
|
||||
649
go.sum
649
go.sum
@@ -1,22 +1,176 @@
|
||||
ariga.io/atlas v0.19.1-0.20240203083654-5948b60a8e43 h1:GwdJbXydHCYPedeeLt4x/lrlIISQ4JTH1mRWuE5ZZ14=
|
||||
ariga.io/atlas v0.19.1-0.20240203083654-5948b60a8e43/go.mod h1:uj3pm+hUTVN/X5yfdBexHlZv+1Xu5u5ZbZx7+CDavNU=
|
||||
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240401165935-b983156c5e99.1 h1:2IGhRovxlsOIQgx2ekZWo4wTPAYpck41+18ICxs37is=
|
||||
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240401165935-b983156c5e99.1/go.mod h1:Tgn5bgL220vkFOI0KPStlcClPeOJzAv4uT+V8JXGUnw=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk=
|
||||
cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI=
|
||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
connectrpc.com/connect v1.16.0 h1:rdtfQjZ0OyFkWPTegBNcH7cwquGAN1WzyJy80oFNibg=
|
||||
connectrpc.com/connect v1.16.0/go.mod h1:XpZAduBQUySsb4/KO5JffORVkDI4B6/EYPi7N8xpNZw=
|
||||
connectrpc.com/otelconnect v0.7.0 h1:ZH55ZZtcJOTKWWLy3qmL4Pam4RzRWBJFOqTPyAqCXkY=
|
||||
connectrpc.com/otelconnect v0.7.0/go.mod h1:Bt2ivBymHZHqxvo4HkJ0EwHuUzQN6k2l0oH+mp/8nwc=
|
||||
connectrpc.com/validate v0.1.0 h1:r55jirxMK7HO/xZwVHj3w2XkVFarsUM77ZDy367NtH4=
|
||||
connectrpc.com/validate v0.1.0/go.mod h1:GU47c9/x/gd+u9wRSPkrQOP46gx2rMN+Wo37EHgI3Ow=
|
||||
cuelabs.dev/go/oci/ociregistry v0.0.0-20240314152124-224736b49f2e h1:GwCVItFUPxwdsEYnlUcJ6PJxOjTeFFCKOh6QWg4oAzQ=
|
||||
cuelabs.dev/go/oci/ociregistry v0.0.0-20240314152124-224736b49f2e/go.mod h1:ApHceQLLwcOkCEXM1+DyCXTHEJhNGDpJ2kmV6axsx24=
|
||||
cuelang.org/go v0.8.0 h1:fO1XPe/SUGtc7dhnGnTPbpIDoQm/XxhDtoSF7jzO01c=
|
||||
cuelang.org/go v0.8.0/go.mod h1:CoDbYolfMms4BhWUlhD+t5ORnihR7wvjcfgyO9lL5FI=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
entgo.io/ent v0.13.1 h1:uD8QwN1h6SNphdCCzmkMN3feSUzNnVvV/WIkHKMbzOE=
|
||||
entgo.io/ent v0.13.1/go.mod h1:qCEmo+biw3ccBn9OyL4ZK5dfpwg++l1Gxwac5B1206A=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
|
||||
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||
github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8=
|
||||
github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bufbuild/buf v1.30.1 h1:QFtanwsXodoGFAwzXFXGXpzBkb7N2u8ZDyA3jWB4Pbs=
|
||||
github.com/bufbuild/buf v1.30.1/go.mod h1:7W8DJnj76wQa55EA3z2CmDxS0/nsHh8FqtE00dyDAdA=
|
||||
github.com/bufbuild/protocompile v0.10.0 h1:+jW/wnLMLxaCEG8AX9lD0bQ5v9h1RUiMKOBOT5ll9dM=
|
||||
github.com/bufbuild/protocompile v0.10.0/go.mod h1:G9qQIQo0xZ6Uyj6CMNz0saGmx2so+KONo8/KrELABiY=
|
||||
github.com/bufbuild/protovalidate-go v0.6.0 h1:Jgs1kFuZ2LHvvdj8SpCLA1W/+pXS8QSM3F/E2l3InPY=
|
||||
github.com/bufbuild/protovalidate-go v0.6.0/go.mod h1:1LamgoYHZ2NdIQH0XGczGTc6Z8YrTHjcJVmiBaar4t4=
|
||||
github.com/bufbuild/protoyaml-go v0.1.8 h1:X9QDLfl9uEllh4gsXUGqPanZYCOKzd92uniRtW2OnAQ=
|
||||
github.com/bufbuild/protoyaml-go v0.1.8/go.mod h1:R8vE2+l49bSiIExP4VJpxOXleHE+FDzZ6HVxr3cYunw=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g=
|
||||
github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
|
||||
github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs=
|
||||
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk=
|
||||
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ=
|
||||
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM=
|
||||
github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg=
|
||||
github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc=
|
||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.15.1 h1:eXJjw9RbkLFgioVaTG+G/ZW/0kEe2oEKCdS/ZxIyoCU=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.15.1/go.mod h1:gr2RNwukQ/S9Nv33Lt6UC7xEx58C+LHRdoqbEKjz1Kk=
|
||||
github.com/coreos/go-oidc/v3 v3.10.0 h1:tDnXHnLyiTVyT/2zLDGj09pFPkhND8Gl8lnTRhoEaJU=
|
||||
github.com/coreos/go-oidc/v3 v3.10.0/go.mod h1:5j11xcw0D3+SGxn6Z/WFADsgcWVMyNAlSQupk0KK3ac=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/cli v26.0.0+incompatible h1:90BKrx1a1HKYpSnnBFR6AgDq/FqkHxwlUyzJVPxD30I=
|
||||
github.com/docker/cli v26.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
|
||||
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v26.0.0+incompatible h1:Ng2qi+gdKADUa/VM+6b6YaY2nlZhk/lVJiKR/2bMudU=
|
||||
github.com/docker/docker v26.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo=
|
||||
github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
|
||||
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
||||
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
|
||||
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/emicklei/proto v1.10.0 h1:pDGyFRVV5RvV+nkBK9iy3q67FBy9Xa7vwrOTE+g5aGw=
|
||||
github.com/emicklei/proto v1.10.0/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI=
|
||||
github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
|
||||
github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI=
|
||||
github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
|
||||
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
|
||||
github.com/felixge/fgprof v0.9.4 h1:ocDNwMFlnA0NU0zSB3I52xkO4sFXk80VK9lXjLClu88=
|
||||
github.com/felixge/fgprof v0.9.4/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fullstorydev/grpcurl v1.9.1 h1:YxX1aCcCc4SDBQfj9uoWcTLe8t4NWrZe1y+mk83BQgo=
|
||||
github.com/fullstorydev/grpcurl v1.9.1/go.mod h1:i8gKLIC6s93WdU3LSmkE5vtsCxyRmihUj5FK1cNW5EM=
|
||||
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
|
||||
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k=
|
||||
github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
|
||||
github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
|
||||
github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4=
|
||||
github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4=
|
||||
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
||||
github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ=
|
||||
github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA=
|
||||
@@ -29,35 +183,141 @@ github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7
|
||||
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
|
||||
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
|
||||
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
||||
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M=
|
||||
github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84=
|
||||
github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg=
|
||||
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
||||
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-containerregistry v0.19.1 h1:yMQ62Al6/V0Z7CqIrrS1iYoA5/oQCm88DeNujc7C1KY=
|
||||
github.com/google/go-containerregistry v0.19.1/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/pprof v0.0.0-20240327155427-868f304927ed h1:n8QtJTrwsv3P7dNxPaMeNkMcxvUpqocsHLr8iDLGlQI=
|
||||
github.com/google/pprof v0.0.0-20240327155427-868f304927ed/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
|
||||
github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/hashicorp/hcl/v2 v2.13.0 h1:0Apadu1w6M11dyGFxWnmhhcMjkbAiKCv7G1r/2QgCNc=
|
||||
github.com/hashicorp/hcl/v2 v2.13.0/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
|
||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/int128/kubelogin v1.28.0 h1:T1xQ/dw2aIX/Bvv3KtSk8m8u483acr/5lidVRLBgIQ4=
|
||||
github.com/int128/kubelogin v1.28.0/go.mod h1:UM4ShH939mXO1Cd0ns13mYQsUctyLbfHFHq8a6NXMG0=
|
||||
github.com/int128/listener v1.1.0 h1:2Jb41DWLpkQ3I9bIdBzO8H/tNwMvyl/OBZWtCV5Pjuw=
|
||||
github.com/int128/listener v1.1.0/go.mod h1:68WkmTN8PQtLzc9DucIaagAKeGVyMnyyKIkW4Xn47UA=
|
||||
github.com/int128/oauth2cli v1.14.0 h1:r63NoO10ybUXIXUQxih8WOmt5HQpJubdTmhWh22B9VE=
|
||||
github.com/int128/oauth2cli v1.14.0/go.mod h1:LIoVAzgAsS2tDDBc8yopkcgY5oZR0+MJAeECkCwtxhA=
|
||||
github.com/int128/oauth2dev v1.0.0 h1:emMhky6ssFEiyujCGcTpuUkeBg121IvcFey54CxW844=
|
||||
github.com/int128/oauth2dev v1.0.0/go.mod h1:lLIeCHF2MzH+sQ35/2IgA+Lbti/K2ONjrwO3n3FKSAM=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
|
||||
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
|
||||
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jdx/go-netrc v1.0.0 h1:QbLMLyCZGj0NA8glAhxUpf1zDg6cxnWgMBbjq40W0gQ=
|
||||
github.com/jdx/go-netrc v1.0.0/go.mod h1:Gh9eFQJnoTNIRHXl2j5bJXA1u84hQWJWgGh569zF3v8=
|
||||
github.com/jhump/protoreflect v1.16.0 h1:54fZg+49widqXYQ0b+usAFHbMkBGR4PpXrsHc8+TBDg=
|
||||
github.com/jhump/protoreflect v1.16.0/go.mod h1:oYPd7nPvcBw/5wlDfm/AVmU9zH9BgqGCI469pGxfj/8=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
|
||||
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
|
||||
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
@@ -67,21 +327,40 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lmittmann/tint v1.0.4 h1:LeYihpJ9hyGvE0w+K2okPTGUdVLfng1+nDNVR4vWISc=
|
||||
github.com/lmittmann/tint v1.0.4/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
|
||||
github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
|
||||
github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo=
|
||||
@@ -90,104 +369,433 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
||||
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
|
||||
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA=
|
||||
github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
|
||||
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||
github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=
|
||||
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/protocolbuffers/txtpbfmt v0.0.0-20230328191034-3462fbc510c0 h1:sadMIsgmHpEOGbUs6VtHBXRR1OHevnj7hLx9ZcdNGW4=
|
||||
github.com/protocolbuffers/txtpbfmt v0.0.0-20230328191034-3462fbc510c0/go.mod h1:jgxiZysxFPM+iWKwQwPR+y+Jvo54ARd4EisXxKYpB5c=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo=
|
||||
github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/sethvargo/go-retry v0.2.4 h1:T+jHEQy/zKJf5s95UkguisicE0zuF9y7+/vgz08Ocec=
|
||||
github.com/sethvargo/go-retry v0.2.4/go.mod h1:1afjQuvh7s4gflMObvjLPaWgluLLyhA1wmVZ6KLpICw=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
|
||||
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
|
||||
github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts=
|
||||
github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk=
|
||||
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
|
||||
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/zclconf/go-cty v1.8.0 h1:s4AvqaeQzJIu3ndv4gVIhplVD0krU+bgrcLSVUnaWuA=
|
||||
github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
|
||||
go.opentelemetry.io/otel v1.25.0 h1:gldB5FfhRl7OJQbUHt/8s0a7cE8fbsPAtdpRaApKy4k=
|
||||
go.opentelemetry.io/otel v1.25.0/go.mod h1:Wa2ds5NOXEMkCmUou1WA7ZBfLTHWIsp034OVD7AO+Vg=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.25.0 h1:dT33yIHtmsqpixFsSQPwNeY5drM9wTcoL8h0FWF4oGM=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.25.0/go.mod h1:h95q0LBGh7hlAC08X2DhSeyIG02YQ0UyioTCVAqRPmc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM=
|
||||
go.opentelemetry.io/otel/metric v1.25.0 h1:LUKbS7ArpFL/I2jJHdJcqMGxkRdxpPHE0VU/D4NuEwA=
|
||||
go.opentelemetry.io/otel/metric v1.25.0/go.mod h1:rkDLUSd2lC5lq2dFNrX9LGAbINP5B7WBkC78RXCpH5s=
|
||||
go.opentelemetry.io/otel/sdk v1.25.0 h1:PDryEJPC8YJZQSyLY5eqLeafHtG+X7FWnf3aXMtxbqo=
|
||||
go.opentelemetry.io/otel/sdk v1.25.0/go.mod h1:oFgzCM2zdsxKzz6zwpTZYLLQsFwc+K0daArPdIhuxkw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8Ni+hx+8i1k=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.19.0/go.mod h1:XjG0jQyFJrv2PbMvwND7LwCEhsJzCzV5210euduKcKY=
|
||||
go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1Dq6RM=
|
||||
go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I=
|
||||
go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI=
|
||||
go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY=
|
||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw=
|
||||
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ=
|
||||
golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a h1:Jw5wfR+h9mnIYH+OtGT2im5wV1YGGDora5vTv/aa5bE=
|
||||
golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
|
||||
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
||||
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI=
|
||||
golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
|
||||
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
||||
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240325203815-454cdb8f5daa h1:Jt1XW5PaLXF1/ePZrznsh/aAUvI7Adfc3LY1dAKlzRs=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240325203815-454cdb8f5daa/go.mod h1:K4kfzHtI0kqWA79gecJarFtDn/Mls+GxQcg3Zox91Ac=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240325203815-454cdb8f5daa h1:RBgMaUMP+6soRkik4VoN8ojR2nex2TqZwjSSogic+eo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240325203815-454cdb8f5daa/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
|
||||
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
google.golang.org/protobuf v1.33.1-0.20240408130810-98873a205002 h1:V7Da7qt0MkY3noVANIMVBk28nOnijADeOR3i5Hcvpj4=
|
||||
google.golang.org/protobuf v1.33.1-0.20240408130810-98873a205002/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
|
||||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.4.7 h1:9MDAWxMoSnB6QoSqiVr7P5mtkT9pOc1kSxchzPCnqJs=
|
||||
honnef.co/go/tools v0.4.7/go.mod h1:+rnGS1THNh8zMwnd2oVOTL9QF6vmfyG6ZXBULae2uc0=
|
||||
k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A=
|
||||
k8s.io/api v0.29.2/go.mod h1:sdIaaKuU7P44aoyyLlikSLayT6Vb7bvJNCX105xZXY0=
|
||||
k8s.io/apimachinery v0.29.2 h1:EWGpfJ856oj11C52NRCHuU7rFDwxev48z+6DSlGNsV8=
|
||||
@@ -202,6 +810,25 @@ k8s.io/kubectl v0.29.2 h1:uaDYaBhumvkwz0S2XHt36fK0v5IdNgL7HyUniwb2IUo=
|
||||
k8s.io/kubectl v0.29.2/go.mod h1:BhizuYBGcKaHWyq+G7txGw2fXg576QbPrrnQdQDZgqI=
|
||||
k8s.io/utils v0.0.0-20231127182322-b307cd553661 h1:FepOBzJ0GXm8t0su67ln2wAZjbQ6RxQGZDnzuLcrUTI=
|
||||
k8s.io/utils v0.0.0-20231127182322-b307cd553661/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
|
||||
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
|
||||
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI=
|
||||
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
|
||||
modernc.org/libc v1.41.0 h1:g9YAc6BkKlgORsUWj+JwqoB1wU3o4DE3bM3yvA3k+Gk=
|
||||
modernc.org/libc v1.41.0/go.mod h1:w0eszPsiXoOnoMJgrXjglgLuDy/bt5RR4y3QzUUeodY=
|
||||
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
||||
modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E=
|
||||
modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E=
|
||||
modernc.org/sqlite v1.29.6 h1:0lOXGrycJPptfHDuohfYgNqoe4hu+gYuN/pKgY5XjS4=
|
||||
modernc.org/sqlite v1.29.6/go.mod h1:S02dvcmm7TnTRvGhv8IGYyLnIt7AS2KPaB1F/71p75U=
|
||||
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
|
||||
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
|
||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
|
||||
|
||||
2
hack/tilt/.gitignore
vendored
Normal file
2
hack/tilt/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
aws-login.last
|
||||
kubeconfig
|
||||
7
hack/tilt/Dockerfile
Normal file
7
hack/tilt/Dockerfile
Normal file
@@ -0,0 +1,7 @@
|
||||
FROM 271053619184.dkr.ecr.us-east-2.amazonaws.com/holos-run/container-images/debian:bullseye AS final
|
||||
USER root
|
||||
WORKDIR /app
|
||||
ADD bin bin
|
||||
RUN chown -R app: /app
|
||||
USER app
|
||||
ENTRYPOINT bin/holos server
|
||||
21
hack/tilt/aws-login.sh
Executable file
21
hack/tilt/aws-login.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#! /bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
PARENT="$(cd $(dirname "$0") && pwd)"
|
||||
|
||||
# If necessary
|
||||
if [[ -s "${PARENT}/aws-login.last" ]]; then
|
||||
last="$(<"${PARENT}/aws-login.last")"
|
||||
now="$(date +%s)"
|
||||
if [[ $(( now - last )) -lt 28800 ]]; then
|
||||
echo "creds are still valid" >&2
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
aws sso logout
|
||||
aws sso login
|
||||
aws ecr get-login-password --region us-east-2 | docker login --username AWS --password-stdin "${AWS_ACCOUNT}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"
|
||||
# Touch a file so tilt docker_build can watch it as a dep
|
||||
date +%s > "${PARENT}/aws-login.last"
|
||||
7
hack/tilt/aws.config
Normal file
7
hack/tilt/aws.config
Normal file
@@ -0,0 +1,7 @@
|
||||
[profile dev-holos]
|
||||
sso_account_id = 271053619184
|
||||
sso_role_name = AdministratorAccess
|
||||
sso_start_url = https://openinfrastructure.awsapps.com/start
|
||||
sso_region = us-east-2
|
||||
region = us-east-2
|
||||
output = json
|
||||
9
hack/tilt/bin/tilt
Executable file
9
hack/tilt/bin/tilt
Executable file
@@ -0,0 +1,9 @@
|
||||
#! /bin/bash
|
||||
# Override kubeconfig so we can create it with local()
|
||||
set -euo pipefail
|
||||
TOPLEVEL="$(cd $(dirname "$0")/.. && pwd)"
|
||||
export NAMESPACE="${USER}-holos"
|
||||
export KUBECONFIG="${TOPLEVEL}/kubeconfig"
|
||||
envsubst < "${KUBECONFIG}.template" > "${KUBECONFIG}"
|
||||
export TILT_WRAPPER=1
|
||||
exec tilt "$@"
|
||||
153
hack/tilt/ecr-creds.yaml
Normal file
153
hack/tilt/ecr-creds.yaml
Normal file
@@ -0,0 +1,153 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/component: container-registry
|
||||
app.kubernetes.io/instance: holos-system-ecr
|
||||
app.kubernetes.io/name: holos-system-ecr
|
||||
app.kubernetes.io/part-of: holos
|
||||
name: holos-system-ecr
|
||||
namespace: holos-system
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/component: container-registry
|
||||
app.kubernetes.io/instance: holos-system-ecr
|
||||
app.kubernetes.io/name: holos-system-ecr
|
||||
app.kubernetes.io/part-of: holos
|
||||
name: holos-system-ecr
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- secrets
|
||||
- namespaces
|
||||
verbs:
|
||||
- list
|
||||
- apiGroups:
|
||||
- ""
|
||||
resourceNames:
|
||||
- holos-system-ecr-image-pull-creds
|
||||
resources:
|
||||
- secrets
|
||||
verbs:
|
||||
- '*'
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/component: container-registry
|
||||
app.kubernetes.io/instance: holos-system-ecr
|
||||
app.kubernetes.io/name: holos-system-ecr
|
||||
app.kubernetes.io/part-of: holos
|
||||
name: holos-system-ecr
|
||||
namespace: holos-system
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: holos-system-ecr
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: holos-system-ecr
|
||||
namespace: holos-system
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
refresh.sh: |-
|
||||
#! /bin/bash
|
||||
tmpdir="$(mktemp -d)"
|
||||
finish() {
|
||||
rm -rf "${tmpdir}"
|
||||
}
|
||||
trap finish EXIT
|
||||
set -euo pipefail
|
||||
aws sts assume-role-with-web-identity \
|
||||
--role-arn ${AWS_ROLE_ARN} \
|
||||
--role-session-name CronJob \
|
||||
--web-identity-token file:///run/secrets/irsa/serviceaccount/token \
|
||||
> "${tmpdir}/creds.json"
|
||||
export AWS_ACCESS_KEY_ID=$(jq -r .Credentials.AccessKeyId "${tmpdir}/creds.json")
|
||||
export AWS_SECRET_ACCESS_KEY=$(jq -r .Credentials.SecretAccessKey "${tmpdir}/creds.json")
|
||||
export AWS_SESSION_TOKEN=$(jq -r .Credentials.SessionToken "${tmpdir}/creds.json")
|
||||
set -x
|
||||
aws ecr get-login-password --region ${AWS_REGION} \
|
||||
| docker login --username AWS --password-stdin ${AWS_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com
|
||||
kubectl create secret docker-registry 'holos-system-ecr-image-pull-creds' \
|
||||
--from-file=.dockerconfigjson=${HOME}/.docker/config.json \
|
||||
--dry-run=client -o yaml \
|
||||
> "${tmpdir}/secret.yaml"
|
||||
# Get namespaces one per line
|
||||
kubectl -o=jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' get namespaces > ${tmpdir}/namespaces.txt
|
||||
# Copy the secret to all namespaces
|
||||
for ns in $(grep -vE '^gke-|^kube-|^gmp-' ${tmpdir}/namespaces.txt); do
|
||||
echo "---" >> "${tmpdir}/secretlist.yaml"
|
||||
kubectl --dry-run=client -o yaml -n $ns apply -f "${tmpdir}/secret.yaml" >> "${tmpdir}/secretlist.yaml"
|
||||
done
|
||||
kubectl apply --server-side=true -f "${tmpdir}/secretlist.yaml"
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/component: image-pull-secret
|
||||
app.kubernetes.io/instance: holos-system-ecr
|
||||
app.kubernetes.io/name: refresher
|
||||
app.kubernetes.io/part-of: holos
|
||||
name: holos-system-ecr
|
||||
namespace: holos-system
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/component: container-registry
|
||||
app.kubernetes.io/instance: holos-system-ecr
|
||||
app.kubernetes.io/name: holos-system-ecr
|
||||
app.kubernetes.io/part-of: holos
|
||||
name: holos-system-ecr
|
||||
namespace: holos-system
|
||||
spec:
|
||||
schedule: 0 */4 * * *
|
||||
jobTemplate:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- command:
|
||||
- bash
|
||||
- /app/scripts/refresh.sh
|
||||
env:
|
||||
- name: AWS_ACCOUNT
|
||||
value: "271053619184"
|
||||
- name: AWS_REGION
|
||||
value: us-east-2
|
||||
- name: AWS_ROLE_ARN
|
||||
value: arn:aws:iam::271053619184:role/ImagePull
|
||||
image: quay.io/holos/toolkit:latest
|
||||
imagePullPolicy: Always
|
||||
name: toolkit
|
||||
resources:
|
||||
limits:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
volumeMounts:
|
||||
- mountPath: /app/scripts
|
||||
name: scripts
|
||||
- mountPath: /run/secrets/irsa/serviceaccount
|
||||
name: irsa
|
||||
restartPolicy: OnFailure
|
||||
serviceAccountName: holos-system-ecr
|
||||
volumes:
|
||||
- configMap:
|
||||
name: holos-system-ecr
|
||||
name: scripts
|
||||
- name: irsa
|
||||
projected:
|
||||
sources:
|
||||
- serviceAccountToken:
|
||||
path: "token"
|
||||
audience: "irsa"
|
||||
expirationSeconds: 3600
|
||||
37
hack/tilt/get-pgadmin-creds
Executable file
37
hack/tilt/get-pgadmin-creds
Executable file
@@ -0,0 +1,37 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
tmpdir="$(mktemp -d)"
|
||||
finish() {
|
||||
code=$?
|
||||
if [[ $code -gt 10 ]]; then
|
||||
jq . "${tmpdir}/creds.json"
|
||||
echo "could not update pg password: jq got null on line $code" >&2
|
||||
fi
|
||||
rm -rf "$tmpdir"
|
||||
exit $code
|
||||
}
|
||||
trap finish EXIT
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
umask 077
|
||||
|
||||
if [[ $(uname) != Darwin ]]; then
|
||||
pbcopy() {
|
||||
xsel --input --clipboard
|
||||
xsel --output --clipboard | xsel --input --primary
|
||||
}
|
||||
fi
|
||||
|
||||
sel="postgres-operator.crunchydata.com/pgadmin=${1}"
|
||||
|
||||
# secret="(kubectl -n "${NAMESPACE}" get secret --selector=$sel '--output=jsonpath={.items..metadata.name}')"
|
||||
|
||||
kubectl get secret "--selector=$sel" -o=json | jq '.items[].data | map_values(@base64d)' > "${tmpdir}/creds.json"
|
||||
|
||||
echo -n "username: "
|
||||
jq --exit-status -r ".username" "${tmpdir}/creds.json"
|
||||
password="$(jq --exit-status -r ".password" "${tmpdir}/creds.json")"
|
||||
# n.b. don't send the trailing newline.
|
||||
echo -n "$password" | pbcopy
|
||||
echo "password: copied to clipboard."
|
||||
53
hack/tilt/get-pgdb-creds
Executable file
53
hack/tilt/get-pgdb-creds
Executable file
@@ -0,0 +1,53 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
tmpdir="$(mktemp -d)"
|
||||
finish() {
|
||||
code=$?
|
||||
if [[ $code -gt 10 ]]; then
|
||||
jq . "${tmpdir}/creds.json"
|
||||
echo "could not update pg password: jq got null on line $code" >&2
|
||||
fi
|
||||
rm -rf "$tmpdir"
|
||||
exit $code
|
||||
}
|
||||
trap finish EXIT
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
umask 077
|
||||
|
||||
if [[ $(uname) != Darwin ]]; then
|
||||
pbcopy() {
|
||||
xsel --input --clipboard
|
||||
xsel --output --clipboard | xsel --input --primary
|
||||
}
|
||||
fi
|
||||
|
||||
kubectl get secret "${1}-pguser-${2}" -o json > "${tmpdir}/creds.json"
|
||||
|
||||
export PGDATABASE="$(jq --exit-status -r '.data | map_values(@base64d) | .dbname' ${tmpdir}/creds.json || exit $LINENO)"
|
||||
export PGUSER="$(jq --exit-status -r '.data | map_values(@base64d) | .user' ${tmpdir}/creds.json || exit $LINENO)"
|
||||
export PGPASSWORD="$(jq --exit-status -r '.data | map_values(@base64d) | .password' ${tmpdir}/creds.json || exit $LINENO)"
|
||||
|
||||
prefix="${PGHOST}:${PGPORT}:${PGDATABASE}:${PGUSER}"
|
||||
if [[ -f ~/.pgpass ]]; then
|
||||
(grep -v "^${prefix}:" ~/.pgpass || true) > "${tmpdir}/pgpass"
|
||||
fi
|
||||
echo "${prefix}:${PGPASSWORD}" >> "${tmpdir}/pgpass"
|
||||
cp "${tmpdir}/pgpass" ~/.pgpass
|
||||
echo "updated: ${HOME}/.pgpass" >&2
|
||||
cat <<EOF >&2
|
||||
|
||||
## Connect from a localhost shell through the port forward to the cluster
|
||||
export PGHOST=${PGHOST}
|
||||
export PGPORT=${PGPORT}
|
||||
export PGDATABASE=${PGDATABASE}
|
||||
export PGUSER=${PGUSER}
|
||||
|
||||
psql -c '\conninfo'
|
||||
EOF
|
||||
psql --host=${PGHOST} --port=${PGPORT} ${PGDATABASE} -c '\conninfo'
|
||||
|
||||
# n.b. do not send a trailing newline to xsel
|
||||
echo -n "$PGPASSWORD" | pbcopy
|
||||
echo "password: copied to clipboard."
|
||||
9
hack/tilt/gh-issue-view
Executable file
9
hack/tilt/gh-issue-view
Executable file
@@ -0,0 +1,9 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
set -euo pipefail
|
||||
issue="$(git rev-parse --abbrev-ref HEAD | tr -d -c 0-9)"
|
||||
if [[ -z $issue ]]; then
|
||||
echo "could not extract issue number from branch name" >&2
|
||||
exit 1
|
||||
fi
|
||||
exec gh issue view --comments $issue
|
||||
4
hack/tilt/gh-issues
Executable file
4
hack/tilt/gh-issues
Executable file
@@ -0,0 +1,4 @@
|
||||
#! /bin/bash
|
||||
set -euo pipefail
|
||||
export GH_FORCE_TTY='120%'
|
||||
exec gh issue list
|
||||
8
hack/tilt/go-test-failfast
Executable file
8
hack/tilt/go-test-failfast
Executable file
@@ -0,0 +1,8 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
set -euo pipefail
|
||||
for s in $(go list ./...); do
|
||||
if ! go test -failfast -v -p 1 $s; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
20
hack/tilt/k8s-get-db-sts
Executable file
20
hack/tilt/k8s-get-db-sts
Executable file
@@ -0,0 +1,20 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# Output the stateful set yaml of the database using selectors
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
sel="postgres-operator.crunchydata.com/cluster=${1},postgres-operator.crunchydata.com/instance-set=db"
|
||||
|
||||
x=30
|
||||
while [[ $x -gt 0 ]]; do
|
||||
for pod in $(kubectl get statefulsets --selector=$sel '--output=jsonpath={.items..metadata.name}'); do
|
||||
echo "---"
|
||||
kubectl get -o yaml statefulsets/$pod
|
||||
x=0
|
||||
done
|
||||
if [[ $x -gt 0 ]]; then
|
||||
((x--))
|
||||
sleep 1
|
||||
fi
|
||||
done
|
||||
5
hack/tilt/k8s-namespace
Executable file
5
hack/tilt/k8s-namespace
Executable file
@@ -0,0 +1,5 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
set -euo pipefail
|
||||
cp "${KUBECONFIG}.template" "${KUBECONFIG}"
|
||||
kubectl config set-context --current --namespace "${NAMESPACE}"
|
||||
308
hack/tilt/k8s.yaml
Normal file
308
hack/tilt/k8s.yaml
Normal file
@@ -0,0 +1,308 @@
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: '{name}'
|
||||
namespace: '{namespace}'
|
||||
labels:
|
||||
app: '{name}'
|
||||
holos.run/developer: '{developer}'
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: '{name}'
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: '{name}'
|
||||
holos.run/developer: '{developer}'
|
||||
sidecar.istio.io/inject: 'true'
|
||||
spec:
|
||||
serviceAccountName: holos
|
||||
containers:
|
||||
- name: holos
|
||||
image: holos # Tilt appends a tilt-* tag for the built docker image
|
||||
# args are configured in the Tiltfile
|
||||
env:
|
||||
- name: GOMAXPROCS
|
||||
value: '1'
|
||||
- name: TZ
|
||||
value: '{tz}'
|
||||
- name: SHUTDOWN_DELAY
|
||||
value: '0'
|
||||
- name: DATABASE_URL
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: holos-pguser-holos
|
||||
key: uri
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: {listen_port}
|
||||
protocol: TCP
|
||||
resources:
|
||||
requests:
|
||||
cpu: 250m
|
||||
memory: 100Mi
|
||||
limits:
|
||||
cpu: 1000m
|
||||
memory: 200Mi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: '{name}'
|
||||
namespace: '{namespace}'
|
||||
labels:
|
||||
app: '{name}'
|
||||
holos.run/developer: '{developer}'
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: '{name}'
|
||||
ports:
|
||||
- name: http
|
||||
port: {listen_port}
|
||||
appProtocol: http2
|
||||
protocol: TCP
|
||||
targetPort: {listen_port}
|
||||
- name: metrics
|
||||
port: {metrics_port}
|
||||
appProtocol: http
|
||||
protocol: TCP
|
||||
targetPort: {metrics_port}
|
||||
---
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: ServiceMonitor
|
||||
metadata:
|
||||
name: '{name}'
|
||||
namespace: '{namespace}'
|
||||
labels:
|
||||
app: '{name}'
|
||||
holos.run/developer: '{developer}'
|
||||
spec:
|
||||
endpoints:
|
||||
- port: metrics
|
||||
path: /metrics
|
||||
interval: 15s
|
||||
selector:
|
||||
matchLabels:
|
||||
app: '{name}'
|
||||
holos.run/developer: '{developer}'
|
||||
---
|
||||
apiVersion: networking.istio.io/v1beta1
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: '{name}'
|
||||
namespace: '{namespace}'
|
||||
labels:
|
||||
app: '{name}'
|
||||
holos.run/developer: '{developer}'
|
||||
spec:
|
||||
gateways:
|
||||
- istio-ingress/default
|
||||
hosts:
|
||||
- '{developer}.holos.dev.k2.ois.run'
|
||||
http:
|
||||
- route:
|
||||
- destination:
|
||||
host: '{name}'
|
||||
port:
|
||||
number: {listen_port}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: holos
|
||||
namespace: '{namespace}'
|
||||
labels:
|
||||
app: '{name}'
|
||||
holos.run/developer: '{developer}'
|
||||
imagePullSecrets:
|
||||
- name: kube-system-ecr-image-pull-creds
|
||||
---
|
||||
apiVersion: security.istio.io/v1beta1
|
||||
kind: AuthorizationPolicy
|
||||
metadata:
|
||||
labels:
|
||||
app: '{name}'
|
||||
holos.run/developer: '{developer}'
|
||||
name: '{name}-allow-groups'
|
||||
namespace: '{namespace}'
|
||||
spec:
|
||||
action: ALLOW
|
||||
rules:
|
||||
- when:
|
||||
- key: request.auth.claims[groups]
|
||||
values:
|
||||
- holos-developer
|
||||
- holos-developer@openinfrastructure.co
|
||||
selector:
|
||||
matchLabels:
|
||||
holos.run/authz: dev-holos-sso
|
||||
---
|
||||
apiVersion: security.istio.io/v1beta1
|
||||
kind: AuthorizationPolicy
|
||||
metadata:
|
||||
name: '{name}-allow-nothing'
|
||||
namespace: '{namespace}'
|
||||
labels:
|
||||
app: '{name}'
|
||||
holos.run/developer: '{developer}'
|
||||
spec:
|
||||
action: ALLOW
|
||||
selector:
|
||||
matchLabels:
|
||||
holos.run/authz: dev-holos-sso
|
||||
---
|
||||
apiVersion: security.istio.io/v1beta1
|
||||
kind: AuthorizationPolicy
|
||||
metadata:
|
||||
name: '{name}-allow-well-known-paths'
|
||||
namespace: '{namespace}'
|
||||
labels:
|
||||
app: '{name}'
|
||||
holos.run/developer: '{developer}'
|
||||
spec:
|
||||
action: ALLOW
|
||||
rules:
|
||||
- to:
|
||||
- operation:
|
||||
paths:
|
||||
- /healthz
|
||||
- /metrics
|
||||
- /callbacks/github
|
||||
selector:
|
||||
matchLabels:
|
||||
holos.run/authz: dev-holos-sso
|
||||
---
|
||||
apiVersion: security.istio.io/v1beta1
|
||||
kind: AuthorizationPolicy
|
||||
metadata:
|
||||
name: '{name}-auth'
|
||||
namespace: '{namespace}'
|
||||
labels:
|
||||
app: '{name}'
|
||||
holos.run/developer: '{developer}'
|
||||
spec:
|
||||
action: CUSTOM
|
||||
provider:
|
||||
name: dev-holos-sso
|
||||
rules:
|
||||
- to:
|
||||
- operation:
|
||||
notPaths:
|
||||
- /healthz
|
||||
- /metrics
|
||||
- /callbacks/github
|
||||
when:
|
||||
- key: request.headers[Authorization]
|
||||
notValues:
|
||||
- Bearer *
|
||||
selector:
|
||||
matchLabels:
|
||||
holos.run/authz: dev-holos-sso
|
||||
---
|
||||
apiVersion: security.istio.io/v1beta1
|
||||
kind: RequestAuthentication
|
||||
metadata:
|
||||
name: '{name}'
|
||||
namespace: '{namespace}'
|
||||
labels:
|
||||
app: '{name}'
|
||||
holos.run/developer: '{developer}'
|
||||
spec:
|
||||
jwtRules:
|
||||
- audiences:
|
||||
- https://sso.dev.holos.run
|
||||
forwardOriginalToken: true
|
||||
fromHeaders:
|
||||
- name: x-auth-request-access-token
|
||||
issuer: https://idex.core.ois.run
|
||||
jwksUri: https://idex.core.ois.run/keys
|
||||
- audiences:
|
||||
- holos-cli
|
||||
forwardOriginalToken: true
|
||||
fromHeaders:
|
||||
- name: authorization
|
||||
prefix: 'Bearer '
|
||||
issuer: https://idex.core.ois.run
|
||||
jwksUri: https://idex.core.ois.run/keys
|
||||
selector:
|
||||
matchLabels:
|
||||
holos.run/authz: dev-holos-sso
|
||||
---
|
||||
apiVersion: postgres-operator.crunchydata.com/v1beta1
|
||||
kind: PGAdmin
|
||||
metadata:
|
||||
name: 'pgadmin'
|
||||
namespace: '{namespace}'
|
||||
labels:
|
||||
holos.run/developer: '{developer}'
|
||||
spec:
|
||||
serverGroups:
|
||||
- name: holos
|
||||
postgresClusterSelector:
|
||||
matchLabels:
|
||||
holos.run/developer: '{developer}'
|
||||
dataVolumeClaimSpec:
|
||||
accessModes:
|
||||
- "ReadWriteOnce"
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
---
|
||||
apiVersion: postgres-operator.crunchydata.com/v1beta1
|
||||
kind: PostgresCluster
|
||||
metadata:
|
||||
name: 'holos'
|
||||
namespace: '{namespace}'
|
||||
labels:
|
||||
holos.run/developer: '{developer}'
|
||||
spec:
|
||||
image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres:ubi8-16.1-0
|
||||
postgresVersion: 16
|
||||
users:
|
||||
- name: holos
|
||||
databases:
|
||||
- holos
|
||||
options: 'SUPERUSER'
|
||||
- name: '{developer}'
|
||||
databases:
|
||||
- holos
|
||||
- '{developer}'
|
||||
options: 'SUPERUSER'
|
||||
# https://access.crunchydata.com/documentation/postgres-operator/latest/architecture/user-management
|
||||
instances:
|
||||
- name: db
|
||||
dataVolumeClaimSpec:
|
||||
accessModes:
|
||||
- "ReadWriteOnce"
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 1
|
||||
podAffinityTerm:
|
||||
topologyKey: kubernetes.io/hostname
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
postgres-operator.crunchydata.com/cluster: '{name}'
|
||||
backups:
|
||||
pgbackrest:
|
||||
image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.47-2
|
||||
# https://github.com/CrunchyData/postgres-operator/issues/2531#issuecomment-1713676019
|
||||
global:
|
||||
archive-async: "y"
|
||||
archive-push-queue-max: "100MiB"
|
||||
spool-path: "/pgdata/backups"
|
||||
repos:
|
||||
- name: repo1
|
||||
volume:
|
||||
volumeClaimSpec:
|
||||
accessModes:
|
||||
- "ReadWriteOnce"
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
45
hack/tilt/kubeconfig.template
Normal file
45
hack/tilt/kubeconfig.template
Normal file
@@ -0,0 +1,45 @@
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJpVENDQVRDZ0F3SUJBZ0lSQU9TenlHd2VMK3N4NjVvckVCTXV1c293Q2dZSUtvWkl6ajBFQXdJd0ZURVQKTUJFR0ExVUVDaE1LYTNWaVpYSnVaWFJsY3pBZUZ3MHlOREF5TVRNd05UQTRNRFJhRncwek5EQXlNVEF3TlRBNApNRFJhTUJVeEV6QVJCZ05WQkFvVENtdDFZbVZ5Ym1WMFpYTXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CCkJ3TkNBQVREWUluR09EN2ZpbFVIeXNpZG1ac2Vtd2liTk9hT1A5ZzVJT1VsTkllUHZ1Y01ZV01aNWNkZXpVQmIKMGh4Zm1WYXR0QWxpcnorMlFpVld5by9WZFNsOG8yRXdYekFPQmdOVkhROEJBZjhFQkFNQ0FvUXdIUVlEVlIwbApCQll3RkFZSUt3WUJCUVVIQXdFR0NDc0dBUVVGQndNQ01BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0hRWURWUjBPCkJCWUVGTGVtcEhSM25lVXYvSUc1WWpwempDbWUydmIyTUFvR0NDcUdTTTQ5QkFNQ0EwY0FNRVFDSUNZajRsNUgKL043OG5UcnJxQzMxWjlsY0lpODEwcno5N3JIdUJnWFZZUkxBQWlBNHVEc0YyNEI5aGV3WklUbWEwaHpCMjNOdQpwZnprTWV5VzZHV2U2RWh4NGc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
|
||||
server: https://k2.core.ois.run:6443
|
||||
name: k2
|
||||
contexts:
|
||||
- context:
|
||||
cluster: k2
|
||||
namespace: default
|
||||
user: admin@k2
|
||||
name: admin@k2
|
||||
- context:
|
||||
cluster: k2
|
||||
namespace: ${NAMESPACE}
|
||||
user: oidc
|
||||
name: sso@k2
|
||||
current-context: sso@k2
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: admin@k2
|
||||
user:
|
||||
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJoRENDQVNxZ0F3SUJBZ0lRVXZKTlEvV0Ewalg5RXF6ZElIMFA4ekFLQmdncWhrak9QUVFEQWpBVk1STXcKRVFZRFZRUUtFd3ByZFdKbGNtNWxkR1Z6TUI0WERUSTBNRE14TVRJek1UY3hPVm9YRFRJMU1ETXhNVEl6TVRjeQpPVm93S1RFWE1CVUdBMVVFQ2hNT2MzbHpkR1Z0T20xaGMzUmxjbk14RGpBTUJnTlZCQU1UQldGa2JXbHVNRmt3CkV3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFNjZrMStQb1l5OHlPWTZkRFR5MHJYRTUvRlZJVU0rbkcKNEVzSXZxOHBuZ2lVRWRkeTdYM3hvZ2E5d2NSZy8xeVZ4Q2FNbzBUVEZveXkxaVZMMWxGWDNLTklNRVl3RGdZRApWUjBQQVFIL0JBUURBZ1dnTUJNR0ExVWRKUVFNTUFvR0NDc0dBUVVGQndNQ01COEdBMVVkSXdRWU1CYUFGTGVtCnBIUjNuZVV2L0lHNVlqcHpqQ21lMnZiMk1Bb0dDQ3FHU000OUJBTUNBMGdBTUVVQ0lDaDVGTWlXV3hxVHYyc0wKQVdvQ2lxaWJ0OUNUMnpsNzRlSTllMEZPTzRKTkFpRUF5T0wwR3RxVnlTSHUzbUsvVDBxZFhYQ3dmdHdWQVE4cgo2ejJWaVZrMzg2dz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
|
||||
client-key-data: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSURtdTh0UGVrRmhlNzRXWm5idXlwOFZ1VUIxTVYwcTN4QklOclVVbjBaRjVvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFNjZrMStQb1l5OHlPWTZkRFR5MHJYRTUvRlZJVU0rbkc0RXNJdnE4cG5naVVFZGR5N1gzeApvZ2E5d2NSZy8xeVZ4Q2FNbzBUVEZveXkxaVZMMWxGWDNBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
|
||||
- name: oidc
|
||||
user:
|
||||
exec:
|
||||
apiVersion: client.authentication.k8s.io/v1beta1
|
||||
args:
|
||||
- oidc-login
|
||||
- get-token
|
||||
- --oidc-issuer-url=https://login.ois.run
|
||||
- --oidc-client-id=261774567918339420@holos_platform
|
||||
- --oidc-extra-scope=openid
|
||||
- --oidc-extra-scope=email
|
||||
- --oidc-extra-scope=profile
|
||||
- --oidc-extra-scope=groups
|
||||
- --oidc-extra-scope=offline_access
|
||||
- --oidc-extra-scope=urn:zitadel:iam:org:domain:primary:openinfrastructure.co
|
||||
- --oidc-use-pkce
|
||||
command: kubectl
|
||||
env: null
|
||||
interactiveMode: IfAvailable
|
||||
provideClusterInfo: false
|
||||
33
hack/tilt/pgpass-zalando
Executable file
33
hack/tilt/pgpass-zalando
Executable file
@@ -0,0 +1,33 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
tmpdir="$(mktemp -d)"
|
||||
finish() {
|
||||
rm -rf "$tmpdir"
|
||||
}
|
||||
trap finish EXIT
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
umask 077
|
||||
|
||||
kubectl -n "dev-${USER}" get secret "${USER}.holos-server-db.credentials.postgresql.acid.zalan.do" -o json > "${tmpdir}/creds.json"
|
||||
if [[ -f ~/.pgpass ]]; then
|
||||
(grep -v "^localhost:14126:holos:${USER}:" ~/.pgpass || true) > "${tmpdir}/pgpass"
|
||||
fi
|
||||
PGUSER="$(jq -r '.data | map_values(@base64d) | .username' ${tmpdir}/creds.json)"
|
||||
PGPASSWORD="$(jq -r '.data | map_values(@base64d) | .password' ${tmpdir}/creds.json)"
|
||||
|
||||
echo "${PGHOST}:${PGPORT}:${PGDATABASE}:${PGUSER}:${PGPASSWORD}" >> "${tmpdir}/pgpass"
|
||||
cp "${tmpdir}/pgpass" ~/.pgpass
|
||||
echo "updated: ${HOME}/.pgpass" >&2
|
||||
cat <<EOF >&2
|
||||
|
||||
## Connect from a localhost shell through the port forward to the cluster
|
||||
export PGHOST=${PGHOST}
|
||||
export PGPORT=${PGPORT}
|
||||
export PGDATABASE=${PGDATABASE}
|
||||
export PGUSER=${PGUSER}
|
||||
|
||||
psql -c '\conninfo'
|
||||
EOF
|
||||
psql --host=${PGHOST} --port=${PGPORT} ${PGDATABASE} -c '\conninfo'
|
||||
484
internal/ent/client.go
Normal file
484
internal/ent/client.go
Normal file
@@ -0,0 +1,484 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"reflect"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/holos-run/holos/internal/ent/migrate"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"github.com/holos-run/holos/internal/ent/organization"
|
||||
"github.com/holos-run/holos/internal/ent/user"
|
||||
)
|
||||
|
||||
// Client is the client that holds all ent builders.
|
||||
type Client struct {
|
||||
config
|
||||
// Schema is the client for creating, migrating and dropping schema.
|
||||
Schema *migrate.Schema
|
||||
// Organization is the client for interacting with the Organization builders.
|
||||
Organization *OrganizationClient
|
||||
// User is the client for interacting with the User builders.
|
||||
User *UserClient
|
||||
}
|
||||
|
||||
// NewClient creates a new client configured with the given options.
|
||||
func NewClient(opts ...Option) *Client {
|
||||
client := &Client{config: newConfig(opts...)}
|
||||
client.init()
|
||||
return client
|
||||
}
|
||||
|
||||
func (c *Client) init() {
|
||||
c.Schema = migrate.NewSchema(c.driver)
|
||||
c.Organization = NewOrganizationClient(c.config)
|
||||
c.User = NewUserClient(c.config)
|
||||
}
|
||||
|
||||
type (
|
||||
// config is the configuration for the client and its builder.
|
||||
config struct {
|
||||
// driver used for executing database requests.
|
||||
driver dialect.Driver
|
||||
// debug enable a debug logging.
|
||||
debug bool
|
||||
// log used for logging on debug mode.
|
||||
log func(...any)
|
||||
// hooks to execute on mutations.
|
||||
hooks *hooks
|
||||
// interceptors to execute on queries.
|
||||
inters *inters
|
||||
}
|
||||
// Option function to configure the client.
|
||||
Option func(*config)
|
||||
)
|
||||
|
||||
// newConfig creates a new config for the client.
|
||||
func newConfig(opts ...Option) config {
|
||||
cfg := config{log: log.Println, hooks: &hooks{}, inters: &inters{}}
|
||||
cfg.options(opts...)
|
||||
return cfg
|
||||
}
|
||||
|
||||
// options applies the options on the config object.
|
||||
func (c *config) options(opts ...Option) {
|
||||
for _, opt := range opts {
|
||||
opt(c)
|
||||
}
|
||||
if c.debug {
|
||||
c.driver = dialect.Debug(c.driver, c.log)
|
||||
}
|
||||
}
|
||||
|
||||
// Debug enables debug logging on the ent.Driver.
|
||||
func Debug() Option {
|
||||
return func(c *config) {
|
||||
c.debug = true
|
||||
}
|
||||
}
|
||||
|
||||
// Log sets the logging function for debug mode.
|
||||
func Log(fn func(...any)) Option {
|
||||
return func(c *config) {
|
||||
c.log = fn
|
||||
}
|
||||
}
|
||||
|
||||
// Driver configures the client driver.
|
||||
func Driver(driver dialect.Driver) Option {
|
||||
return func(c *config) {
|
||||
c.driver = driver
|
||||
}
|
||||
}
|
||||
|
||||
// Open opens a database/sql.DB specified by the driver name and
|
||||
// the data source name, and returns a new client attached to it.
|
||||
// Optional parameters can be added for configuring the client.
|
||||
func Open(driverName, dataSourceName string, options ...Option) (*Client, error) {
|
||||
switch driverName {
|
||||
case dialect.MySQL, dialect.Postgres, dialect.SQLite:
|
||||
drv, err := sql.Open(driverName, dataSourceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewClient(append(options, Driver(drv))...), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported driver: %q", driverName)
|
||||
}
|
||||
}
|
||||
|
||||
// ErrTxStarted is returned when trying to start a new transaction from a transactional client.
|
||||
var ErrTxStarted = errors.New("ent: cannot start a transaction within a transaction")
|
||||
|
||||
// Tx returns a new transactional client. The provided context
|
||||
// is used until the transaction is committed or rolled back.
|
||||
func (c *Client) Tx(ctx context.Context) (*Tx, error) {
|
||||
if _, ok := c.driver.(*txDriver); ok {
|
||||
return nil, ErrTxStarted
|
||||
}
|
||||
tx, err := newTx(ctx, c.driver)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ent: starting a transaction: %w", err)
|
||||
}
|
||||
cfg := c.config
|
||||
cfg.driver = tx
|
||||
return &Tx{
|
||||
ctx: ctx,
|
||||
config: cfg,
|
||||
Organization: NewOrganizationClient(cfg),
|
||||
User: NewUserClient(cfg),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// BeginTx returns a transactional client with specified options.
|
||||
func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) {
|
||||
if _, ok := c.driver.(*txDriver); ok {
|
||||
return nil, errors.New("ent: cannot start a transaction within a transaction")
|
||||
}
|
||||
tx, err := c.driver.(interface {
|
||||
BeginTx(context.Context, *sql.TxOptions) (dialect.Tx, error)
|
||||
}).BeginTx(ctx, opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ent: starting a transaction: %w", err)
|
||||
}
|
||||
cfg := c.config
|
||||
cfg.driver = &txDriver{tx: tx, drv: c.driver}
|
||||
return &Tx{
|
||||
ctx: ctx,
|
||||
config: cfg,
|
||||
Organization: NewOrganizationClient(cfg),
|
||||
User: NewUserClient(cfg),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Debug returns a new debug-client. It's used to get verbose logging on specific operations.
|
||||
//
|
||||
// client.Debug().
|
||||
// Organization.
|
||||
// Query().
|
||||
// Count(ctx)
|
||||
func (c *Client) Debug() *Client {
|
||||
if c.debug {
|
||||
return c
|
||||
}
|
||||
cfg := c.config
|
||||
cfg.driver = dialect.Debug(c.driver, c.log)
|
||||
client := &Client{config: cfg}
|
||||
client.init()
|
||||
return client
|
||||
}
|
||||
|
||||
// Close closes the database connection and prevents new queries from starting.
|
||||
func (c *Client) Close() error {
|
||||
return c.driver.Close()
|
||||
}
|
||||
|
||||
// Use adds the mutation hooks to all the entity clients.
|
||||
// In order to add hooks to a specific client, call: `client.Node.Use(...)`.
|
||||
func (c *Client) Use(hooks ...Hook) {
|
||||
c.Organization.Use(hooks...)
|
||||
c.User.Use(hooks...)
|
||||
}
|
||||
|
||||
// Intercept adds the query interceptors to all the entity clients.
|
||||
// In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`.
|
||||
func (c *Client) Intercept(interceptors ...Interceptor) {
|
||||
c.Organization.Intercept(interceptors...)
|
||||
c.User.Intercept(interceptors...)
|
||||
}
|
||||
|
||||
// Mutate implements the ent.Mutator interface.
|
||||
func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
|
||||
switch m := m.(type) {
|
||||
case *OrganizationMutation:
|
||||
return c.Organization.mutate(ctx, m)
|
||||
case *UserMutation:
|
||||
return c.User.mutate(ctx, m)
|
||||
default:
|
||||
return nil, fmt.Errorf("ent: unknown mutation type %T", m)
|
||||
}
|
||||
}
|
||||
|
||||
// OrganizationClient is a client for the Organization schema.
|
||||
type OrganizationClient struct {
|
||||
config
|
||||
}
|
||||
|
||||
// NewOrganizationClient returns a client for the Organization from the given config.
|
||||
func NewOrganizationClient(c config) *OrganizationClient {
|
||||
return &OrganizationClient{config: c}
|
||||
}
|
||||
|
||||
// Use adds a list of mutation hooks to the hooks stack.
|
||||
// A call to `Use(f, g, h)` equals to `organization.Hooks(f(g(h())))`.
|
||||
func (c *OrganizationClient) Use(hooks ...Hook) {
|
||||
c.hooks.Organization = append(c.hooks.Organization, hooks...)
|
||||
}
|
||||
|
||||
// Intercept adds a list of query interceptors to the interceptors stack.
|
||||
// A call to `Intercept(f, g, h)` equals to `organization.Intercept(f(g(h())))`.
|
||||
func (c *OrganizationClient) Intercept(interceptors ...Interceptor) {
|
||||
c.inters.Organization = append(c.inters.Organization, interceptors...)
|
||||
}
|
||||
|
||||
// Create returns a builder for creating a Organization entity.
|
||||
func (c *OrganizationClient) Create() *OrganizationCreate {
|
||||
mutation := newOrganizationMutation(c.config, OpCreate)
|
||||
return &OrganizationCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// CreateBulk returns a builder for creating a bulk of Organization entities.
|
||||
func (c *OrganizationClient) CreateBulk(builders ...*OrganizationCreate) *OrganizationCreateBulk {
|
||||
return &OrganizationCreateBulk{config: c.config, builders: builders}
|
||||
}
|
||||
|
||||
// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
|
||||
// a builder and applies setFunc on it.
|
||||
func (c *OrganizationClient) MapCreateBulk(slice any, setFunc func(*OrganizationCreate, int)) *OrganizationCreateBulk {
|
||||
rv := reflect.ValueOf(slice)
|
||||
if rv.Kind() != reflect.Slice {
|
||||
return &OrganizationCreateBulk{err: fmt.Errorf("calling to OrganizationClient.MapCreateBulk with wrong type %T, need slice", slice)}
|
||||
}
|
||||
builders := make([]*OrganizationCreate, rv.Len())
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
builders[i] = c.Create()
|
||||
setFunc(builders[i], i)
|
||||
}
|
||||
return &OrganizationCreateBulk{config: c.config, builders: builders}
|
||||
}
|
||||
|
||||
// Update returns an update builder for Organization.
|
||||
func (c *OrganizationClient) Update() *OrganizationUpdate {
|
||||
mutation := newOrganizationMutation(c.config, OpUpdate)
|
||||
return &OrganizationUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOne returns an update builder for the given entity.
|
||||
func (c *OrganizationClient) UpdateOne(o *Organization) *OrganizationUpdateOne {
|
||||
mutation := newOrganizationMutation(c.config, OpUpdateOne, withOrganization(o))
|
||||
return &OrganizationUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOneID returns an update builder for the given id.
|
||||
func (c *OrganizationClient) UpdateOneID(id uuid.UUID) *OrganizationUpdateOne {
|
||||
mutation := newOrganizationMutation(c.config, OpUpdateOne, withOrganizationID(id))
|
||||
return &OrganizationUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// Delete returns a delete builder for Organization.
|
||||
func (c *OrganizationClient) Delete() *OrganizationDelete {
|
||||
mutation := newOrganizationMutation(c.config, OpDelete)
|
||||
return &OrganizationDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// DeleteOne returns a builder for deleting the given entity.
|
||||
func (c *OrganizationClient) DeleteOne(o *Organization) *OrganizationDeleteOne {
|
||||
return c.DeleteOneID(o.ID)
|
||||
}
|
||||
|
||||
// DeleteOneID returns a builder for deleting the given entity by its id.
|
||||
func (c *OrganizationClient) DeleteOneID(id uuid.UUID) *OrganizationDeleteOne {
|
||||
builder := c.Delete().Where(organization.ID(id))
|
||||
builder.mutation.id = &id
|
||||
builder.mutation.op = OpDeleteOne
|
||||
return &OrganizationDeleteOne{builder}
|
||||
}
|
||||
|
||||
// Query returns a query builder for Organization.
|
||||
func (c *OrganizationClient) Query() *OrganizationQuery {
|
||||
return &OrganizationQuery{
|
||||
config: c.config,
|
||||
ctx: &QueryContext{Type: TypeOrganization},
|
||||
inters: c.Interceptors(),
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns a Organization entity by its id.
|
||||
func (c *OrganizationClient) Get(ctx context.Context, id uuid.UUID) (*Organization, error) {
|
||||
return c.Query().Where(organization.ID(id)).Only(ctx)
|
||||
}
|
||||
|
||||
// GetX is like Get, but panics if an error occurs.
|
||||
func (c *OrganizationClient) GetX(ctx context.Context, id uuid.UUID) *Organization {
|
||||
obj, err := c.Get(ctx, id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
// Hooks returns the client hooks.
|
||||
func (c *OrganizationClient) Hooks() []Hook {
|
||||
return c.hooks.Organization
|
||||
}
|
||||
|
||||
// Interceptors returns the client interceptors.
|
||||
func (c *OrganizationClient) Interceptors() []Interceptor {
|
||||
return c.inters.Organization
|
||||
}
|
||||
|
||||
func (c *OrganizationClient) mutate(ctx context.Context, m *OrganizationMutation) (Value, error) {
|
||||
switch m.Op() {
|
||||
case OpCreate:
|
||||
return (&OrganizationCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdate:
|
||||
return (&OrganizationUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdateOne:
|
||||
return (&OrganizationUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpDelete, OpDeleteOne:
|
||||
return (&OrganizationDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
|
||||
default:
|
||||
return nil, fmt.Errorf("ent: unknown Organization mutation op: %q", m.Op())
|
||||
}
|
||||
}
|
||||
|
||||
// UserClient is a client for the User schema.
|
||||
type UserClient struct {
|
||||
config
|
||||
}
|
||||
|
||||
// NewUserClient returns a client for the User from the given config.
|
||||
func NewUserClient(c config) *UserClient {
|
||||
return &UserClient{config: c}
|
||||
}
|
||||
|
||||
// Use adds a list of mutation hooks to the hooks stack.
|
||||
// A call to `Use(f, g, h)` equals to `user.Hooks(f(g(h())))`.
|
||||
func (c *UserClient) Use(hooks ...Hook) {
|
||||
c.hooks.User = append(c.hooks.User, hooks...)
|
||||
}
|
||||
|
||||
// Intercept adds a list of query interceptors to the interceptors stack.
|
||||
// A call to `Intercept(f, g, h)` equals to `user.Intercept(f(g(h())))`.
|
||||
func (c *UserClient) Intercept(interceptors ...Interceptor) {
|
||||
c.inters.User = append(c.inters.User, interceptors...)
|
||||
}
|
||||
|
||||
// Create returns a builder for creating a User entity.
|
||||
func (c *UserClient) Create() *UserCreate {
|
||||
mutation := newUserMutation(c.config, OpCreate)
|
||||
return &UserCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// CreateBulk returns a builder for creating a bulk of User entities.
|
||||
func (c *UserClient) CreateBulk(builders ...*UserCreate) *UserCreateBulk {
|
||||
return &UserCreateBulk{config: c.config, builders: builders}
|
||||
}
|
||||
|
||||
// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
|
||||
// a builder and applies setFunc on it.
|
||||
func (c *UserClient) MapCreateBulk(slice any, setFunc func(*UserCreate, int)) *UserCreateBulk {
|
||||
rv := reflect.ValueOf(slice)
|
||||
if rv.Kind() != reflect.Slice {
|
||||
return &UserCreateBulk{err: fmt.Errorf("calling to UserClient.MapCreateBulk with wrong type %T, need slice", slice)}
|
||||
}
|
||||
builders := make([]*UserCreate, rv.Len())
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
builders[i] = c.Create()
|
||||
setFunc(builders[i], i)
|
||||
}
|
||||
return &UserCreateBulk{config: c.config, builders: builders}
|
||||
}
|
||||
|
||||
// Update returns an update builder for User.
|
||||
func (c *UserClient) Update() *UserUpdate {
|
||||
mutation := newUserMutation(c.config, OpUpdate)
|
||||
return &UserUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOne returns an update builder for the given entity.
|
||||
func (c *UserClient) UpdateOne(u *User) *UserUpdateOne {
|
||||
mutation := newUserMutation(c.config, OpUpdateOne, withUser(u))
|
||||
return &UserUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOneID returns an update builder for the given id.
|
||||
func (c *UserClient) UpdateOneID(id uuid.UUID) *UserUpdateOne {
|
||||
mutation := newUserMutation(c.config, OpUpdateOne, withUserID(id))
|
||||
return &UserUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// Delete returns a delete builder for User.
|
||||
func (c *UserClient) Delete() *UserDelete {
|
||||
mutation := newUserMutation(c.config, OpDelete)
|
||||
return &UserDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// DeleteOne returns a builder for deleting the given entity.
|
||||
func (c *UserClient) DeleteOne(u *User) *UserDeleteOne {
|
||||
return c.DeleteOneID(u.ID)
|
||||
}
|
||||
|
||||
// DeleteOneID returns a builder for deleting the given entity by its id.
|
||||
func (c *UserClient) DeleteOneID(id uuid.UUID) *UserDeleteOne {
|
||||
builder := c.Delete().Where(user.ID(id))
|
||||
builder.mutation.id = &id
|
||||
builder.mutation.op = OpDeleteOne
|
||||
return &UserDeleteOne{builder}
|
||||
}
|
||||
|
||||
// Query returns a query builder for User.
|
||||
func (c *UserClient) Query() *UserQuery {
|
||||
return &UserQuery{
|
||||
config: c.config,
|
||||
ctx: &QueryContext{Type: TypeUser},
|
||||
inters: c.Interceptors(),
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns a User entity by its id.
|
||||
func (c *UserClient) Get(ctx context.Context, id uuid.UUID) (*User, error) {
|
||||
return c.Query().Where(user.ID(id)).Only(ctx)
|
||||
}
|
||||
|
||||
// GetX is like Get, but panics if an error occurs.
|
||||
func (c *UserClient) GetX(ctx context.Context, id uuid.UUID) *User {
|
||||
obj, err := c.Get(ctx, id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
// Hooks returns the client hooks.
|
||||
func (c *UserClient) Hooks() []Hook {
|
||||
return c.hooks.User
|
||||
}
|
||||
|
||||
// Interceptors returns the client interceptors.
|
||||
func (c *UserClient) Interceptors() []Interceptor {
|
||||
return c.inters.User
|
||||
}
|
||||
|
||||
func (c *UserClient) mutate(ctx context.Context, m *UserMutation) (Value, error) {
|
||||
switch m.Op() {
|
||||
case OpCreate:
|
||||
return (&UserCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdate:
|
||||
return (&UserUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdateOne:
|
||||
return (&UserUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpDelete, OpDeleteOne:
|
||||
return (&UserDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
|
||||
default:
|
||||
return nil, fmt.Errorf("ent: unknown User mutation op: %q", m.Op())
|
||||
}
|
||||
}
|
||||
|
||||
// hooks and interceptors per client, for fast access.
|
||||
type (
|
||||
hooks struct {
|
||||
Organization, User []ent.Hook
|
||||
}
|
||||
inters struct {
|
||||
Organization, User []ent.Interceptor
|
||||
}
|
||||
)
|
||||
610
internal/ent/ent.go
Normal file
610
internal/ent/ent.go
Normal file
@@ -0,0 +1,610 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"github.com/holos-run/holos/internal/ent/organization"
|
||||
"github.com/holos-run/holos/internal/ent/user"
|
||||
)
|
||||
|
||||
// ent aliases to avoid import conflicts in user's code.
|
||||
type (
|
||||
Op = ent.Op
|
||||
Hook = ent.Hook
|
||||
Value = ent.Value
|
||||
Query = ent.Query
|
||||
QueryContext = ent.QueryContext
|
||||
Querier = ent.Querier
|
||||
QuerierFunc = ent.QuerierFunc
|
||||
Interceptor = ent.Interceptor
|
||||
InterceptFunc = ent.InterceptFunc
|
||||
Traverser = ent.Traverser
|
||||
TraverseFunc = ent.TraverseFunc
|
||||
Policy = ent.Policy
|
||||
Mutator = ent.Mutator
|
||||
Mutation = ent.Mutation
|
||||
MutateFunc = ent.MutateFunc
|
||||
)
|
||||
|
||||
type clientCtxKey struct{}
|
||||
|
||||
// FromContext returns a Client stored inside a context, or nil if there isn't one.
|
||||
func FromContext(ctx context.Context) *Client {
|
||||
c, _ := ctx.Value(clientCtxKey{}).(*Client)
|
||||
return c
|
||||
}
|
||||
|
||||
// NewContext returns a new context with the given Client attached.
|
||||
func NewContext(parent context.Context, c *Client) context.Context {
|
||||
return context.WithValue(parent, clientCtxKey{}, c)
|
||||
}
|
||||
|
||||
type txCtxKey struct{}
|
||||
|
||||
// TxFromContext returns a Tx stored inside a context, or nil if there isn't one.
|
||||
func TxFromContext(ctx context.Context) *Tx {
|
||||
tx, _ := ctx.Value(txCtxKey{}).(*Tx)
|
||||
return tx
|
||||
}
|
||||
|
||||
// NewTxContext returns a new context with the given Tx attached.
|
||||
func NewTxContext(parent context.Context, tx *Tx) context.Context {
|
||||
return context.WithValue(parent, txCtxKey{}, tx)
|
||||
}
|
||||
|
||||
// OrderFunc applies an ordering on the sql selector.
|
||||
// Deprecated: Use Asc/Desc functions or the package builders instead.
|
||||
type OrderFunc func(*sql.Selector)
|
||||
|
||||
var (
|
||||
initCheck sync.Once
|
||||
columnCheck sql.ColumnCheck
|
||||
)
|
||||
|
||||
// columnChecker checks if the column exists in the given table.
|
||||
func checkColumn(table, column string) error {
|
||||
initCheck.Do(func() {
|
||||
columnCheck = sql.NewColumnCheck(map[string]func(string) bool{
|
||||
organization.Table: organization.ValidColumn,
|
||||
user.Table: user.ValidColumn,
|
||||
})
|
||||
})
|
||||
return columnCheck(table, column)
|
||||
}
|
||||
|
||||
// Asc applies the given fields in ASC order.
|
||||
func Asc(fields ...string) func(*sql.Selector) {
|
||||
return func(s *sql.Selector) {
|
||||
for _, f := range fields {
|
||||
if err := checkColumn(s.TableName(), f); err != nil {
|
||||
s.AddError(&ValidationError{Name: f, err: fmt.Errorf("ent: %w", err)})
|
||||
}
|
||||
s.OrderBy(sql.Asc(s.C(f)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Desc applies the given fields in DESC order.
|
||||
func Desc(fields ...string) func(*sql.Selector) {
|
||||
return func(s *sql.Selector) {
|
||||
for _, f := range fields {
|
||||
if err := checkColumn(s.TableName(), f); err != nil {
|
||||
s.AddError(&ValidationError{Name: f, err: fmt.Errorf("ent: %w", err)})
|
||||
}
|
||||
s.OrderBy(sql.Desc(s.C(f)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AggregateFunc applies an aggregation step on the group-by traversal/selector.
|
||||
type AggregateFunc func(*sql.Selector) string
|
||||
|
||||
// As is a pseudo aggregation function for renaming another other functions with custom names. For example:
|
||||
//
|
||||
// GroupBy(field1, field2).
|
||||
// Aggregate(ent.As(ent.Sum(field1), "sum_field1"), (ent.As(ent.Sum(field2), "sum_field2")).
|
||||
// Scan(ctx, &v)
|
||||
func As(fn AggregateFunc, end string) AggregateFunc {
|
||||
return func(s *sql.Selector) string {
|
||||
return sql.As(fn(s), end)
|
||||
}
|
||||
}
|
||||
|
||||
// Count applies the "count" aggregation function on each group.
|
||||
func Count() AggregateFunc {
|
||||
return func(s *sql.Selector) string {
|
||||
return sql.Count("*")
|
||||
}
|
||||
}
|
||||
|
||||
// Max applies the "max" aggregation function on the given field of each group.
|
||||
func Max(field string) AggregateFunc {
|
||||
return func(s *sql.Selector) string {
|
||||
if err := checkColumn(s.TableName(), field); err != nil {
|
||||
s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)})
|
||||
return ""
|
||||
}
|
||||
return sql.Max(s.C(field))
|
||||
}
|
||||
}
|
||||
|
||||
// Mean applies the "mean" aggregation function on the given field of each group.
|
||||
func Mean(field string) AggregateFunc {
|
||||
return func(s *sql.Selector) string {
|
||||
if err := checkColumn(s.TableName(), field); err != nil {
|
||||
s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)})
|
||||
return ""
|
||||
}
|
||||
return sql.Avg(s.C(field))
|
||||
}
|
||||
}
|
||||
|
||||
// Min applies the "min" aggregation function on the given field of each group.
|
||||
func Min(field string) AggregateFunc {
|
||||
return func(s *sql.Selector) string {
|
||||
if err := checkColumn(s.TableName(), field); err != nil {
|
||||
s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)})
|
||||
return ""
|
||||
}
|
||||
return sql.Min(s.C(field))
|
||||
}
|
||||
}
|
||||
|
||||
// Sum applies the "sum" aggregation function on the given field of each group.
|
||||
func Sum(field string) AggregateFunc {
|
||||
return func(s *sql.Selector) string {
|
||||
if err := checkColumn(s.TableName(), field); err != nil {
|
||||
s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)})
|
||||
return ""
|
||||
}
|
||||
return sql.Sum(s.C(field))
|
||||
}
|
||||
}
|
||||
|
||||
// ValidationError returns when validating a field or edge fails.
|
||||
type ValidationError struct {
|
||||
Name string // Field or edge name.
|
||||
err error
|
||||
}
|
||||
|
||||
// Error implements the error interface.
|
||||
func (e *ValidationError) Error() string {
|
||||
return e.err.Error()
|
||||
}
|
||||
|
||||
// Unwrap implements the errors.Wrapper interface.
|
||||
func (e *ValidationError) Unwrap() error {
|
||||
return e.err
|
||||
}
|
||||
|
||||
// IsValidationError returns a boolean indicating whether the error is a validation error.
|
||||
func IsValidationError(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
var e *ValidationError
|
||||
return errors.As(err, &e)
|
||||
}
|
||||
|
||||
// NotFoundError returns when trying to fetch a specific entity and it was not found in the database.
|
||||
type NotFoundError struct {
|
||||
label string
|
||||
}
|
||||
|
||||
// Error implements the error interface.
|
||||
func (e *NotFoundError) Error() string {
|
||||
return "ent: " + e.label + " not found"
|
||||
}
|
||||
|
||||
// IsNotFound returns a boolean indicating whether the error is a not found error.
|
||||
func IsNotFound(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
var e *NotFoundError
|
||||
return errors.As(err, &e)
|
||||
}
|
||||
|
||||
// MaskNotFound masks not found error.
|
||||
func MaskNotFound(err error) error {
|
||||
if IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// NotSingularError returns when trying to fetch a singular entity and more then one was found in the database.
|
||||
type NotSingularError struct {
|
||||
label string
|
||||
}
|
||||
|
||||
// Error implements the error interface.
|
||||
func (e *NotSingularError) Error() string {
|
||||
return "ent: " + e.label + " not singular"
|
||||
}
|
||||
|
||||
// IsNotSingular returns a boolean indicating whether the error is a not singular error.
|
||||
func IsNotSingular(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
var e *NotSingularError
|
||||
return errors.As(err, &e)
|
||||
}
|
||||
|
||||
// NotLoadedError returns when trying to get a node that was not loaded by the query.
|
||||
type NotLoadedError struct {
|
||||
edge string
|
||||
}
|
||||
|
||||
// Error implements the error interface.
|
||||
func (e *NotLoadedError) Error() string {
|
||||
return "ent: " + e.edge + " edge was not loaded"
|
||||
}
|
||||
|
||||
// IsNotLoaded returns a boolean indicating whether the error is a not loaded error.
|
||||
func IsNotLoaded(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
var e *NotLoadedError
|
||||
return errors.As(err, &e)
|
||||
}
|
||||
|
||||
// ConstraintError returns when trying to create/update one or more entities and
|
||||
// one or more of their constraints failed. For example, violation of edge or
|
||||
// field uniqueness.
|
||||
type ConstraintError struct {
|
||||
msg string
|
||||
wrap error
|
||||
}
|
||||
|
||||
// Error implements the error interface.
|
||||
func (e ConstraintError) Error() string {
|
||||
return "ent: constraint failed: " + e.msg
|
||||
}
|
||||
|
||||
// Unwrap implements the errors.Wrapper interface.
|
||||
func (e *ConstraintError) Unwrap() error {
|
||||
return e.wrap
|
||||
}
|
||||
|
||||
// IsConstraintError returns a boolean indicating whether the error is a constraint failure.
|
||||
func IsConstraintError(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
var e *ConstraintError
|
||||
return errors.As(err, &e)
|
||||
}
|
||||
|
||||
// selector embedded by the different Select/GroupBy builders.
|
||||
type selector struct {
|
||||
label string
|
||||
flds *[]string
|
||||
fns []AggregateFunc
|
||||
scan func(context.Context, any) error
|
||||
}
|
||||
|
||||
// ScanX is like Scan, but panics if an error occurs.
|
||||
func (s *selector) ScanX(ctx context.Context, v any) {
|
||||
if err := s.scan(ctx, v); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Strings returns list of strings from a selector. It is only allowed when selecting one field.
|
||||
func (s *selector) Strings(ctx context.Context) ([]string, error) {
|
||||
if len(*s.flds) > 1 {
|
||||
return nil, errors.New("ent: Strings is not achievable when selecting more than 1 field")
|
||||
}
|
||||
var v []string
|
||||
if err := s.scan(ctx, &v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// StringsX is like Strings, but panics if an error occurs.
|
||||
func (s *selector) StringsX(ctx context.Context) []string {
|
||||
v, err := s.Strings(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// String returns a single string from a selector. It is only allowed when selecting one field.
|
||||
func (s *selector) String(ctx context.Context) (_ string, err error) {
|
||||
var v []string
|
||||
if v, err = s.Strings(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(v) {
|
||||
case 1:
|
||||
return v[0], nil
|
||||
case 0:
|
||||
err = &NotFoundError{s.label}
|
||||
default:
|
||||
err = fmt.Errorf("ent: Strings returned %d results when one was expected", len(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// StringX is like String, but panics if an error occurs.
|
||||
func (s *selector) StringX(ctx context.Context) string {
|
||||
v, err := s.String(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Ints returns list of ints from a selector. It is only allowed when selecting one field.
|
||||
func (s *selector) Ints(ctx context.Context) ([]int, error) {
|
||||
if len(*s.flds) > 1 {
|
||||
return nil, errors.New("ent: Ints is not achievable when selecting more than 1 field")
|
||||
}
|
||||
var v []int
|
||||
if err := s.scan(ctx, &v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// IntsX is like Ints, but panics if an error occurs.
|
||||
func (s *selector) IntsX(ctx context.Context) []int {
|
||||
v, err := s.Ints(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Int returns a single int from a selector. It is only allowed when selecting one field.
|
||||
func (s *selector) Int(ctx context.Context) (_ int, err error) {
|
||||
var v []int
|
||||
if v, err = s.Ints(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(v) {
|
||||
case 1:
|
||||
return v[0], nil
|
||||
case 0:
|
||||
err = &NotFoundError{s.label}
|
||||
default:
|
||||
err = fmt.Errorf("ent: Ints returned %d results when one was expected", len(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// IntX is like Int, but panics if an error occurs.
|
||||
func (s *selector) IntX(ctx context.Context) int {
|
||||
v, err := s.Int(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Float64s returns list of float64s from a selector. It is only allowed when selecting one field.
|
||||
func (s *selector) Float64s(ctx context.Context) ([]float64, error) {
|
||||
if len(*s.flds) > 1 {
|
||||
return nil, errors.New("ent: Float64s is not achievable when selecting more than 1 field")
|
||||
}
|
||||
var v []float64
|
||||
if err := s.scan(ctx, &v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// Float64sX is like Float64s, but panics if an error occurs.
|
||||
func (s *selector) Float64sX(ctx context.Context) []float64 {
|
||||
v, err := s.Float64s(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Float64 returns a single float64 from a selector. It is only allowed when selecting one field.
|
||||
func (s *selector) Float64(ctx context.Context) (_ float64, err error) {
|
||||
var v []float64
|
||||
if v, err = s.Float64s(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(v) {
|
||||
case 1:
|
||||
return v[0], nil
|
||||
case 0:
|
||||
err = &NotFoundError{s.label}
|
||||
default:
|
||||
err = fmt.Errorf("ent: Float64s returned %d results when one was expected", len(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Float64X is like Float64, but panics if an error occurs.
|
||||
func (s *selector) Float64X(ctx context.Context) float64 {
|
||||
v, err := s.Float64(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Bools returns list of bools from a selector. It is only allowed when selecting one field.
|
||||
func (s *selector) Bools(ctx context.Context) ([]bool, error) {
|
||||
if len(*s.flds) > 1 {
|
||||
return nil, errors.New("ent: Bools is not achievable when selecting more than 1 field")
|
||||
}
|
||||
var v []bool
|
||||
if err := s.scan(ctx, &v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// BoolsX is like Bools, but panics if an error occurs.
|
||||
func (s *selector) BoolsX(ctx context.Context) []bool {
|
||||
v, err := s.Bools(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Bool returns a single bool from a selector. It is only allowed when selecting one field.
|
||||
func (s *selector) Bool(ctx context.Context) (_ bool, err error) {
|
||||
var v []bool
|
||||
if v, err = s.Bools(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(v) {
|
||||
case 1:
|
||||
return v[0], nil
|
||||
case 0:
|
||||
err = &NotFoundError{s.label}
|
||||
default:
|
||||
err = fmt.Errorf("ent: Bools returned %d results when one was expected", len(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BoolX is like Bool, but panics if an error occurs.
|
||||
func (s *selector) BoolX(ctx context.Context) bool {
|
||||
v, err := s.Bool(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// withHooks invokes the builder operation with the given hooks, if any.
|
||||
func withHooks[V Value, M any, PM interface {
|
||||
*M
|
||||
Mutation
|
||||
}](ctx context.Context, exec func(context.Context) (V, error), mutation PM, hooks []Hook) (value V, err error) {
|
||||
if len(hooks) == 0 {
|
||||
return exec(ctx)
|
||||
}
|
||||
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
|
||||
mutationT, ok := any(m).(PM)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected mutation type %T", m)
|
||||
}
|
||||
// Set the mutation to the builder.
|
||||
*mutation = *mutationT
|
||||
return exec(ctx)
|
||||
})
|
||||
for i := len(hooks) - 1; i >= 0; i-- {
|
||||
if hooks[i] == nil {
|
||||
return value, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)")
|
||||
}
|
||||
mut = hooks[i](mut)
|
||||
}
|
||||
v, err := mut.Mutate(ctx, mutation)
|
||||
if err != nil {
|
||||
return value, err
|
||||
}
|
||||
nv, ok := v.(V)
|
||||
if !ok {
|
||||
return value, fmt.Errorf("unexpected node type %T returned from %T", v, mutation)
|
||||
}
|
||||
return nv, nil
|
||||
}
|
||||
|
||||
// setContextOp returns a new context with the given QueryContext attached (including its op) in case it does not exist.
|
||||
func setContextOp(ctx context.Context, qc *QueryContext, op string) context.Context {
|
||||
if ent.QueryFromContext(ctx) == nil {
|
||||
qc.Op = op
|
||||
ctx = ent.NewQueryContext(ctx, qc)
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
func querierAll[V Value, Q interface {
|
||||
sqlAll(context.Context, ...queryHook) (V, error)
|
||||
}]() Querier {
|
||||
return QuerierFunc(func(ctx context.Context, q Query) (Value, error) {
|
||||
query, ok := q.(Q)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected query type %T", q)
|
||||
}
|
||||
return query.sqlAll(ctx)
|
||||
})
|
||||
}
|
||||
|
||||
func querierCount[Q interface {
|
||||
sqlCount(context.Context) (int, error)
|
||||
}]() Querier {
|
||||
return QuerierFunc(func(ctx context.Context, q Query) (Value, error) {
|
||||
query, ok := q.(Q)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected query type %T", q)
|
||||
}
|
||||
return query.sqlCount(ctx)
|
||||
})
|
||||
}
|
||||
|
||||
func withInterceptors[V Value](ctx context.Context, q Query, qr Querier, inters []Interceptor) (v V, err error) {
|
||||
for i := len(inters) - 1; i >= 0; i-- {
|
||||
qr = inters[i].Intercept(qr)
|
||||
}
|
||||
rv, err := qr.Query(ctx, q)
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
vt, ok := rv.(V)
|
||||
if !ok {
|
||||
return v, fmt.Errorf("unexpected type %T returned from %T. expected type: %T", vt, q, v)
|
||||
}
|
||||
return vt, nil
|
||||
}
|
||||
|
||||
func scanWithInterceptors[Q1 ent.Query, Q2 interface {
|
||||
sqlScan(context.Context, Q1, any) error
|
||||
}](ctx context.Context, rootQuery Q1, selectOrGroup Q2, inters []Interceptor, v any) error {
|
||||
rv := reflect.ValueOf(v)
|
||||
var qr Querier = QuerierFunc(func(ctx context.Context, q Query) (Value, error) {
|
||||
query, ok := q.(Q1)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected query type %T", q)
|
||||
}
|
||||
if err := selectOrGroup.sqlScan(ctx, query, v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if k := rv.Kind(); k == reflect.Pointer && rv.Elem().CanInterface() {
|
||||
return rv.Elem().Interface(), nil
|
||||
}
|
||||
return v, nil
|
||||
})
|
||||
for i := len(inters) - 1; i >= 0; i-- {
|
||||
qr = inters[i].Intercept(qr)
|
||||
}
|
||||
vv, err := qr.Query(ctx, rootQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch rv2 := reflect.ValueOf(vv); {
|
||||
case rv.IsNil(), rv2.IsNil(), rv.Kind() != reflect.Pointer:
|
||||
case rv.Type() == rv2.Type():
|
||||
rv.Elem().Set(rv2.Elem())
|
||||
case rv.Elem().Type() == rv2.Type():
|
||||
rv.Elem().Set(rv2)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// queryHook describes an internal hook for the different sqlAll methods.
|
||||
type queryHook func(context.Context, *sqlgraph.QuerySpec)
|
||||
84
internal/ent/enttest/enttest.go
Normal file
84
internal/ent/enttest/enttest.go
Normal file
@@ -0,0 +1,84 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package enttest
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/holos-run/holos/internal/ent"
|
||||
// required by schema hooks.
|
||||
_ "github.com/holos-run/holos/internal/ent/runtime"
|
||||
|
||||
"entgo.io/ent/dialect/sql/schema"
|
||||
"github.com/holos-run/holos/internal/ent/migrate"
|
||||
)
|
||||
|
||||
type (
|
||||
// TestingT is the interface that is shared between
|
||||
// testing.T and testing.B and used by enttest.
|
||||
TestingT interface {
|
||||
FailNow()
|
||||
Error(...any)
|
||||
}
|
||||
|
||||
// Option configures client creation.
|
||||
Option func(*options)
|
||||
|
||||
options struct {
|
||||
opts []ent.Option
|
||||
migrateOpts []schema.MigrateOption
|
||||
}
|
||||
)
|
||||
|
||||
// WithOptions forwards options to client creation.
|
||||
func WithOptions(opts ...ent.Option) Option {
|
||||
return func(o *options) {
|
||||
o.opts = append(o.opts, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
// WithMigrateOptions forwards options to auto migration.
|
||||
func WithMigrateOptions(opts ...schema.MigrateOption) Option {
|
||||
return func(o *options) {
|
||||
o.migrateOpts = append(o.migrateOpts, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
func newOptions(opts []Option) *options {
|
||||
o := &options{}
|
||||
for _, opt := range opts {
|
||||
opt(o)
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
// Open calls ent.Open and auto-run migration.
|
||||
func Open(t TestingT, driverName, dataSourceName string, opts ...Option) *ent.Client {
|
||||
o := newOptions(opts)
|
||||
c, err := ent.Open(driverName, dataSourceName, o.opts...)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.FailNow()
|
||||
}
|
||||
migrateSchema(t, c, o)
|
||||
return c
|
||||
}
|
||||
|
||||
// NewClient calls ent.NewClient and auto-run migration.
|
||||
func NewClient(t TestingT, opts ...Option) *ent.Client {
|
||||
o := newOptions(opts)
|
||||
c := ent.NewClient(o.opts...)
|
||||
migrateSchema(t, c, o)
|
||||
return c
|
||||
}
|
||||
func migrateSchema(t TestingT, c *ent.Client, o *options) {
|
||||
tables, err := schema.CopyTables(migrate.Tables)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.FailNow()
|
||||
}
|
||||
if err := migrate.Create(context.Background(), c.Schema, tables, o.migrateOpts...); err != nil {
|
||||
t.Error(err)
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
3
internal/ent/generate.go
Normal file
3
internal/ent/generate.go
Normal file
@@ -0,0 +1,3 @@
|
||||
package ent
|
||||
|
||||
//go:generate go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert ./schema
|
||||
211
internal/ent/hook/hook.go
Normal file
211
internal/ent/hook/hook.go
Normal file
@@ -0,0 +1,211 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package hook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/holos-run/holos/internal/ent"
|
||||
)
|
||||
|
||||
// The OrganizationFunc type is an adapter to allow the use of ordinary
|
||||
// function as Organization mutator.
|
||||
type OrganizationFunc func(context.Context, *ent.OrganizationMutation) (ent.Value, error)
|
||||
|
||||
// Mutate calls f(ctx, m).
|
||||
func (f OrganizationFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
|
||||
if mv, ok := m.(*ent.OrganizationMutation); ok {
|
||||
return f(ctx, mv)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.OrganizationMutation", m)
|
||||
}
|
||||
|
||||
// The UserFunc type is an adapter to allow the use of ordinary
|
||||
// function as User mutator.
|
||||
type UserFunc func(context.Context, *ent.UserMutation) (ent.Value, error)
|
||||
|
||||
// Mutate calls f(ctx, m).
|
||||
func (f UserFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
|
||||
if mv, ok := m.(*ent.UserMutation); ok {
|
||||
return f(ctx, mv)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.UserMutation", m)
|
||||
}
|
||||
|
||||
// Condition is a hook condition function.
|
||||
type Condition func(context.Context, ent.Mutation) bool
|
||||
|
||||
// And groups conditions with the AND operator.
|
||||
func And(first, second Condition, rest ...Condition) Condition {
|
||||
return func(ctx context.Context, m ent.Mutation) bool {
|
||||
if !first(ctx, m) || !second(ctx, m) {
|
||||
return false
|
||||
}
|
||||
for _, cond := range rest {
|
||||
if !cond(ctx, m) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Or groups conditions with the OR operator.
|
||||
func Or(first, second Condition, rest ...Condition) Condition {
|
||||
return func(ctx context.Context, m ent.Mutation) bool {
|
||||
if first(ctx, m) || second(ctx, m) {
|
||||
return true
|
||||
}
|
||||
for _, cond := range rest {
|
||||
if cond(ctx, m) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Not negates a given condition.
|
||||
func Not(cond Condition) Condition {
|
||||
return func(ctx context.Context, m ent.Mutation) bool {
|
||||
return !cond(ctx, m)
|
||||
}
|
||||
}
|
||||
|
||||
// HasOp is a condition testing mutation operation.
|
||||
func HasOp(op ent.Op) Condition {
|
||||
return func(_ context.Context, m ent.Mutation) bool {
|
||||
return m.Op().Is(op)
|
||||
}
|
||||
}
|
||||
|
||||
// HasAddedFields is a condition validating `.AddedField` on fields.
|
||||
func HasAddedFields(field string, fields ...string) Condition {
|
||||
return func(_ context.Context, m ent.Mutation) bool {
|
||||
if _, exists := m.AddedField(field); !exists {
|
||||
return false
|
||||
}
|
||||
for _, field := range fields {
|
||||
if _, exists := m.AddedField(field); !exists {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// HasClearedFields is a condition validating `.FieldCleared` on fields.
|
||||
func HasClearedFields(field string, fields ...string) Condition {
|
||||
return func(_ context.Context, m ent.Mutation) bool {
|
||||
if exists := m.FieldCleared(field); !exists {
|
||||
return false
|
||||
}
|
||||
for _, field := range fields {
|
||||
if exists := m.FieldCleared(field); !exists {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// HasFields is a condition validating `.Field` on fields.
|
||||
func HasFields(field string, fields ...string) Condition {
|
||||
return func(_ context.Context, m ent.Mutation) bool {
|
||||
if _, exists := m.Field(field); !exists {
|
||||
return false
|
||||
}
|
||||
for _, field := range fields {
|
||||
if _, exists := m.Field(field); !exists {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// If executes the given hook under condition.
|
||||
//
|
||||
// hook.If(ComputeAverage, And(HasFields(...), HasAddedFields(...)))
|
||||
func If(hk ent.Hook, cond Condition) ent.Hook {
|
||||
return func(next ent.Mutator) ent.Mutator {
|
||||
return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) {
|
||||
if cond(ctx, m) {
|
||||
return hk(next).Mutate(ctx, m)
|
||||
}
|
||||
return next.Mutate(ctx, m)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// On executes the given hook only for the given operation.
|
||||
//
|
||||
// hook.On(Log, ent.Delete|ent.Create)
|
||||
func On(hk ent.Hook, op ent.Op) ent.Hook {
|
||||
return If(hk, HasOp(op))
|
||||
}
|
||||
|
||||
// Unless skips the given hook only for the given operation.
|
||||
//
|
||||
// hook.Unless(Log, ent.Update|ent.UpdateOne)
|
||||
func Unless(hk ent.Hook, op ent.Op) ent.Hook {
|
||||
return If(hk, Not(HasOp(op)))
|
||||
}
|
||||
|
||||
// FixedError is a hook returning a fixed error.
|
||||
func FixedError(err error) ent.Hook {
|
||||
return func(ent.Mutator) ent.Mutator {
|
||||
return ent.MutateFunc(func(context.Context, ent.Mutation) (ent.Value, error) {
|
||||
return nil, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Reject returns a hook that rejects all operations that match op.
|
||||
//
|
||||
// func (T) Hooks() []ent.Hook {
|
||||
// return []ent.Hook{
|
||||
// Reject(ent.Delete|ent.Update),
|
||||
// }
|
||||
// }
|
||||
func Reject(op ent.Op) ent.Hook {
|
||||
hk := FixedError(fmt.Errorf("%s operation is not allowed", op))
|
||||
return On(hk, op)
|
||||
}
|
||||
|
||||
// Chain acts as a list of hooks and is effectively immutable.
|
||||
// Once created, it will always hold the same set of hooks in the same order.
|
||||
type Chain struct {
|
||||
hooks []ent.Hook
|
||||
}
|
||||
|
||||
// NewChain creates a new chain of hooks.
|
||||
func NewChain(hooks ...ent.Hook) Chain {
|
||||
return Chain{append([]ent.Hook(nil), hooks...)}
|
||||
}
|
||||
|
||||
// Hook chains the list of hooks and returns the final hook.
|
||||
func (c Chain) Hook() ent.Hook {
|
||||
return func(mutator ent.Mutator) ent.Mutator {
|
||||
for i := len(c.hooks) - 1; i >= 0; i-- {
|
||||
mutator = c.hooks[i](mutator)
|
||||
}
|
||||
return mutator
|
||||
}
|
||||
}
|
||||
|
||||
// Append extends a chain, adding the specified hook
|
||||
// as the last ones in the mutation flow.
|
||||
func (c Chain) Append(hooks ...ent.Hook) Chain {
|
||||
newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks))
|
||||
newHooks = append(newHooks, c.hooks...)
|
||||
newHooks = append(newHooks, hooks...)
|
||||
return Chain{newHooks}
|
||||
}
|
||||
|
||||
// Extend extends a chain, adding the specified chain
|
||||
// as the last ones in the mutation flow.
|
||||
func (c Chain) Extend(chain Chain) Chain {
|
||||
return c.Append(chain.hooks...)
|
||||
}
|
||||
64
internal/ent/migrate/migrate.go
Normal file
64
internal/ent/migrate/migrate.go
Normal file
@@ -0,0 +1,64 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"entgo.io/ent/dialect"
|
||||
"entgo.io/ent/dialect/sql/schema"
|
||||
)
|
||||
|
||||
var (
|
||||
// WithGlobalUniqueID sets the universal ids options to the migration.
|
||||
// If this option is enabled, ent migration will allocate a 1<<32 range
|
||||
// for the ids of each entity (table).
|
||||
// Note that this option cannot be applied on tables that already exist.
|
||||
WithGlobalUniqueID = schema.WithGlobalUniqueID
|
||||
// WithDropColumn sets the drop column option to the migration.
|
||||
// If this option is enabled, ent migration will drop old columns
|
||||
// that were used for both fields and edges. This defaults to false.
|
||||
WithDropColumn = schema.WithDropColumn
|
||||
// WithDropIndex sets the drop index option to the migration.
|
||||
// If this option is enabled, ent migration will drop old indexes
|
||||
// that were defined in the schema. This defaults to false.
|
||||
// Note that unique constraints are defined using `UNIQUE INDEX`,
|
||||
// and therefore, it's recommended to enable this option to get more
|
||||
// flexibility in the schema changes.
|
||||
WithDropIndex = schema.WithDropIndex
|
||||
// WithForeignKeys enables creating foreign-key in schema DDL. This defaults to true.
|
||||
WithForeignKeys = schema.WithForeignKeys
|
||||
)
|
||||
|
||||
// Schema is the API for creating, migrating and dropping a schema.
|
||||
type Schema struct {
|
||||
drv dialect.Driver
|
||||
}
|
||||
|
||||
// NewSchema creates a new schema client.
|
||||
func NewSchema(drv dialect.Driver) *Schema { return &Schema{drv: drv} }
|
||||
|
||||
// Create creates all schema resources.
|
||||
func (s *Schema) Create(ctx context.Context, opts ...schema.MigrateOption) error {
|
||||
return Create(ctx, s, Tables, opts...)
|
||||
}
|
||||
|
||||
// Create creates all table resources using the given schema driver.
|
||||
func Create(ctx context.Context, s *Schema, tables []*schema.Table, opts ...schema.MigrateOption) error {
|
||||
migrate, err := schema.NewMigrate(s.drv, opts...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ent/migrate: %w", err)
|
||||
}
|
||||
return migrate.Create(ctx, tables...)
|
||||
}
|
||||
|
||||
// WriteTo writes the schema changes to w instead of running them against the database.
|
||||
//
|
||||
// if err := client.Schema.WriteTo(context.Background(), os.Stdout); err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
func (s *Schema) WriteTo(ctx context.Context, w io.Writer, opts ...schema.MigrateOption) error {
|
||||
return Create(ctx, &Schema{drv: &schema.WriteDriver{Writer: w, Driver: s.drv}}, Tables, opts...)
|
||||
}
|
||||
49
internal/ent/migrate/schema.go
Normal file
49
internal/ent/migrate/schema.go
Normal file
@@ -0,0 +1,49 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"entgo.io/ent/dialect/sql/schema"
|
||||
"entgo.io/ent/schema/field"
|
||||
)
|
||||
|
||||
var (
|
||||
// OrganizationsColumns holds the columns for the "organizations" table.
|
||||
OrganizationsColumns = []*schema.Column{
|
||||
{Name: "id", Type: field.TypeUUID},
|
||||
{Name: "created_at", Type: field.TypeTime},
|
||||
{Name: "updated_at", Type: field.TypeTime},
|
||||
{Name: "name", Type: field.TypeString, Unique: true},
|
||||
{Name: "display_name", Type: field.TypeString},
|
||||
}
|
||||
// OrganizationsTable holds the schema information for the "organizations" table.
|
||||
OrganizationsTable = &schema.Table{
|
||||
Name: "organizations",
|
||||
Columns: OrganizationsColumns,
|
||||
PrimaryKey: []*schema.Column{OrganizationsColumns[0]},
|
||||
}
|
||||
// UsersColumns holds the columns for the "users" table.
|
||||
UsersColumns = []*schema.Column{
|
||||
{Name: "id", Type: field.TypeUUID},
|
||||
{Name: "created_at", Type: field.TypeTime},
|
||||
{Name: "updated_at", Type: field.TypeTime},
|
||||
{Name: "email", Type: field.TypeString, Unique: true},
|
||||
{Name: "iss", Type: field.TypeString},
|
||||
{Name: "sub", Type: field.TypeString},
|
||||
{Name: "name", Type: field.TypeString},
|
||||
}
|
||||
// UsersTable holds the schema information for the "users" table.
|
||||
UsersTable = &schema.Table{
|
||||
Name: "users",
|
||||
Columns: UsersColumns,
|
||||
PrimaryKey: []*schema.Column{UsersColumns[0]},
|
||||
}
|
||||
// Tables holds all the tables in the schema.
|
||||
Tables = []*schema.Table{
|
||||
OrganizationsTable,
|
||||
UsersTable,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
}
|
||||
1127
internal/ent/mutation.go
Normal file
1127
internal/ent/mutation.go
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user